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