web-dev-qa-db-ja.com

Gmakeマクロ展開:マクロは引数に変数を指定してマクロを呼び出します

次のmakeffileでは、1つのマクロプロセスが別のマクロを呼び出すための引数です。以下のmakefileは、2つのターゲットと、$ TARGETS内のターゲットの正しいリストを生成することを期待しています。しかし実際には、正しいリストを持つターゲットを1つだけ生成します。そのようなマクロ呼び出しを正しい方法で行う方法は?

 all:$ TARGETS 
 define f2 
。PHONY:target $(1)
 target $(1):
 echo "私たちは$(1) "
 TARGETS + = target $(1)
 endef 
 
 define f1 
 VAR $(1)= ValueWith $(1 )
 $(eval $(call f2、$$(VAR $(1))))
 endef 
 
 $(eval $(call f1、CallOne ))
 $(eval $(call f1、CallTwo))
 
 $(警告警告:$(TARGETS))

makeの出力:

 test.mk:16:警告:ターゲット `target 'のレシピを上書きします
 test.mk:15:警告:ターゲット` target'の古いレシピを無視します
 test.mk: 18:警告:targetValueWithCallOne targetValueWithCallTwo 
 gmake:「すべて」に対して何もする必要はありません。
1
gena2x

さらにデバッグコードを追加しましょう。

all: $TARGETS
define f2
$$(info f2 called on $(1))
.PHONY: target$(1)
target$(1):
    echo "We are in $(1)"
TARGETS+=target$(1)
endef

define f1
VAR$(1)=ValueWith$(1)
$(info too early: VAR$(1) is $$(VAR$(1)))
$$(info right time: VAR$(1) is $$(VAR$(1)))
$(eval $(call f2,$(VAR$(1))))
endef

$(eval $(call f1,CallOne))
$(eval $(call f1,CallTwo))

$(warning Warning: $(TARGETS))

出力:

too early: VARCallOne is $(VARCallOne)
f2 called on 
right time: VARCallOne is ValueWithCallOne
too early: VARCallTwo is $(VARCallTwo)
f2 called on 
debug.mk:18: warning: overriding commands for target `target'
debug.mk:17: warning: ignoring old commands for target `target'
right time: VARCallTwo is ValueWithCallTwo
debug.mk:20: Warning: target target
make: *** No rule to make target `ARGETS', needed by `all'.  Stop.

問題は、関数VAR…が展開されたとき、その展開の結果が処理されたときではなく、f1の定義の前にeval呼び出しが行われることです。 evalを遅らせる必要があります。

また、1行目にタイプミスがあります。修正すると、ターゲットallは使用時に定義されていないため、ターゲットTARGETSは何もビルドしないことがわかります。後で依存関係を宣言する必要があります。

all:  # default target, declare it first

define f2
.PHONY: target$(1)
target$(1):
        echo "We are in $(1)"
TARGETS+=target$(1)
endef

define f1
VAR$(1)=ValueWith$(1)
$$(eval $$(call f2,$$(VAR$(1))))
endef

$(eval $(call f1,CallOne))
$(eval $(call f1,CallTwo))

$(warning Warning: $(TARGETS))
all: $(TARGETS)