Thomas Ellin
Thomas Ellin

Reputation: 35

Makefile variable expansion not working as expected

I want to auto-create makefile rules based on a variable list (in my use case a set of files which I want to selectively build). However I have issues expanding the names.

I have created the following Makefile as an example (M(not)WE):

FILES_A=a1 a2 a3
FILES_B=b1 b2 b3
TARGET_BASES=A B

define test
  FILES := $(value FILES_$1)
  build_$1: $(addsuffix .ext, $(FILES))
  build_dummy_$1: $(FILES)
endef

$(foreach target, $(TARGET_BASES), $(eval $(call test,$(target))))

Running make -p|grep build I would expect the following output:

[...]
build_A: a1.ext a2.ext a3.ext
build_dummy_A: a1 a2 a3
build_B: b1.ext b2.ext b3.ext
build_dummy_B: b1 b2 b3

but instead I get

build_A:
build_dummy_A:
build_B: a1.ext a2.ext a3.ext
build_dummy_B: a1 a2 a3

and I do not know why. Can somebody shed some light on what I am missing here?

Upvotes: 2

Views: 232

Answers (1)

MadScientist
MadScientist

Reputation: 101051

Understanding expansion around eval and call can be confusing. That's why they're considered advanced items which should only be used if none of the simpler to understand facilities will solve the problem.

The issue here is that your macro test is evaluated first by the call function, before being passed to the eval function. During that evaluation, the variable FILES is not not set yet and so it resolves to whatever it was set to the last time the eval ran: the first time it evaluates to empty and the second time it evaluates to the result after the first run, etc.

Basically the rule is that any variable you want to be expanded by call should have only one $, and any variable you want to be expanded by the eval needs to be escaped with $$. So:

define test
  FILES := $$(value FILES_$1)
  build_$1: $$(addsuffix .ext, $$(FILES))
  build_dummy_$1: $$(FILES)
endef

Upvotes: 3

Related Questions