var-op-default.mk revision 1.5 1 # $NetBSD: var-op-default.mk,v 1.5 2023/11/19 22:32:44 rillig Exp $
2 #
3 # Tests for the ?= variable assignment operator, which only assigns
4 # if the variable is still undefined.
5
6 # The variable VAR is not defined yet. Therefore it gets the default value
7 # from the variable assignment.
8 VAR?= default value
9 .if ${VAR} != "default value"
10 . error
11 .endif
12
13 # At this point, the variable 'VAR' is already defined. The '?=' therefore
14 # ignores the new variable value, preserving the previous "default value".
15 VAR?= ignored
16 .if ${VAR} != "default value"
17 . error
18 .endif
19
20 # The '?=' operator only checks whether the variable is defined or not.
21 # An empty variable is defined, therefore the '?=' operator does nothing.
22 EMPTY= # empty
23 EMPTY?= ignored
24 .if ${EMPTY} != ""
25 . error
26 .endif
27
28 # The .for loop is described in the manual page as if it would operate on
29 # variables. This is not entirely true. Instead, each occurrence of an
30 # expression $i or ${i} or ${i:...} is substituted with ${:Uloop-value}.
31 # This comes very close to the description, the only difference is that
32 # there is never an actual variable named 'i' involved.
33 #
34 # Because there is not really a variable named 'i', the '?=' operator
35 # performs the variable assignment, resulting in $i == "default".
36 .for i in loop-value
37 i?= default
38 .endfor
39 .if ${i} != "default"
40 . error
41 .endif
42
43 # At the point where the '?=' operator checks whether the variable exists,
44 # it expands the variable name exactly once. Therefore both 'VAR.param'
45 # and 'VAR.${param}' expand to 'VAR.param', and the second '?=' assignment
46 # has no effect.
47 #
48 # Since 2000.05.11.07.43.42 it has been possible to use nested
49 # expressions in variable names, which made make much more versatile.
50 # On 2008.03.31.00.12.21, this particular case of the '?=' operator has been
51 # fixed. Before, the '?=' operator had not expanded the variable name
52 # 'VAR.${:Uparam}' to see whether the variable already existed. Since that
53 # variable didn't exist (and variables with '$' in their name are particularly
54 # fragile), the variable assignment with "not used" was performed, and only
55 # during that, the variable name was expanded.
56 VAR.param= already defined
57 VAR.${:Uparam}?= not used
58 .if ${VAR.param} != "already defined"
59 . error
60 .endif
61
62 # Now demonstrate that the variable name is indeed expanded exactly once.
63 # This is tricky to measure correctly since there are many inconsistencies
64 # in and around the code that expands expressions in the various
65 # places where expressions can occur. If in doubt, enable the
66 # following debug flags to see what happens:
67 #.MAKEFLAGS: -dcpv
68 EXPAND_NAME= EXPAND.$$$$ # The full variable name is EXPAND.$$
69 PARAM= $$$$
70 EXPAND.${PARAM}?= value with param
71 .if ${${EXPAND_NAME}} != "value with param"
72 . error
73 .endif
74 .MAKEFLAGS: -d0
75
76 all:
77 @:;
78