1# $NetBSD: var-op-default.mk,v 1.5 2023/11/19 22:32:44 rillig Exp $
2#
3# Tests for the ?= variable assignment operator, which only assigns
4# if the variable is still undefined.
5
6# The variable VAR is not defined yet.  Therefore it gets the default value
7# from the variable assignment.
8VAR?=		default value
9.if ${VAR} != "default value"
10.  error
11.endif
12
13# At this point, the variable 'VAR' is already defined.  The '?=' therefore
14# ignores the new variable value, preserving the previous "default value".
15VAR?=		ignored
16.if ${VAR} != "default value"
17.  error
18.endif
19
20# The '?=' operator only checks whether the variable is defined or not.
21# An empty variable is defined, therefore the '?=' operator does nothing.
22EMPTY=		# empty
23EMPTY?=		ignored
24.if ${EMPTY} != ""
25.  error
26.endif
27
28# The .for loop is described in the manual page as if it would operate on
29# variables.  This is not entirely true.  Instead, each occurrence of an
30# expression $i or ${i} or ${i:...} is substituted with ${:Uloop-value}.
31# This comes very close to the description, the only difference is that
32# there is never an actual variable named 'i' involved.
33#
34# Because there is not really a variable named 'i', the '?=' operator
35# performs the variable assignment, resulting in $i == "default".
36.for i in loop-value
37i?=		default
38.endfor
39.if ${i} != "default"
40.  error
41.endif
42
43# At the point where the '?=' operator checks whether the variable exists,
44# it expands the variable name exactly once.  Therefore both 'VAR.param'
45# and 'VAR.${param}' expand to 'VAR.param', and the second '?=' assignment
46# has no effect.
47#
48# Since 2000.05.11.07.43.42 it has been possible to use nested
49# expressions in variable names, which made make much more versatile.
50# On 2008.03.31.00.12.21, this particular case of the '?=' operator has been
51# fixed.  Before, the '?=' operator had not expanded the variable name
52# 'VAR.${:Uparam}' to see whether the variable already existed.  Since that
53# variable didn't exist (and variables with '$' in their name are particularly
54# fragile), the variable assignment with "not used" was performed, and only
55# during that, the variable name was expanded.
56VAR.param=		already defined
57VAR.${:Uparam}?=	not used
58.if ${VAR.param} != "already defined"
59.  error
60.endif
61
62# Now demonstrate that the variable name is indeed expanded exactly once.
63# This is tricky to measure correctly since there are many inconsistencies
64# in and around the code that expands expressions in the various
65# places where expressions can occur.  If in doubt, enable the
66# following debug flags to see what happens:
67#.MAKEFLAGS: -dcpv
68EXPAND_NAME=		EXPAND.$$$$	# The full variable name is EXPAND.$$
69PARAM=			$$$$
70EXPAND.${PARAM}?=	value with param
71.if ${${EXPAND_NAME}} != "value with param"
72.  error
73.endif
74.MAKEFLAGS: -d0
75
76all:
77	@:;
78