Previously we learned that GNU make
works in two distinct phases: a read-in phase and a target-update phase (see How make
Reads a Makefile). GNU make also has the ability to enable a second expansion of the prerequisites (only) for some or all targets defined in the makefile. In order for this second expansion to occur, the special target .SECONDEXPANSION
must be defined before the first prerequisite list that makes use of this feature.
If that special target is defined then in between the two phases mentioned above, right at the end of the read-in phase, all the prerequisites of the targets defined after the special target are expanded a second time. In most circumstances this secondary expansion will have no effect, since all variable and function references will have been expanded during the initial parsing of the makefiles. In order to take advantage of the secondary expansion phase of the parser, then, it’s necessary to escape the variable or function reference in the makefile. In this case the first expansion merely un-escapes the reference but doesn’t expand it, and expansion is left to the secondary expansion phase. For example, consider this makefile:
.SECONDEXPANSION: ONEVAR = onefile TWOVAR = twofile myfile: $(ONEVAR) $$(TWOVAR)
After the first expansion phase the prerequisites list of the myfile target will be onefile
and $(TWOVAR)
; the first (unescaped) variable reference to ONEVAR is expanded, while the second (escaped) variable reference is simply unescaped, without being recognized as a variable reference. Now during the secondary expansion the first word is expanded again but since it contains no variable or function references it remains the value onefile, while the second word is now a normal reference to the variable TWOVAR, which is expanded to the value twofile. The final result is that there are two prerequisites, onefile and twofile.
Obviously, this is not a very interesting case since the same result could more easily have been achieved simply by having both variables appear, unescaped, in the prerequisites list. One difference becomes apparent if the variables are reset; consider this example:
.SECONDEXPANSION: AVAR = top onefile: $(AVAR) twofile: $$(AVAR) AVAR = bottom
Here the prerequisite of onefile will be expanded immediately, and resolve to the value top, while the prerequisite of twofile will not be full expanded until the secondary expansion and yield a value of bottom.
This is marginally more exciting, but the true power of this feature only becomes apparent when you discover that secondary expansions always take place within the scope of the automatic variables for that target. This means that you can use variables such as $@
, $*
, etc. during the second expansion and they will have their expected values, just as in the recipe. All you have to do is defer the expansion by escaping the $
. Also, secondary expansion occurs for both explicit and implicit (pattern) rules. Knowing this, the possible uses for this feature increase dramatically. For example:
.SECONDEXPANSION: main_OBJS := main.o try.o test.o lib_OBJS := lib.o api.o main lib: $$($$@_OBJS)
Here, after the initial expansion the prerequisites of both the main and lib targets will be $($@_OBJS)
. During the secondary expansion, the $@
variable is set to the name of the target and so the expansion for the main target will yield $(main_OBJS)
, or main.o try.o test.o
, while the secondary expansion for the lib target will yield $(lib_OBJS)
, or lib.o api.o
.
You can also mix in functions here, as long as they are properly escaped:
main_SRCS := main.c try.c test.c lib_SRCS := lib.c api.c .SECONDEXPANSION: main lib: $$(patsubst %.c,%.o,$$($$@_SRCS))
This version allows users to specify source files rather than object files, but gives the same resulting prerequisites list as the previous example.
Evaluation of automatic variables during the secondary expansion phase, especially of the target name variable $$@
, behaves similarly to evaluation within recipes. However, there are some subtle differences and “corner cases” which come into play for the different types of rule definitions that make
understands. The subtleties of using the different automatic variables are described below.
During the secondary expansion of explicit rules, $$@
and $$%
evaluate, respectively, to the file name of the target and, when the target is an archive member, the target member name. The $$<
variable evaluates to the first prerequisite in the first rule for this target. $$^
and $$+
evaluate to the list of all prerequisites of rules that have already appeared for the same target ($$+
with repetitions and $$^
without). The following example will help illustrate these behaviors:
.SECONDEXPANSION: foo: foo.1 bar.1 $$< $$^ $$+ # line #1 foo: foo.2 bar.2 $$< $$^ $$+ # line #2 foo: foo.3 bar.3 $$< $$^ $$+ # line #3
In the first prerequisite list, all three variables ($$<
, $$^
, and $$+
) expand to the empty string. In the second, they will have values foo.1
, foo.1 bar.1
, and foo.1 bar.1
respectively. In the third they will have values foo.1
, foo.1 bar.1 foo.2 bar.2
, and foo.1 bar.1
foo.2 bar.2 foo.1 foo.1 bar.1 foo.1 bar.1
respectively.
Rules undergo secondary expansion in makefile order, except that the rule with the recipe is always evaluated last.
The variables $$?
and $$*
are not available and expand to the empty string.
Rules for secondary expansion of static pattern rules are identical to those for explicit rules, above, with one exception: for static pattern rules the $$*
variable is set to the pattern stem. As with explicit rules, $$?
is not available and expands to the empty string.
As make
searches for an implicit rule, it substitutes the stem and then performs secondary expansion for every rule with a matching target pattern. The value of the automatic variables is derived in the same fashion as for static pattern rules. As an example:
.SECONDEXPANSION: foo: bar foo foz: fo%: bo% %oo: $$< $$^ $$+ $$*
When the implicit rule is tried for target foo, $$<
expands to bar, $$^
expands to bar boo, $$+
also expands to bar boo, and $$*
expands to f.
Note that the directory prefix (D), as described in Implicit Rule Search Algorithm, is appended (after expansion) to all the patterns in the prerequisites list. As an example:
.SECONDEXPANSION: /tmp/foo.o: %.o: $$(addsuffix /%.c,foo bar) foo.h @echo $^
The prerequisite list printed, after the secondary expansion and directory prefix reconstruction, will be /tmp/foo/foo.c /tmp/bar/foo.c foo.h. If you are not interested in this reconstruction, you can use $$*
instead of %
in the prerequisites list.
Copyright © 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Free Software Foundation, Inc.
Licensed under the GNU Free Documentation License.
https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html