Alexander Gromnitsky
Alexander Gromnitsky

Reputation: 3029

GNU Make recursively expanded variables examples

Could somebody provide a real-world example of using recursively expanded variables (REV)? In the docs or various blog posts people give only useless toy examples, like

foo = $(bar)
bar = $(ugh)
ugh = Huh?

I cannot find a real use for REV besides creating custom functions with $(call). I also found that in the past people were using REV to supply additional parameters to a compiler for specific targets but that trick is considered outdated now because GNU Make has target-specific variables.

Upvotes: 2

Views: 9290

Answers (3)

Ryan de Kwaadsteniet
Ryan de Kwaadsteniet

Reputation: 13

It just means that recursively defined variables are set at the time of definition only!

The best example I can find is this

x := foo 
y := $(x) bar 
x := later

and is equivalent to

y := foo bar
x := later

Upvotes: 1

Etan Reisner
Etan Reisner

Reputation: 80931

Both recursively expanded variables and simply expanded variables recurse their expansions. The major difference is when that expansion happens.

So your example above works just fine with simply expanded variables if you invert the assignments:

ugh := Huh?
bar := $(ugh)
foo := $(bar)

So the major thing that recursively expanded variables get you is the freedom to assign values in whatever order you need (which means you don't need to worry about inclusion order for included makefiles, etc.).

In a project at work we have a dozen or so included makefiles that have inter-dependent relationships. These are expressed through the usage of known-format variable names (e.g. module A generates an A_provides variable, etc.) Modules that need to utilize the things that module A provides can then list $(A_provides) in their makefiles.

With simply expanded variables (which we had been using until somewhat recently) this meant that the inclusion of the generated makefiles required a manually sorted order to force the inclusion of assigning makefiles before consuming makefiles (into other variables).

With recursively expanded variables this order does not matter. (This would not be the case if the variables were used in any immediately evaluated context in these makefiles but luckily they are not, they only set variables that are used later in the main makefiles.)

Upvotes: 8

MadScientist
MadScientist

Reputation: 100836

Well, one simple example are variables which contain commands for recipes; perhaps:

buildc = $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%.o: %.c
        $(buildc)

I probably wouldn't write a compile rule like this this way, but if you have a much more complex recipe it can be very useful.

Personally I don't consider "additional parameters ... for specific targets" (by which I assume you mean recursively defined variables such as $($*_FLAGS)) to be outdated or obsoleted by target-specific variables, by any stretch. If nothing else recursively defined variables are much more portable than target-specific variables.

Upvotes: 2

Related Questions