help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Variable expansion question


From: Sébastien Hinderer
Subject: Re: Variable expansion question
Date: Wed, 26 Oct 2022 15:43:41 +0200

Hey Paul,

Many thakns for your response, precious and helpful as usual.

Paul Smith (2022/10/24 12:33 -0400):
> 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".

Okay. Actually in the original Makefile (which is more complex than what
I showed above) I had added the ".SECONDEXPANSION:" target so because of
that and the doubled dollars I thought I did use secondary expansion
already but I realise with your repsonse that this was a wrong
assumption of mine. But then, just to make sure, is it because of eval
that all the double dollars were necessary? Because I think I wrote the
macro in the simplest way possible and it would not have worked if I had
used less dollars than I did, right?

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

Ah, many thanks for explaining all this and reminding the info debugging
trick, I find both points very useful.

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

Okay, makes sense. Except that I'd rather not impose any particular
style to the users of the macro.

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

Is it necessary to use a variable, here? If I wanted to change the
content of the macro itself so that secondary expansion takes place,
woudlnt it be enough to just add two more addition $ signs at the outer
level, so something like

$(1): $$$$($$(basename $$(notdir $(1)))_OBJECTS:=.o)

Thanks,

Sébastien.

>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]