Reputation: 3029
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
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
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
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