1 # $NetBSD: var-op-expand.mk,v 1.11 2021/01/01 23:07:48 sjg Exp $
3 # Tests for the := variable assignment operator, which expands its
6 .MAKE.SAVE_DOLLARS:= yes
8 # If the right-hand side does not contain a dollar sign, the ':=' assignment
9 # operator has the same effect as the '=' assignment operator.
15 # When a ':=' assignment is performed, its right-hand side is evaluated and
16 # expanded as far as possible. Contrary to other situations, '$$' and
17 # variable expressions based on undefined variables are preserved though.
19 # Whether a variable expression is undefined or not is determined at the end
20 # of evaluating the expression. The consequence is that ${:Ufallback} expands
21 # to "fallback"; initially this expression is undefined since it is based on
22 # the variable named "", which is guaranteed to be never defined, but at the
23 # end of evaluating the expression ${:Ufallback}, the modifier ':U' has turned
24 # the expression into a defined expression.
27 # literal dollar signs
28 VAR:= $$ $$$$ $$$$$$$$
29 .if ${VAR} != "\$ \$\$ \$\$\$\$"
34 # reference to a variable containing a literal dollar sign
38 .if ${VAR} != "\$ \$\$ \$\$\$\$"
43 # reference to an undefined variable
47 .if ${VAR} != "<after>"
52 # reference to a variable whose name is computed from another variable
57 .if ${VAR} != "referred to"
62 # expression with an indirect modifier referring to an undefined variable
66 .if ${VAR} != "was undefined"
71 # expression with an indirect modifier referring to another variable that
72 # in turn refers to an undefined variable
74 # XXX: Even though this is a ':=' assignment, the '${UNDEF}' in the part of
75 # the variable modifier is not preserved. To preserve it, ParseModifierPart
76 # would have to call VarSubstExpr somehow since this is the only piece of
77 # code that takes care of this global variable.
90 # In variable assignments using the ':=' operator, undefined variables are
91 # preserved, no matter how indirectly they are referenced.
97 .if ${VAR} != "<too late>"
102 # In variable assignments using the ':=' operator, '$$' are preserved, no
103 # matter how indirectly they are referenced.
105 REF= REF:$$ $$$$ ${REF2}
106 VAR:= VAR:$$ $$$$ ${REF}
107 .if ${VAR} != "VAR:\$ \$\$ REF:\$ \$\$ REF2:\$ \$\$"
112 # In variable assignments using the ':=' operator, '$$' are preserved in the
113 # expressions of the top level, but not in expressions that are nested.
114 VAR:= top:$$ ${:Unest1\:\$\$} ${:Unest2${:U\:\$\$}}
115 .if ${VAR} != "top:\$ nest1:\$ nest2:\$"
120 # In variable assignments using the ':=' operator, there may be expressions
121 # containing variable modifiers, and these modifiers may refer to other
122 # variables. These referred-to variables are expanded at the time of
123 # assignment. The undefined variables are kept as-is and are later expanded
124 # when evaluating the condition.
126 # Contrary to the assignment operator '=', the assignment operator ':='
127 # consumes the '$' from modifier parts.
128 REF.word= 1:$$ 2:$$$$ 4:$$$$$$$$
130 VAR:= ${:Uword undef:@word@${REF.${word}}@}, direct: ${REF.word} ${REF.undef}
132 REF.undef= undef.after
133 .if ${VAR} != "1:2:\$ 4:\$\$ undef.after, direct: 1:\$ 2:\$\$ 4:\$\$\$\$ undef.after"
137 # Just for comparison, the previous example using the assignment operator '='
138 # instead of ':='. The right-hand side of the assignment is not evaluated at
139 # the time of assignment but only later, when ${VAR} appears in the condition.
141 # At that point, both REF.word and REF.undef are defined.
142 REF.word= 1:$$ 2:$$$$ 4:$$$$$$$$
144 VAR= ${:Uword undef:@word@${REF.${word}}@}, direct: ${REF.word} ${REF.undef}
146 REF.undef= undef.after
147 .if ${VAR} != "word.after undef.after, direct: word.after undef.after"
152 # Between var.c 1.42 from 2000-05-11 and before parse.c 1.520 from 2020-12-27,
153 # if the variable name in a ':=' assignment referred to an undefined variable,
154 # there were actually 2 assignments to different variables:
156 # Global["VAR_SUBST_${UNDEF}"] = ""
157 # Global["VAR_SUBST_"] = ""
159 # The variable name with the empty value actually included a dollar sign.
160 # Variable names with dollars are not used in practice.
162 # It might be a good idea to forbid undefined variables on the left-hand side
163 # of a variable assignment.
165 VAR_ASSIGN_${UNDEF}= assigned by '='
166 VAR_SUBST_${UNDEF}:= assigned by ':='
167 .if ${VAR_ASSIGN_} != "assigned by '='"
170 .if defined(${:UVAR_SUBST_\${UNDEF\}})
173 .if ${VAR_SUBST_} != "assigned by ':='"