Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make/unit-tests make: document the history of bugs i...



details:   https://anonhg.NetBSD.org/src/rev/2701fbdbabd6
branches:  trunk
changeset: 959770:2701fbdbabd6
user:      rillig <rillig%NetBSD.org@localhost>
date:      Tue Feb 23 21:59:31 2021 +0000

description:
make: document the history of bugs in "cmdline overrides global"

For performance reasons, the implementation of the simple rule "cmdline
overrides global" grew into code that is much more complicated than a
straight-forward implementation.  This added complexity made it easy for
bugs to sneak in.

diffstat:

 usr.bin/make/unit-tests/var-class-cmdline.exp |   4 +-
 usr.bin/make/unit-tests/var-class-cmdline.mk  |  62 +++++++++++++++++++++++---
 2 files changed, 55 insertions(+), 11 deletions(-)

diffs (85 lines):

diff -r e511bde7c061 -r 2701fbdbabd6 usr.bin/make/unit-tests/var-class-cmdline.exp
--- a/usr.bin/make/unit-tests/var-class-cmdline.exp     Tue Feb 23 21:59:04 2021 +0000
+++ b/usr.bin/make/unit-tests/var-class-cmdline.exp     Tue Feb 23 21:59:31 2021 +0000
@@ -1,4 +1,4 @@
-make: "var-class-cmdline.mk" line 23: global
-make: "var-class-cmdline.mk" line 32: makeflags
+make: "var-class-cmdline.mk" line 67: global
+make: "var-class-cmdline.mk" line 76: makeflags
 makeflags
 exit status 0
diff -r e511bde7c061 -r 2701fbdbabd6 usr.bin/make/unit-tests/var-class-cmdline.mk
--- a/usr.bin/make/unit-tests/var-class-cmdline.mk      Tue Feb 23 21:59:04 2021 +0000
+++ b/usr.bin/make/unit-tests/var-class-cmdline.mk      Tue Feb 23 21:59:31 2021 +0000
@@ -1,18 +1,62 @@
-# $NetBSD: var-class-cmdline.mk,v 1.4 2021/02/23 14:17:21 rillig Exp $
+# $NetBSD: var-class-cmdline.mk,v 1.5 2021/02/23 21:59:31 rillig Exp $
 #
 # Tests for variables specified on the command line.
 #
 # Variables that are specified on the command line override those from the
 # global scope.
 #
-# For performance reasons, variable lookup often starts in the global scope
-# since that is where most practically used variables are stored.  But even
-# in these cases, variables from the command line scope must override the
-# global variables.  Therefore, whenever a global variable is tried to be
-# set, it is ignored when there is already a variable of the same name in
-# the cmdline scope.  In the same vein, when a cmdline variable is set and
-# there is already a variable of the same name in the global scope, that
-# global variable is deleted first.
+# For performance reasons, the actual implementation is more complex than the
+# above single-sentence rule, in order to avoid unnecessary lookups in scopes,
+# which before var.c 1.586 from 2020-10-25 calculated the hash value of the
+# variable name once for each lookup.  Instead, when looking up the value of
+# a variable, the search often starts in the global scope since that is where
+# most of the variables are stored.  This conflicts with the statement that
+# variables from the cmdline scope override global variables, since after the
+# common case of finding a variable in the global scope, another lookup would
+# be needed in the cmdline scope to ensure that there is no overriding
+# variable there.
+#
+# Instead of this costly lookup scheme, make implements it in a different
+# way:
+#
+#      Whenever a global variable is created, this creation is ignored if
+#      there is a cmdline variable of the same name.
+#
+#      Whenever a cmdline variable is created, any global variable of the
+#      same name is deleted.
+#
+#      Whenever a global variable is deleted, nothing special happens.
+#
+#      Deleting a cmdline variable is not possible.
+#
+# These 4 rules provide the guarantee that whenever a global variable exists,
+# there cannot be a cmdline variable of the same name.  Therefore, after
+# finding a variable in the global scope, no additional lookup is needed in
+# the cmdline scope.
+#
+# The above ruleset provides the same guarantees as the simple rule "cmdline
+# overrides global".  Due to an implementation mistake, the actual behavior
+# was not entirely equivalent to the simple rule though.  The mistake was
+# that when a cmdline variable with '$$' in its name was added, a global
+# variable was deleted, but not with the exact same name as the cmdline
+# variable.  Instead, the name of the global variable was expanded one more
+# time than the name of the cmdline variable.  For variable names that didn't
+# have a '$$' in their name, it was implemented correctly all the time.
+#
+# The bug was added in var.c 1.183 on 2013-07-16, when Var_Set called
+# Var_Delete to delete the global variable.  Just two months earlier, in var.c
+# 1.174 from 2013-05-18, Var_Delete had started to expand the variable name.
+# Together, these two changes made the variable name be expanded twice in a
+# row.  This bug was fixed in var.c 1.835 from 2021-02-22.
+#
+# Another bug was the wrong assumption that "deleting a cmdline variable is
+# not possible".  Deleting such a variable has been possible since var.c 1.204
+# from 2016-02-19, when the variable modifier ':@' started to delete the
+# temporary loop variable after finishing the loop.  It was probably not
+# intended back then that a side effect of this seemingly simple change was
+# that both global and cmdline variables could now be undefined at will as a
+# side effect of evaluating a variable expression.  As of 2021-02-23, this is
+# still possible.
 #
 # Most cmdline variables are set at the very beginning, when parsing the
 # command line arguments.  Using the special target '.MAKEFLAGS', it is



Home | Main Index | Thread Index | Old Index