This section describes some advanced features you can use to reference variables in more flexible ways.
6.3.1 Substitution References
Asubstitution referencesubstitutes the value of a variable with alterations that you specify. It has the form ‘$(var:a=b)’ (or ‘${var:a=b}’) and its meaning is to take the value of the variable var, replace every a at the end of a word with b in that value, and substitute the resulting string.
When we say “at the end of a word”, we mean that a must appear either followed by whitespace or at the end of the value in order to be replaced; other occurrences of ain the value are unaltered. For example:
foo := a.o b.o c.o bar := $(foo:.o=.c)
sets ‘bar’ to ‘a.c b.c c.c’. See Section 6.5 [Setting Variables], page 65.
A substitution reference is actually an abbreviation for use of the patsubstexpansion function (see Section 8.2 [Functions for String Substitution and Analysis], page 84). We provide substitution references as well aspatsubstfor compatibility with other implemen- tations ofmake.
Another type of substitution reference lets you use the full power of thepatsubstfunc- tion. It has the same form ‘$(var:a=b)’ described above, except that nowamust contain a single ‘%’ character. This case is equivalent to ‘$(patsubsta,b,$(var))’. See Section 8.2 [Functions for String Substitution and Analysis], page 84, for a description of thepatsubst function.
For example:
foo := a.o b.o c.o bar := $(foo:%.o=%.c) sets ‘bar’ to ‘a.c b.c c.c’.
6.3.2 Computed Variable Names
Computed variable names are a complicated concept needed only for sophisticated makefile programming. For most purposes you need not consider them, except to know that making a variable with a dollar sign in its name might have strange results. However, if you are the type that wants to understand everything, or you are actually interested in what they do, read on.
Variables may be referenced inside the name of a variable. This is called a computed variable name or a nested variable reference. For example,
x = y y = z
a := $($(x))
defines aas ‘z’: the ‘$(x)’ inside ‘$($(x))’ expands to ‘y’, so ‘$($(x))’ expands to ‘$(y)’ which in turn expands to ‘z’. Here the name of the variable to reference is not stated explicitly; it is computed by expansion of ‘$(x)’. The reference ‘$(x)’ here is nested within the outer variable reference.
The previous example shows two levels of nesting, but any number of levels is possible. For example, here are three levels:
x = y y = z z = u
a := $($($(x)))
Here the innermost ‘$(x)’ expands to ‘y’, so ‘$($(x))’ expands to ‘$(y)’ which in turn expands to ‘z’; now we have ‘$(z)’, which becomes ‘u’.
References to recursively-expanded variables within a variable name are re-expanded in the usual fashion. For example:
x = $(y) y = z z = Hello a := $($(x))
defines a as ‘Hello’: ‘$($(x))’ becomes ‘$($(y))’ which becomes ‘$(z)’ which becomes ‘Hello’.
Nested variable references can also contain modified references and function invocations (see Chapter 8 [Functions for Transforming Text], page 83), just like any other reference. For example, using the subst function (see Section 8.2 [Functions for String Substitution and Analysis], page 84):
x = variable1 variable2 := Hello y = $(subst 1,2,$(x)) z = y
a := $($($(z)))
eventually definesaas ‘Hello’. It is doubtful that anyone would ever want to write a nested reference as convoluted as this one, but it works: ‘$($($(z)))’ expands to ‘$($(y))’ which becomes ‘$($(subst 1,2,$(x)))’. This gets the value ‘variable1’ from xand changes it by substitution to ‘variable2’, so that the entire string becomes ‘$(variable2)’, a simple variable reference whose value is ‘Hello’.
A computed variable name need not consist entirely of a single variable reference. It can contain several variable references, as well as some invariant text. For example,
a_dirs := dira dirb 1_dirs := dir1 dir2 a_files := filea fileb 1_files := file1 file2 ifeq "$(use_a)" "yes" a1 := a
else a1 := 1 endif
ifeq "$(use_dirs)" "yes" df := dirs
else
df := files endif
dirs := $($(a1)_$(df))
will give dirs the same value as a_dirs, 1_dirs, a_files or 1_files depending on the settings of use_aand use_dirs.
Computed variable names can also be used in substitution references: a_objects := a.o b.o c.o
1_objects := 1.o 2.o 3.o
sources := $($(a1)_objects:.o=.c)
defines sourcesas either ‘a.c b.c c.c’ or ‘1.c 2.c 3.c’, depending on the value ofa1. The only restriction on this sort of use of nested variable references is that they cannot specify part of the name of a function to be called. This is because the test for a recognized function name is done before the expansion of nested references. For example,
ifdef do_sort func := sort else func := strip endif bar := a d b g q c
foo := $($(func) $(bar))
attempts to give ‘foo’ the value of the variable ‘sort a d b g q c’ or ‘strip a d b g q c’, rather than giving ‘a d b g q c’ as the argument to either the sort or thestrip function. This restriction could be removed in the future if that change is shown to be a good idea.
You can also use computed variable names in the left-hand side of a variable assignment, or in a definedirective, as in:
dir = foo
$(dir)_sources := $(wildcard $(dir)/*.c) define $(dir)_print =
lpr $($(dir)_sources) endef
This example defines the variables ‘dir’, ‘foo_sources’, and ‘foo_print’.
Note that nested variable references are quite different from recursively expanded vari- ables (see Section 6.2 [The Two Flavors of Variables], page 60), though both are used together in complex ways when doing makefile programming.