Home | History | Annotate | Line # | Download | only in unit-tests
      1  1.4  rillig # $NetBSD: var-scope-cmdline.mk,v 1.4 2023/11/19 21:47:52 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.4  rillig # side effect of evaluating an 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