varmisc.mk revision 1.31 1 # $NetBSD: varmisc.mk,v 1.31 2021/11/30 23:52:19 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 strftime cmpv manok
7 all: save-dollars
8 all: export-appended
9 all: parse-dynamic
10 all: varerror-unclosed
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 April1= 1459494000
50
51 # slightly contorted syntax to use utc via variable
52 strftime:
53 @echo ${year=%Y month=%m day=%d:L:gmtime=1459494000}
54 @echo date=${%Y%m%d:L:${gmtime=${April1}:L}}
55
56 # big jumps to handle 3 digits per step
57 M_cmpv.units= 1 1000 1000000
58 M_cmpv= S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh
59
60 Version= 123.456.789
61 cmpv.only= target specific vars
62
63 cmpv:
64 @echo Version=${Version} == ${Version:${M_cmpv}}
65 @echo Literal=3.4.5 == ${3.4.5:L:${M_cmpv}}
66 @echo We have ${${.TARGET:T}.only}
67
68 # catch mishandling of nested variables in .for loop
69 MAN=
70 MAN1= make.1
71 .for s in 1 2
72 . if defined(MAN$s) && !empty(MAN$s)
73 MAN+= ${MAN$s}
74 . endif
75 .endfor
76
77 manok:
78 @echo MAN=${MAN}
79
80 # Test parsing of boolean values.
81 # begin .MAKE.SAVE_DOLLARS; see Var_SetWithFlags and ParseBoolean.
82 SD_VALUES= 0 1 2 False True false true Yes No yes no On Off ON OFF on off
83 SD_4_DOLLARS= $$$$
84
85 .for val in ${SD_VALUES}
86 .MAKE.SAVE_DOLLARS:= ${val} # Must be := since a simple '=' has no effect.
87 SD.${val}:= ${SD_4_DOLLARS}
88 .endfor
89 .MAKE.SAVE_DOLLARS:= yes
90
91 save-dollars:
92 .for val in ${SD_VALUES}
93 @printf '%s: %-8s = %s\n' $@ ${val} ${SD.${val}:Q}
94 .endfor
95 # end .MAKE.SAVE_DOLLARS
96
97 # Appending to an undefined variable does not add a space in front.
98 .undef APPENDED
99 APPENDED+= value
100 .if ${APPENDED} != "value"
101 . error "${APPENDED}"
102 .endif
103
104 # Appending to an empty variable adds a space between the old value
105 # and the additional value.
106 APPENDED= # empty
107 APPENDED+= value
108 .if ${APPENDED} != " value"
109 . error "${APPENDED}"
110 .endif
111
112 # Appending to parameterized variables works as well.
113 PARAM= param
114 VAR.${PARAM}= 1
115 VAR.${PARAM}+= 2
116 .if ${VAR.param} != "1 2"
117 . error "${VAR.param}"
118 .endif
119
120 # The variable name can contain arbitrary characters.
121 # If the expanded variable name ends in a +, this still does not influence
122 # the parser. The assignment operator is still a simple assignment.
123 # Therefore, there is no need to add a space between the variable name
124 # and the assignment operator.
125 PARAM= +
126 VAR.${PARAM}= 1
127 VAR.${PARAM}+= 2
128 .if ${VAR.+} != "1 2"
129 . error "${VAR.+}"
130 .endif
131 .for param in + ! ?
132 VAR.${param}= ${param}
133 .endfor
134 .if ${VAR.+} != "+" || ${VAR.!} != "!" || ${VAR.?} != "?"
135 . error "${VAR.+}" "${VAR.!}" "${VAR.?}"
136 .endif
137
138 # Appending to a variable from the environment creates a copy of that variable
139 # in the global scope.
140 # The appended value is not exported automatically.
141 # When a variable is exported, the exported value is taken at the time of the
142 # .export directive. Later changes to the variable have no effect.
143 .export FROM_ENV_BEFORE
144 FROM_ENV+= mk
145 FROM_ENV_BEFORE+= mk
146 FROM_ENV_AFTER+= mk
147 .export FROM_ENV_AFTER
148
149 export-appended:
150 @echo $@: "$$FROM_ENV"
151 @echo $@: "$$FROM_ENV_BEFORE"
152 @echo $@: "$$FROM_ENV_AFTER"
153
154 # begin parse-dynamic
155 #
156 # Demonstrate that the target-specific variables are not evaluated in
157 # the global scope. Their expressions are preserved until there is a local
158 # scope in which resolving them makes sense.
159
160 # There are different code paths for short names ...
161 ${:U>}= before
162 GS_TARGET:= $@
163 GS_MEMBER:= $%
164 GS_PREFIX:= $*
165 GS_ARCHIVE:= $!
166 GS_ALLSRC:= $>
167 ${:U>}= after
168 # ... and for braced short names ...
169 GB_TARGET:= ${@}
170 GB_MEMBER:= ${%}
171 GB_PREFIX:= ${*}
172 GB_ARCHIVE:= ${!}
173 GB_ALLSRC:= ${>}
174 # ... and for long names.
175 GL_TARGET:= ${.TARGET}
176 GL_MEMBER:= ${.MEMBER}
177 GL_PREFIX:= ${.PREFIX}
178 GL_ARCHIVE:= ${.ARCHIVE}
179 GL_ALLSRC:= ${.ALLSRC}
180
181 parse-dynamic:
182 @echo $@: ${GS_TARGET} ${GS_MEMBER} ${GS_PREFIX} ${GS_ARCHIVE} ${GS_ALLSRC}
183 @echo $@: ${GB_TARGET} ${GB_MEMBER} ${GB_PREFIX} ${GB_ARCHIVE} ${GB_ALLSRC}
184 @echo $@: ${GL_TARGET} ${GL_MEMBER} ${GL_PREFIX} ${GL_ARCHIVE} ${GL_ALLSRC}
185
186 # Since 2020-07-28, make complains about unclosed variables.
187 # Before that, it had complained about unclosed variables only when
188 # parsing the modifiers, but not when parsing the variable name.
189
190 UNCLOSED_INDIR_1= ${UNCLOSED_ORIG
191 UNCLOSED_INDIR_2= ${UNCLOSED_INDIR_1}
192
193 FLAGS= one two
194 FLAGS+= ${FLAGS.${.ALLSRC:M*.c:T:u}}
195 FLAGS.target2.c= three four
196
197 target1.c:
198 target2.c:
199
200 all: target1-flags target2-flags
201 target1-flags: target1.c
202 @echo $@: we have: ${FLAGS}
203
204 target2-flags: target2.c
205 @echo $@: we have: ${FLAGS}
206
207 varerror-unclosed:
208 @echo $@:begin
209 @echo $(
210 @echo $(UNCLOSED
211 @echo ${UNCLOSED
212 @echo ${UNCLOSED:M${PATTERN
213 @echo ${UNCLOSED.${param
214 @echo $
215 .for i in 1 2 3
216 @echo ${UNCLOSED.${i}
217 .endfor
218 @echo ${UNCLOSED_INDIR_2}
219 @echo $@:end
220