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