varmisc.mk revision 1.37 1 # $NetBSD: varmisc.mk,v 1.37 2024/08/29 20:20:36 rillig Exp $
2 #
3 # Miscellaneous variable tests.
4
5 all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none \
6 cmpv
7 all: save-dollars
8 all: export-appended
9 all: parse-dynamic
10 all: varerror-unclosed-{1,2,3,4,5,6,7,8}
11
12 unmatched_var_paren:
13 @echo ${foo::=foo-text}
14
15 True= ${echo true >&2:L:sh}TRUE
16 False= ${echo false >&2:L:sh}FALSE
17
18 VSET= is set
19 .undef UNDEF
20
21 U_false:
22 @echo :U skipped when var set
23 @echo ${VSET:U${False}}
24
25 D_false:
26 @echo :D skipped if var undef
27 @echo ${UNDEF:D${False}}
28
29 U_true:
30 @echo :U expanded when var undef
31 @echo ${UNDEF:U${True}}
32
33 D_true:
34 @echo :D expanded when var set
35 @echo ${VSET:D${True}}
36
37 Q_lhs:
38 @echo :? only lhs when value true
39 @echo ${1:L:?${True}:${False}}
40
41 Q_rhs:
42 @echo :? only rhs when value false
43 @echo ${0:L:?${True}:${False}}
44
45 NQ_none:
46 @echo do not evaluate or expand :? if discarding
47 @echo ${VSET:U${1:L:?${True}:${False}}}
48
49 # big jumps to handle 3 digits per step
50 M_cmpv.units= 1 1000 1000000
51 M_cmpv= S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh
52
53 Version= 123.456.789
54 cmpv.only= target specific vars
55
56 cmpv:
57 @echo Version=${Version} == ${Version:${M_cmpv}}
58 @echo Literal=3.4.5 == ${3.4.5:L:${M_cmpv}}
59 @echo We have ${${.TARGET:T}.only}
60
61
62 # Test parsing of boolean values.
63 # begin .MAKE.SAVE_DOLLARS; see Var_SetWithFlags and ParseBoolean.
64 SD_VALUES= 0 1 2 False True false true Yes No yes no On Off ON OFF on off
65 SD_4_DOLLARS= $$$$
66
67 .for val in ${SD_VALUES}
68 # The assignment must be done using ':=' since a simple '=' would be
69 # interpreted as 'yes', due to the leading '$'; see ParseBoolean.
70 .MAKE.SAVE_DOLLARS:= ${val}
71 SD.${val}:= ${SD_4_DOLLARS}
72 .endfor
73 .MAKE.SAVE_DOLLARS:= yes
74
75 save-dollars:
76 .for val in ${SD_VALUES}
77 @printf '%s: %-8s = %s\n' $@ ${val} ${SD.${val}:Q}
78 .endfor
79 # end .MAKE.SAVE_DOLLARS
80
81 # Appending to an undefined variable does not add a space in front.
82 .undef APPENDED
83 APPENDED+= value
84 .if ${APPENDED} != "value"
85 . error "${APPENDED}"
86 .endif
87
88 # Appending to an empty variable adds a space between the old value
89 # and the additional value.
90 APPENDED= # empty
91 APPENDED+= value
92 .if ${APPENDED} != " value"
93 . error "${APPENDED}"
94 .endif
95
96 # Appending to parameterized variables works as well.
97 PARAM= param
98 VAR.${PARAM}= 1
99 VAR.${PARAM}+= 2
100 .if ${VAR.param} != "1 2"
101 . error "${VAR.param}"
102 .endif
103
104 # The variable name can contain arbitrary characters.
105 # If the expanded variable name ends in a +, this still does not influence
106 # the parser. The assignment operator is still a simple assignment.
107 # Therefore, there is no need to add a space between the variable name
108 # and the assignment operator.
109 PARAM= +
110 VAR.${PARAM}= 1
111 VAR.${PARAM}+= 2
112 .if ${VAR.+} != "1 2"
113 . error "${VAR.+}"
114 .endif
115 .for param in : + ! ?
116 VAR.${param}= ${param}
117 .endfor
118 .if ${VAR.${:U\:}} != ":" || ${VAR.+} != "+" || ${VAR.!} != "!" || ${VAR.?} != "?"
119 . error "${VAR.+}" "${VAR.!}" "${VAR.?}"
120 .endif
121
122 # Appending to a variable from the environment creates a copy of that variable
123 # in the global scope.
124 # The appended value is not exported automatically.
125 # When a variable is exported, the exported value is taken at the time of the
126 # .export directive. Later changes to the variable have no effect.
127 .export FROM_ENV_BEFORE
128 FROM_ENV+= mk
129 FROM_ENV_BEFORE+= mk
130 FROM_ENV_AFTER+= mk
131 .export FROM_ENV_AFTER
132
133 export-appended:
134 @echo $@: "$$FROM_ENV"
135 @echo $@: "$$FROM_ENV_BEFORE"
136 @echo $@: "$$FROM_ENV_AFTER"
137
138 # begin parse-dynamic
139 #
140 # Demonstrate that the target-specific variables are not evaluated in
141 # the global scope. Their expressions are preserved until there is a local
142 # scope in which resolving them makes sense.
143
144 # There are different code paths for short names ...
145 ${:U>}= before
146 GS_TARGET:= $@
147 GS_MEMBER:= $%
148 GS_PREFIX:= $*
149 GS_ARCHIVE:= $!
150 GS_ALLSRC:= $>
151 ${:U>}= after
152 # ... and for braced short names ...
153 GB_TARGET:= ${@}
154 GB_MEMBER:= ${%}
155 GB_PREFIX:= ${*}
156 GB_ARCHIVE:= ${!}
157 GB_ALLSRC:= ${>}
158 # ... and for long names.
159 GL_TARGET:= ${.TARGET}
160 GL_MEMBER:= ${.MEMBER}
161 GL_PREFIX:= ${.PREFIX}
162 GL_ARCHIVE:= ${.ARCHIVE}
163 GL_ALLSRC:= ${.ALLSRC}
164
165 parse-dynamic:
166 @echo $@: ${GS_TARGET} ${GS_MEMBER} ${GS_PREFIX} ${GS_ARCHIVE} ${GS_ALLSRC}
167 @echo $@: ${GB_TARGET} ${GB_MEMBER} ${GB_PREFIX} ${GB_ARCHIVE} ${GB_ALLSRC}
168 @echo $@: ${GL_TARGET} ${GL_MEMBER} ${GL_PREFIX} ${GL_ARCHIVE} ${GL_ALLSRC}
169
170 # Since 2020-07-28, make complains about unclosed variables.
171 # Before that, it had complained about unclosed variables only when
172 # parsing the modifiers, but not when parsing the variable name.
173
174 UNCLOSED_INDIR_1= ${UNCLOSED_ORIG
175 UNCLOSED_INDIR_2= ${UNCLOSED_INDIR_1}
176
177 FLAGS= one two
178 FLAGS+= ${FLAGS.${.ALLSRC:M*.c:T:u}}
179 FLAGS.target2.c= three four
180
181 target1.c:
182 target2.c:
183
184 all: target1-flags target2-flags
185 target1-flags: target1.c
186 @echo $@: we have: ${FLAGS}
187
188 target2-flags: target2.c
189 @echo $@: we have: ${FLAGS}
190
191 varerror-unclosed-1:
192 @echo $@:begin
193 varerror-unclosed-2:
194 # expect: make: Unclosed variable ""
195 @echo $(
196 varerror-unclosed-3:
197 # expect: make: Unclosed variable "UNCLOSED"
198 @echo $(UNCLOSED
199 varerror-unclosed-4:
200 # expect: make: Unclosed variable "UNCLOSED"
201 @echo ${UNCLOSED
202 varerror-unclosed-5:
203 # expect: make: Unclosed expression, expecting '}' for modifier "M${PATTERN"
204 @echo ${UNCLOSED:M${PATTERN
205 varerror-unclosed-6:
206 # expect: make: Unclosed variable "param"
207 # expect: make: Unclosed variable "UNCLOSED."
208 @echo ${UNCLOSED.${param
209 varerror-unclosed-7:
210 @echo $
211 .for i in 1 2 3
212 # expect: make: Unclosed variable "UNCLOSED.1"
213 @echo ${UNCLOSED.${i}
214 .endfor
215 varerror-unclosed-8:
216 @echo ${UNCLOSED_INDIR_2}
217 @echo $@:end
218