Re: Variable expansion question

Sébastien Hinderer <[email protected]>
Newsgroups gmane.comp.gnu.make.general
Message-ID <[email protected]>
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.

>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.