[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Variable expansion question
From: |
Paul Smith |
Subject: |
Re: Variable expansion question |
Date: |
Mon, 24 Oct 2022 12:33:15 -0400 |
User-agent: |
Evolution 3.46.0 (by Flathub.org)) |
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)