1*9f45a3c8SSimon J. Gerraty# $NetBSD: var-scope-cmdline.mk,v 1.1 2022/01/23 16:25:54 rillig Exp $ 2*9f45a3c8SSimon J. Gerraty# 3*9f45a3c8SSimon J. Gerraty# Tests for variables specified on the command line. 4*9f45a3c8SSimon J. Gerraty# 5*9f45a3c8SSimon J. Gerraty# Variables that are specified on the command line override those from the 6*9f45a3c8SSimon J. Gerraty# global scope. 7*9f45a3c8SSimon J. Gerraty# 8*9f45a3c8SSimon J. Gerraty# For performance reasons, the actual implementation is more complex than the 9*9f45a3c8SSimon J. Gerraty# above single-sentence rule, in order to avoid unnecessary lookups in scopes, 10*9f45a3c8SSimon J. Gerraty# which before var.c 1.586 from 2020-10-25 calculated the hash value of the 11*9f45a3c8SSimon J. Gerraty# variable name once for each lookup. Instead, when looking up the value of 12*9f45a3c8SSimon J. Gerraty# a variable, the search often starts in the global scope since that is where 13*9f45a3c8SSimon J. Gerraty# most of the variables are stored. This conflicts with the statement that 14*9f45a3c8SSimon J. Gerraty# variables from the cmdline scope override global variables, since after the 15*9f45a3c8SSimon J. Gerraty# common case of finding a variable in the global scope, another lookup would 16*9f45a3c8SSimon J. Gerraty# be needed in the cmdline scope to ensure that there is no overriding 17*9f45a3c8SSimon J. Gerraty# variable there. 18*9f45a3c8SSimon J. Gerraty# 19*9f45a3c8SSimon J. Gerraty# Instead of this costly lookup scheme, make implements it in a different 20*9f45a3c8SSimon J. Gerraty# way: 21*9f45a3c8SSimon J. Gerraty# 22*9f45a3c8SSimon J. Gerraty# Whenever a global variable is created, this creation is ignored if 23*9f45a3c8SSimon J. Gerraty# there is a cmdline variable of the same name. 24*9f45a3c8SSimon J. Gerraty# 25*9f45a3c8SSimon J. Gerraty# Whenever a cmdline variable is created, any global variable of the 26*9f45a3c8SSimon J. Gerraty# same name is deleted. 27*9f45a3c8SSimon J. Gerraty# 28*9f45a3c8SSimon J. Gerraty# Whenever a global variable is deleted, nothing special happens. 29*9f45a3c8SSimon J. Gerraty# 30*9f45a3c8SSimon J. Gerraty# Deleting a cmdline variable is not possible. 31*9f45a3c8SSimon J. Gerraty# 32*9f45a3c8SSimon J. Gerraty# These 4 rules provide the guarantee that whenever a global variable exists, 33*9f45a3c8SSimon J. Gerraty# there cannot be a cmdline variable of the same name. Therefore, after 34*9f45a3c8SSimon J. Gerraty# finding a variable in the global scope, no additional lookup is needed in 35*9f45a3c8SSimon J. Gerraty# the cmdline scope. 36*9f45a3c8SSimon J. Gerraty# 37*9f45a3c8SSimon J. Gerraty# The above ruleset provides the same guarantees as the simple rule "cmdline 38*9f45a3c8SSimon J. Gerraty# overrides global". Due to an implementation mistake, the actual behavior 39*9f45a3c8SSimon J. Gerraty# was not entirely equivalent to the simple rule though. The mistake was 40*9f45a3c8SSimon J. Gerraty# that when a cmdline variable with '$$' in its name was added, a global 41*9f45a3c8SSimon J. Gerraty# variable was deleted, but not with the exact same name as the cmdline 42*9f45a3c8SSimon J. Gerraty# variable. Instead, the name of the global variable was expanded one more 43*9f45a3c8SSimon J. Gerraty# time than the name of the cmdline variable. For variable names that didn't 44*9f45a3c8SSimon J. Gerraty# have a '$$' in their name, it was implemented correctly all the time. 45*9f45a3c8SSimon J. Gerraty# 46*9f45a3c8SSimon J. Gerraty# The bug was added in var.c 1.183 on 2013-07-16, when Var_Set called 47*9f45a3c8SSimon J. Gerraty# Var_Delete to delete the global variable. Just two months earlier, in var.c 48*9f45a3c8SSimon J. Gerraty# 1.174 from 2013-05-18, Var_Delete had started to expand the variable name. 49*9f45a3c8SSimon J. Gerraty# Together, these two changes made the variable name be expanded twice in a 50*9f45a3c8SSimon J. Gerraty# row. This bug was fixed in var.c 1.835 from 2021-02-22. 51*9f45a3c8SSimon J. Gerraty# 52*9f45a3c8SSimon J. Gerraty# Another bug was the wrong assumption that "deleting a cmdline variable is 53*9f45a3c8SSimon J. Gerraty# not possible". Deleting such a variable has been possible since var.c 1.204 54*9f45a3c8SSimon J. Gerraty# from 2016-02-19, when the variable modifier ':@' started to delete the 55*9f45a3c8SSimon J. Gerraty# temporary loop variable after finishing the loop. It was probably not 56*9f45a3c8SSimon J. Gerraty# intended back then that a side effect of this seemingly simple change was 57*9f45a3c8SSimon J. Gerraty# that both global and cmdline variables could now be undefined at will as a 58*9f45a3c8SSimon J. Gerraty# side effect of evaluating a variable expression. As of 2021-02-23, this is 59*9f45a3c8SSimon J. Gerraty# still possible. 60*9f45a3c8SSimon J. Gerraty# 61*9f45a3c8SSimon J. Gerraty# Most cmdline variables are set at the very beginning, when parsing the 62*9f45a3c8SSimon J. Gerraty# command line arguments. Using the special target '.MAKEFLAGS', it is 63*9f45a3c8SSimon J. Gerraty# possible to set cmdline variables at any later time. 64*9f45a3c8SSimon J. Gerraty 65*9f45a3c8SSimon J. Gerraty# A normal global variable, without any cmdline variable nearby. 66*9f45a3c8SSimon J. GerratyVAR= global 67*9f45a3c8SSimon J. Gerraty.info ${VAR} 68*9f45a3c8SSimon J. Gerraty 69*9f45a3c8SSimon J. Gerraty# The global variable is "overridden" by simply deleting it and then 70*9f45a3c8SSimon J. Gerraty# installing the cmdline variable instead. Since there is no obvious way to 71*9f45a3c8SSimon J. Gerraty# undefine a cmdline variable, there is no need to remember the old value 72*9f45a3c8SSimon J. Gerraty# of the global variable could become visible again. 73*9f45a3c8SSimon J. Gerraty# 74*9f45a3c8SSimon J. Gerraty# See varmod-loop.mk for a non-obvious way to undefine a cmdline variable. 75*9f45a3c8SSimon J. Gerraty.MAKEFLAGS: VAR=makeflags 76*9f45a3c8SSimon J. Gerraty.info ${VAR} 77*9f45a3c8SSimon J. Gerraty 78*9f45a3c8SSimon J. Gerraty# If Var_SetWithFlags should ever forget to delete the global variable, 79*9f45a3c8SSimon J. Gerraty# the below line would print "global" instead of the current "makeflags". 80*9f45a3c8SSimon J. Gerraty.MAKEFLAGS: -V VAR 81