xref: /freebsd/contrib/bmake/unit-tests/varmisc.mk (revision 6a7405f5a6b639682cacf01e35d561411ff556aa)
1# $NetBSD: varmisc.mk,v 1.37 2024/08/29 20:20:36 rillig 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	cmpv
7all: save-dollars
8all: export-appended
9all: parse-dynamic
10all: varerror-unclosed-{1,2,3,4,5,6,7,8}
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
49# big jumps to handle 3 digits per step
50M_cmpv.units=	1 1000 1000000
51M_cmpv=		S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh
52
53Version=	123.456.789
54cmpv.only=	target specific vars
55
56cmpv:
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.
64SD_VALUES=	0 1 2 False True false true Yes No yes no On Off ON OFF on off
65SD_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}
71SD.${val}:=		${SD_4_DOLLARS}
72.endfor
73.MAKE.SAVE_DOLLARS:=	yes
74
75save-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
83APPENDED+=	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.
90APPENDED=	# empty
91APPENDED+=	value
92.if ${APPENDED} != " value"
93.  error "${APPENDED}"
94.endif
95
96# Appending to parameterized variables works as well.
97PARAM=		param
98VAR.${PARAM}=	1
99VAR.${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.
109PARAM=		+
110VAR.${PARAM}=	1
111VAR.${PARAM}+=	2
112.if ${VAR.+} != "1 2"
113.  error "${VAR.+}"
114.endif
115.for param in : + ! ?
116VAR.${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
128FROM_ENV+=		mk
129FROM_ENV_BEFORE+=	mk
130FROM_ENV_AFTER+=	mk
131.export FROM_ENV_AFTER
132
133export-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
146GS_TARGET:=	$@
147GS_MEMBER:=	$%
148GS_PREFIX:=	$*
149GS_ARCHIVE:=	$!
150GS_ALLSRC:=	$>
151${:U>}=		after
152# ... and for braced short names ...
153GB_TARGET:=	${@}
154GB_MEMBER:=	${%}
155GB_PREFIX:=	${*}
156GB_ARCHIVE:=	${!}
157GB_ALLSRC:=	${>}
158# ... and for long names.
159GL_TARGET:=	${.TARGET}
160GL_MEMBER:=	${.MEMBER}
161GL_PREFIX:=	${.PREFIX}
162GL_ARCHIVE:=	${.ARCHIVE}
163GL_ALLSRC:=	${.ALLSRC}
164
165parse-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
174UNCLOSED_INDIR_1=	${UNCLOSED_ORIG
175UNCLOSED_INDIR_2=	${UNCLOSED_INDIR_1}
176
177FLAGS=	one two
178FLAGS+=	${FLAGS.${.ALLSRC:M*.c:T:u}}
179FLAGS.target2.c= three four
180
181target1.c:
182target2.c:
183
184all: target1-flags target2-flags
185target1-flags: target1.c
186	@echo $@: we have: ${FLAGS}
187
188target2-flags: target2.c
189	@echo $@: we have: ${FLAGS}
190
191varerror-unclosed-1:
192	@echo $@:begin
193varerror-unclosed-2:
194# expect: make: Unclosed variable ""
195	@echo $(
196varerror-unclosed-3:
197# expect: make: Unclosed variable "UNCLOSED"
198	@echo $(UNCLOSED
199varerror-unclosed-4:
200# expect: make: Unclosed variable "UNCLOSED"
201	@echo ${UNCLOSED
202varerror-unclosed-5:
203# expect: make: Unclosed expression, expecting '}' for modifier "M${PATTERN"
204	@echo ${UNCLOSED:M${PATTERN
205varerror-unclosed-6:
206# expect: make: Unclosed variable "param"
207# expect: make: Unclosed variable "UNCLOSED."
208	@echo ${UNCLOSED.${param
209varerror-unclosed-7:
210	@echo $
211.for i in 1 2 3
212# expect: make: Unclosed variable "UNCLOSED.1"
213	@echo ${UNCLOSED.${i}
214.endfor
215varerror-unclosed-8:
216	@echo ${UNCLOSED_INDIR_2}
217	@echo $@:end
218