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