次の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:「すべて」に対して何もする必要はありません。
さらにデバッグコードを追加しましょう。
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)