1

In the following makeffile one macro process it's arguments to call another macro. I expect that makefile below will generate two targets and correct list of the targets in $TARGETS. But in fact it only generates one target with correct list. How to do such macro call in correct way?

all: $TARGETS
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))

output of make:

test.mk:16: warning: overriding recipe for target `target'
test.mk:15: warning: ignoring old recipe for target `target'
test.mk:18: Warning: targetValueWithCallOne targetValueWithCallTwo
gmake: Nothing to be done for `all'.
1

Let's add some more debugging code.

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))

Output:

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.

The problem is that the eval call is made before the definition of VAR…, at the time the function f1 is expanded, instead of at the time the result of that expansion is processed. You need to delay the eval.

Also there is a typo in line 1; if you fix it, you'll find that the target all builds nothing since TARGETS is not defined at the time it's used. You need to declare the dependencies later.

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)
  • Thank you. I learnt a lot from your explanation and it indeed answers my question. – gena2x Sep 10 '14 at 8:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.