1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
<h1 class="subsection">Computed Variable Names</h1> <p>Computed variable names are an advanced concept, very useful in more sophisticated makefile programming. In simple situations you need not consider them, but they can be extremely useful. </p> <p>Variables may be referenced inside the name of a variable. This is called a <em>computed variable name</em> or a <em>nested variable reference</em>. For example, </p> <div class="example"> <pre class="example">x = y
y = z
a := $($(x))
</pre>
</div> <p>defines <code>a</code> as ‘<samp>z</samp>’: the ‘<samp>$(x)</samp>’ inside ‘<samp>$($(x))</samp>’ expands to ‘<samp>y</samp>’, so ‘<samp>$($(x))</samp>’ expands to ‘<samp>$(y)</samp>’ which in turn expands to ‘<samp>z</samp>’. Here the name of the variable to reference is not stated explicitly; it is computed by expansion of ‘<samp>$(x)</samp>’. The reference ‘<samp>$(x)</samp>’ here is nested within the outer variable reference. </p> <p>The previous example shows two levels of nesting, but any number of levels is possible. For example, here are three levels: </p> <div class="example"> <pre class="example">x = y
y = z
z = u
a := $($($(x)))
</pre>
</div> <p>Here the innermost ‘<samp>$(x)</samp>’ expands to ‘<samp>y</samp>’, so ‘<samp>$($(x))</samp>’ expands to ‘<samp>$(y)</samp>’ which in turn expands to ‘<samp>z</samp>’; now we have ‘<samp>$(z)</samp>’, which becomes ‘<samp>u</samp>’. </p> <p>References to recursively-expanded variables within a variable name are re-expanded in the usual fashion. For example: </p> <div class="example"> <pre class="example">x = $(y)
y = z
z = Hello
a := $($(x))
</pre>
</div> <p>defines <code>a</code> as ‘<samp>Hello</samp>’: ‘<samp>$($(x))</samp>’ becomes ‘<samp>$($(y))</samp>’ which becomes ‘<samp>$(z)</samp>’ which becomes ‘<samp>Hello</samp>’. </p> <p>Nested variable references can also contain modified references and function invocations (see <a href="functions">Functions for Transforming Text</a>), just like any other reference. For example, using the <code>subst</code> function (see <a href="text-functions">Functions for String Substitution and Analysis</a>): </p> <div class="example"> <pre class="example">x = variable1
variable2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z)))
</pre>
</div> <p>eventually defines <code>a</code> as ‘<samp>Hello</samp>’. It is doubtful that anyone would ever want to write a nested reference as convoluted as this one, but it works: ‘<samp>$($($(z)))</samp>’ expands to ‘<samp>$($(y))</samp>’ which becomes ‘<samp>$($(subst 1,2,$(x)))</samp>’. This gets the value ‘<samp>variable1</samp>’ from <code>x</code> and changes it by substitution to ‘<samp>variable2</samp>’, so that the entire string becomes ‘<samp>$(variable2)</samp>’, a simple variable reference whose value is ‘<samp>Hello</samp>’. </p> <p>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, </p> <div class="example"> <pre class="example">a_dirs := dira dirb
1_dirs := dir1 dir2
</pre>
<pre class="example">a_files := filea fileb
1_files := file1 file2
</pre>
<pre class="example">ifeq "$(use_a)" "yes"
a1 := a
else
a1 := 1
endif
</pre>
<pre class="example">ifeq "$(use_dirs)" "yes"
df := dirs
else
df := files
endif
dirs := $($(a1)_$(df))
</pre>
</div> <p>will give <code>dirs</code> the same value as <code>a_dirs</code>, <code>1_dirs</code>, <code>a_files</code> or <code>1_files</code> depending on the settings of <code>use_a</code> and <code>use_dirs</code>. </p> <p>Computed variable names can also be used in substitution references: </p> <div class="example"> <pre class="example">a_objects := a.o b.o c.o
1_objects := 1.o 2.o 3.o
sources := $($(a1)_objects:.o=.c)
</pre>
</div> <p>defines <code>sources</code> as either ‘<samp>a.c b.c c.c</samp>’ or ‘<samp>1.c 2.c 3.c</samp>’, depending on the value of <code>a1</code>. </p> <p>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, </p> <div class="example"> <pre class="example">ifdef do_sort
func := sort
else
func := strip
endif
</pre>
<pre class="example">bar := a d b g q c
</pre>
<pre class="example">foo := $($(func) $(bar))
</pre>
</div> <p>attempts to give ‘<samp>foo</samp>’ the value of the variable ‘<samp>sort a d b g q c</samp>’ or ‘<samp>strip a d b g q c</samp>’, rather than giving ‘<samp>a d b g q c</samp>’ as the argument to either the <code>sort</code> or the <code>strip</code> function. This restriction could be removed in the future if that change is shown to be a good idea. </p> <p>You can also use computed variable names in the left-hand side of a variable assignment, or in a <code>define</code> directive, as in: </p> <div class="example"> <pre class="example">dir = foo
$(dir)_sources := $(wildcard $(dir)/*.c)
define $(dir)_print =
lpr $($(dir)_sources)
endef
</pre>
</div> <p>This example defines the variables ‘<samp>dir</samp>’, ‘<samp>foo_sources</samp>’, and ‘<samp>foo_print</samp>’. </p> <p>Note that <em>nested variable references</em> are quite different from <em>recursively expanded variables</em> (see <a href="flavors">The Two Flavors of Variables</a>), though both are used together in complex ways when doing makefile programming. </p><div class="_attribution">
<p class="_attribution-p">
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, 2021, 2022 Free Software Foundation, Inc. <br>Licensed under the GNU Free Documentation License.<br>
<a href="https://www.gnu.org/software/make/manual/html_node/Computed-Names.html" class="_attribution-link">https://www.gnu.org/software/make/manual/html_node/Computed-Names.html</a>
</p>
</div>
|