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