On Mon, 2022-10-24 at 14:10 +0200, Sébastien Hinderer wrote: > define BUILD_MACRO > $(1): $$($$(basename $$(notdir $(1)))_OBJECTS:=.o) > @echo Building $$@ from $$^ > endef # BUILD_MACRO > > $(foreach PROGRAM, $(PROGRAMS),\ > $(eval $(call BUILD_MACRO,$(PROGRAM)))) > > If progmod1.o and progmod2.o exist, then running `make > tools/prog.exe` displays: > > Building tools/prog.exe from progmod1.o progmod2.o > > Which is what I expect. > > However, if prog_OBJECTS is defined after the call to foreach rather > than before, then the same command ran in the same context says: > > Building tools/prog.exe from > > In other words the evaluated list of prerequisites is empty and I am > wondering why this is so and whether there would be a way to defiine > BUILD_MACRO so that therelative positions of its invocation andthe > definition of the _OBJECTS variables does not matter.
Short answer is "basically, no". Why does this happen? Because the targets and prerequisites of a rule are expanded in "immediate context" which means "as the makefile is read in". So when the makefile is parsed, the foreach loop is expanded, which expands the eval, which expands the call, etc. and the whole thing exists right there in the makefile as if you'd written it out by hand. If you replace the "eval" call in your loop with "info" it will print out the content of the makefile that make will then parse, as if you'd typed it in directly. See for example: https://www.gnu.org/software/make/manual/html_node/Reading-Makefiles.html But the longer answer is "yes there's a way to do it". You need to delay the expansion of the prerequisites until after you're sure that all the *_OBJECTS variables have been set. One straightforward way to do it is to put the foreach etc. into a variable, and expand the variable at the end of the makefile after all possible resetting of *_OBJECTS is complete. Another option is to use secondary expansion; this would require even more escaping than you have above. Probably the easiest thing to do is put the prerequisite into a separate variable and use that, something like this: .SECONDEXPANSION: BUILD_PREREQS = $($(basename $(notdir $@))_OBJECTS:=.o) define BUILD_MACRO $(1): $$$$(BUILD_PREREQS) @echo Building $$@ from $$^ endef # BUILD_MACRO (untested)