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