Module Name:    src
Committed By:   rillig
Date:           Sat Feb 25 06:54:08 UTC 2023

Modified Files:
        src/usr.bin/make/unit-tests: varname-dot-makeflags.exp
            varname-dot-makeflags.mk varname-dot-makeoverrides.exp
            varname-dot-makeoverrides.mk

Log Message:
tests/make: reproduce and explain '$' in MAKEFLAGS

https://mail-index.netbsd.org/current-users/2023/02/24/msg043633.html


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 \
    src/usr.bin/make/unit-tests/varname-dot-makeflags.exp \
    src/usr.bin/make/unit-tests/varname-dot-makeflags.mk
cvs rdiff -u -r1.2 -r1.3 \
    src/usr.bin/make/unit-tests/varname-dot-makeoverrides.exp
cvs rdiff -u -r1.4 -r1.5 \
    src/usr.bin/make/unit-tests/varname-dot-makeoverrides.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/unit-tests/varname-dot-makeflags.exp
diff -u src/usr.bin/make/unit-tests/varname-dot-makeflags.exp:1.1 src/usr.bin/make/unit-tests/varname-dot-makeflags.exp:1.2
--- src/usr.bin/make/unit-tests/varname-dot-makeflags.exp:1.1	Tue Dec  1 20:37:30 2020
+++ src/usr.bin/make/unit-tests/varname-dot-makeflags.exp	Sat Feb 25 06:54:08 2023
@@ -1,3 +1,11 @@
-echo "$MAKEFLAGS"
- -r -k -d 00000 -D VARNAME WITH SPACES 
+dollars_stage_0: MAKEFLAGS=< -r -k >
+dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
+dollars_stage_1: MAKEFLAGS=< -r -k DOLLARS=\{varname\}>
+dollars_stage_1: MAKEFLAGS:q=< -r -k DOLLARS=\{varname\}>
+dollars_stage_2: env MAKEFLAGS=< -r -k DOLLARS=>
+dollars_stage_2: dollars=<>
+dollars_stage_2: MAKEFLAGS=< -r -k DOLLARS=>
+dollars_stage_3: env MAKEFLAGS=< -r -k DOLLARS=>
+dollars_stage_3: dollars=<>
+dollars_stage_3: MAKEFLAGS=< -r -k DOLLARS=>
 exit status 0
Index: src/usr.bin/make/unit-tests/varname-dot-makeflags.mk
diff -u src/usr.bin/make/unit-tests/varname-dot-makeflags.mk:1.1 src/usr.bin/make/unit-tests/varname-dot-makeflags.mk:1.2
--- src/usr.bin/make/unit-tests/varname-dot-makeflags.mk:1.1	Tue Dec  1 20:37:30 2020
+++ src/usr.bin/make/unit-tests/varname-dot-makeflags.mk	Sat Feb 25 06:54:08 2023
@@ -1,15 +1,107 @@
-# $NetBSD: varname-dot-makeflags.mk,v 1.1 2020/12/01 20:37:30 rillig Exp $
+# $NetBSD: varname-dot-makeflags.mk,v 1.2 2023/02/25 06:54:08 rillig Exp $
 #
 # Tests for the special .MAKEFLAGS variable, which collects almost all
 # command line arguments and passes them on to any child processes via
 # the environment variable MAKEFLAGS (without leading '.').
+#
+# See also:
+#	varname-dot-makeoverrides.mk
+
+all: dollars_stage_0 #spaces_stage_0 dollars_stage_0 append_stage_0
+
 
 # When options are parsed, the option and its argument are appended as
 # separate words to .MAKEFLAGS.  Special characters in the option argument
-# are not quoted though.  It seems to have not been necessary at least from
-# 1993 until 2020.
-.MAKEFLAGS: -d00000 -D"VARNAME WITH SPACES"
-
-all:
-	echo "$$MAKEFLAGS"
-	@:;
+# are not quoted though.  It seems to have not been necessary since at least
+# 1993.
+spaces_stage_0:
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
+	@${MAKE} -f ${MAKEFILE} spaces_stage_1 -d00000 -D"VARNAME WITH SPACES"
+
+# At this point, the 'VARNAME WITH SPACES' is no longer recognizable as a
+# single command line argument.  In practice, variable names don't contain
+# spaces.
+spaces_stage_1:
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
+
+# Demonstrate that '$' characters are altered when they are passed on to child
+# make processes via MAKEFLAGS.
+dollars_stage_0:
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+	# The '$$$$' gets parsed as a literal '$$', making the actual variable
+	# value '$${varname}'.
+	#
+	# When Main_ExportMAKEFLAGS adds the variable DOLLARS to MAKEFLAGS, it
+	# first evaluates the variable value, resulting in '${varname}'.
+	#
+	# This value is then escaped as '\$\{varname\}', to ensure that the
+	# variable is later interpreted as a single shell word.
+	@${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}'
+
+# The environment variable 'MAKEFLAGS' now contains the variable assignment
+# 'DOLLARS=\$\{varname\}', including the backslashes.
+#
+# expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
+#
+# When Main_ParseArgLine calls Str_Words to parse the flags from MAKEFLAGS, it
+# removes the backslashes, resulting in the plain variable assignment
+# 'DOLLARS=${varname}'.
+dollars_stage_1:
+	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
+
+	# At this point, evaluating the environment variable 'MAKEFLAGS' has
+	# strange side effects, as the string '\$\{varname\}' is interpreted
+	# as:
+	#
+	#	\		a single backslash
+	#	$\		the value of the variable named '\'
+	#	{varname\}	a literal string
+	#
+	# Since the variable name '\' is not defined, the resulting value is
+	# '\{varname\}'.
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+
+	# The modifier ':q' escapes a '$' in the variable value to '$$', but
+	# it's too late, as that modifier applies after the expression has
+	# been evaluated.
+	@echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>'
+
+	# The value of the variable DOLLARS is now '${varname}'.  Since there
+	# is no variable named 'varname', this expression evaluates to ''.
+	@${MAKE} -f ${MAKEFILE} dollars_stage_2
+
+# Uncomment these lines to see the above variable expansions in action.
+#${:U\\}=backslash
+#varname=varvalue
+
+dollars_stage_2:
+	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
+	@echo '$@: dollars=<'${DOLLARS:Q}'>'
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+	@${MAKE} -f ${MAKEFILE} dollars_stage_3
+
+dollars_stage_3:
+	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
+	@echo '$@: dollars=<'${DOLLARS:Uundefined:Q}'>'
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+
+
+# Demonstrates in which exact order the MAKEFLAGS are built together from the
+# parent MAKEFLAGS and the flags from the command line, in particular that
+# variable assignments are passed at the end, after the options.
+append_stage_0:
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+	@${MAKE} -Dbefore-0 -f ${MAKEFILE} append_stage_1 VAR0=value -Dafter-0
+
+append_stage_1:
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+	@${MAKE} -Dbefore-1 -f ${MAKEFILE} append_stage_2 VAR1=value -Dafter-1
+
+append_stage_2:
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
+	@${MAKE} -Dbefore-2 -f ${MAKEFILE} append_stage_3 VAR2=value -Dafter-2
+
+append_stage_3:
+	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'

Index: src/usr.bin/make/unit-tests/varname-dot-makeoverrides.exp
diff -u src/usr.bin/make/unit-tests/varname-dot-makeoverrides.exp:1.2 src/usr.bin/make/unit-tests/varname-dot-makeoverrides.exp:1.3
--- src/usr.bin/make/unit-tests/varname-dot-makeoverrides.exp:1.2	Sat Feb 25 00:09:52 2023
+++ src/usr.bin/make/unit-tests/varname-dot-makeoverrides.exp	Sat Feb 25 06:54:08 2023
@@ -1,5 +1,8 @@
-make -r -f varname-dot-makeoverrides.mk dollars_stage_2 DOLLARS='$${varname}'
-stage 2: dollars=<${varname}>
-make -r -f varname-dot-makeoverrides.mk dollars_stage_3
-stage 3: dollars=<>
+all: overrides=<>
+make -f varname-dot-makeoverrides.mk stage_1 VAR=value
+stage_1: overrides=< VAR>
+make -f varname-dot-makeoverrides.mk stage_2
+stage_2: overrides=< VAR>
+make -f varname-dot-makeoverrides.mk stage_3
+stage_3: overrides=< VAR>
 exit status 0

Index: src/usr.bin/make/unit-tests/varname-dot-makeoverrides.mk
diff -u src/usr.bin/make/unit-tests/varname-dot-makeoverrides.mk:1.4 src/usr.bin/make/unit-tests/varname-dot-makeoverrides.mk:1.5
--- src/usr.bin/make/unit-tests/varname-dot-makeoverrides.mk:1.4	Sat Feb 25 00:09:52 2023
+++ src/usr.bin/make/unit-tests/varname-dot-makeoverrides.mk	Sat Feb 25 06:54:08 2023
@@ -1,18 +1,23 @@
-# $NetBSD: varname-dot-makeoverrides.mk,v 1.4 2023/02/25 00:09:52 rillig Exp $
+# $NetBSD: varname-dot-makeoverrides.mk,v 1.5 2023/02/25 06:54:08 rillig Exp $
 #
-# Tests for the special .MAKEOVERRIDES variable.
+# Tests for the special .MAKEOVERRIDES variable, which lists the names of the
+# variables that are passed on to child processes via the MAKEFLAGS
+# environment variable.
+#
+# See also:
+#	varname-dot-makeflags.mk
 
 all:
-	@${MAKE} -r -f ${MAKEFILE} dollars_stage_1
+	@echo '$@: overrides=<'${.MAKEOVERRIDES:Uundefined:Q}'>'
+	${MAKE} -f ${MAKEFILE} stage_1 VAR=value
 
-# Demonstrate that '$' characters are altered when they are passed on to child
-# make processes via .MAKEOVERRIDES and MAKEFLAGS.
-dollars_stage_1:
-	${MAKE} -r -f ${MAKEFILE} dollars_stage_2 DOLLARS='$$$${varname}'
+stage_1:
+	@echo '$@: overrides=<'${.MAKEOVERRIDES:Q}'>'
+	${MAKE} -f ${MAKEFILE} stage_2
 
-dollars_stage_2:
-	@echo 'stage 2: dollars=<${DOLLARS}>'
-	${MAKE} -r -f ${MAKEFILE} dollars_stage_3
+stage_2:
+	@echo '$@: overrides=<'${.MAKEOVERRIDES:Q}'>'
+	${MAKE} -f ${MAKEFILE} stage_3
 
-dollars_stage_3:
-	@echo 'stage 3: dollars=<${DOLLARS}>'
+stage_3:
+	@echo '$@: overrides=<'${.MAKEOVERRIDES:Q}'>'

Reply via email to