Module Name: src Committed By: rillig Date: Sat Feb 25 11:59:12 UTC 2023
Modified Files: src/usr.bin/make/unit-tests: varname-dot-makeflags.exp varname-dot-makeflags.mk varname-makeflags.exp varname-makeflags.mk Log Message: tests/make: move tests for MAKRFLAGS to the correct file I had accidentally added these tests to the file for the special variable '.MAKEFLAGS' instead of the file for the environment variable 'MAKEFLAGS'. While here, add a basic test that shows how 'MAKEFLAGS' is built from '.MAKEFLAGS' and '.MAKEOVERRIDES'. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 \ src/usr.bin/make/unit-tests/varname-dot-makeflags.exp cvs rdiff -u -r1.5 -r1.6 src/usr.bin/make/unit-tests/varname-dot-makeflags.mk \ src/usr.bin/make/unit-tests/varname-makeflags.mk cvs rdiff -u -r1.1 -r1.2 src/usr.bin/make/unit-tests/varname-makeflags.exp 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.4 src/usr.bin/make/unit-tests/varname-dot-makeflags.exp:1.5 --- src/usr.bin/make/unit-tests/varname-dot-makeflags.exp:1.4 Sat Feb 25 11:11:16 2023 +++ src/usr.bin/make/unit-tests/varname-dot-makeflags.exp Sat Feb 25 11:59:12 2023 @@ -1,21 +1,10 @@ -spaces_stage_0: MAKEFLAGS=< -r -k > -spaces_stage_0: env MAKEFLAGS=< -r -k > -spaces_stage_1: MAKEFLAGS=< -r -k -d 00000 -D VARNAME WITH SPACES > -spaces_stage_1: env 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=> -append_stage_0: MAKEFLAGS=< -r -k > -append_stage_1: MAKEFLAGS=< -r -k -D before-0 -D after-0 VAR0=value> -append_stage_2: MAKEFLAGS=< -r -k -D before-0 -D after-0 -D before-1 -D after-1 VAR0=value VAR1=value> -append_stage_3: MAKEFLAGS=< -r -k -D before-0 -D after-0 -D before-1 -D after-1 -D before-2 -D after-2 VAR0=value VAR1=value VAR2=value> -override_stage_1: run MAKEFLAGS=< -r -k STAGE=1 VAR=value> -override_stage_2: STAGE=<2> VAR=<value> +make: "varname-dot-makeflags.mk" line 10: MAKEFLAGS=<undefined> +make: "varname-dot-makeflags.mk" line 11: .MAKEFLAGS=< -r -k> +make: "varname-dot-makeflags.mk" line 12: .MAKEOVERRIDES=<> +make: "varname-dot-makeflags.mk" line 17: MAKEFLAGS=<undefined> +make: "varname-dot-makeflags.mk" line 18: .MAKEFLAGS=< -r -k -D VARNAME -r> +make: "varname-dot-makeflags.mk" line 19: .MAKEOVERRIDES=< VAR> +runtime: MAKEFLAGS=< -r -k -D VARNAME -r VAR=value> +runtime: .MAKEFLAGS=< -r -k -D VARNAME -r> +runtime: .MAKEOVERRIDES=< VAR> 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.5 src/usr.bin/make/unit-tests/varname-dot-makeflags.mk:1.6 --- src/usr.bin/make/unit-tests/varname-dot-makeflags.mk:1.5 Sat Feb 25 11:11:16 2023 +++ src/usr.bin/make/unit-tests/varname-dot-makeflags.mk Sat Feb 25 11:59:12 2023 @@ -1,4 +1,4 @@ -# $NetBSD: varname-dot-makeflags.mk,v 1.5 2023/02/25 11:11:16 rillig Exp $ +# $NetBSD: varname-dot-makeflags.mk,v 1.6 2023/02/25 11:59:12 rillig Exp $ # # Tests for the special .MAKEFLAGS variable, which collects almost all # command line arguments and passes them on to any child processes via @@ -7,143 +7,19 @@ # See also: # varname-dot-makeoverrides.mk -all: spaces_stage_0 dollars_stage_0 append_stage_0 override_stage_0 +.info MAKEFLAGS=<${MAKEFLAGS:Uundefined}> +.info .MAKEFLAGS=<${.MAKEFLAGS}> +.info .MAKEOVERRIDES=<${.MAKEOVERRIDES:Uundefined}> + +# Append an option with argument, a plain option and a variable assignment. +.MAKEFLAGS: -DVARNAME -r VAR=value + +.info MAKEFLAGS=<${MAKEFLAGS:Uundefined}> +.info .MAKEFLAGS=<${.MAKEFLAGS}> +.info .MAKEOVERRIDES=<${.MAKEOVERRIDES}> - -# 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 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: +# After parsing, the environment variable 'MAKEFLAGS' is set based on +runtime: @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>' - - # The '$$$$' becomes a literal '$$' when building the '${MAKE}' - # command line, making the actual argument 'DOLLARS=$${varname}'. - # At this stage, MAKEFLAGS is not yet involved. - @${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}' - -.if make(dollars_stage_1) -# At this point, the variable 'DOLLARS' contains '$${varname}', which -# evaluates to a literal '$' followed by '{varname}'. -. if ${DOLLARS} != "\${varname}" -. error -. endif -.endif -dollars_stage_1: - # At this point, the stage 1 make provides the environment variable - # 'MAKEFLAGS' to its child processes, even if the child process is not - # another make. - # - # expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}> - # - # The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage - # 2 make will see it as a single word. - @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>" - - # At this point, evaluating the environment variable 'MAKEFLAGS' leads - # to strange side effects as the string '\$\{varname\}' is interpreted - # as: - # - # \ a literal string of 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\}'. Make doesn't handle isolated '$' characters in - # strings well, instead each '$' has to be part of a '$$' or be part - # of a subexpression like '${VAR}'. - @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>' - - # The modifier ':q' preserves a '$$' in an expression value instead of - # expanding it to a single '$', but it's already too late, as that - # modifier applies after the expression has been evaluated. Except - # for debug logging, there is no way to process strings that contain - # isolated '$'. - @echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>' - - @${MAKE} -f ${MAKEFILE} dollars_stage_2 - -.if make(dollars_stage_2) -# At this point, the variable 'DOLLARS' contains '${varname}', and since -# 'varname' is undefined, that expression evaluates to an empty string. -. if ${DOLLARS} != "" -. error -. endif -varname= varvalue -. if ${DOLLARS} != "varvalue" -. error -. endif -. undef varname -.endif -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}'>' - - -# Demonstrates the implementation details of 'MAKEFLAGS', in particular that -# it is an environment variable rather than a global variable. -override_stage_0: - @${MAKE} -f ${MAKEFILE} STAGE=1 VAR=value override_stage_1 - -.if make(override_stage_1) -# While parsing the makefiles, 'MAKEFLAGS' is the value of the environment -# variable, in this case provided by stage 0. -. if ${MAKEFLAGS:M*} != "-r -k" -. error -. endif -MAKEFLAGS= overridden # temporarily override it -. if ${MAKEFLAGS} != "overridden" -. error -. endif -.undef MAKEFLAGS # make the environment variable visible again -. if ${MAKEFLAGS:M*} != "-r -k" -. error -. endif -.endif -override_stage_1: - @echo '$@: run MAKEFLAGS=<'${MAKEFLAGS:Q}'>' - @${MAKE} -f ${MAKEFILE} STAGE=2 override_stage_2 - -override_stage_2: - @echo '$@: STAGE=<${STAGE}> VAR=<${VAR}>' + @echo '$@: .MAKEFLAGS=<'${.MAKEFLAGS:Q}'>' + @echo '$@: .MAKEOVERRIDES=<'${.MAKEOVERRIDES:Q}'>' Index: src/usr.bin/make/unit-tests/varname-makeflags.mk diff -u src/usr.bin/make/unit-tests/varname-makeflags.mk:1.5 src/usr.bin/make/unit-tests/varname-makeflags.mk:1.6 --- src/usr.bin/make/unit-tests/varname-makeflags.mk:1.5 Sun Jan 16 18:16:06 2022 +++ src/usr.bin/make/unit-tests/varname-makeflags.mk Sat Feb 25 11:59:12 2023 @@ -1,44 +1,182 @@ -# $NetBSD: varname-makeflags.mk,v 1.5 2022/01/16 18:16:06 sjg Exp $ +# $NetBSD: varname-makeflags.mk,v 1.6 2023/02/25 11:59:12 rillig Exp $ # # Tests for the special MAKEFLAGS variable, which is basically just a normal # environment variable. It is closely related to .MAKEFLAGS but captures the # state of .MAKEFLAGS at the very beginning of make, before any makefiles are # read. -# TODO: Implementation +all: spaces_stage_0 dollars_stage_0 append_stage_0 override_stage_0 -.MAKEFLAGS: -d0 + +.if !make(*stage*) # The unit tests are run with an almost empty environment. In particular, # the variable MAKEFLAGS is not set. The '.MAKEFLAGS:' above also doesn't # influence the environment variable MAKEFLAGS, therefore it is still # undefined at this point. -.if ${MAKEFLAGS:Uundefined} != "undefined" -. error -.endif +. if ${MAKEFLAGS:Uundefined} != "undefined" +. error +. endif # The special variable .MAKEFLAGS is influenced though. # See varname-dot-makeflags.mk for more details. -.if ${.MAKEFLAGS} != " -r -k -d 0" -. error -.endif +. if ${.MAKEFLAGS} != " -r -k" +. error +. endif # In POSIX mode, the environment variable MAKEFLAGS can contain letters only, # for compatibility. These letters are exploded to form regular options. OUTPUT!= env MAKEFLAGS=ikrs ${MAKE} -f /dev/null -v .MAKEFLAGS -.if ${OUTPUT} != " -i -k -r -s -V .MAKEFLAGS" -. error -.endif +. if ${OUTPUT} != " -i -k -r -s -V .MAKEFLAGS" +. error +. endif # As soon as there is a single non-alphabetic character in the environment # variable MAKEFLAGS, it is no longer split. In this example, the word # "d0ikrs" is treated as a target, but the option '-v' prevents any targets # from being built. OUTPUT!= env MAKEFLAGS=d0ikrs ${MAKE} -r -f /dev/null -v .MAKEFLAGS -.if ${OUTPUT} != " -r -V .MAKEFLAGS" -. error ${OUTPUT} +. if ${OUTPUT} != " -r -V .MAKEFLAGS" +. error ${OUTPUT} +. endif + .endif -all: +# When options are parsed, the option and its argument are appended as +# separate words to the MAKEFLAGS for the child processes. Special characters +# in the option arguments are not quoted though. +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 '$$$$' becomes a literal '$$' when building the '${MAKE}' + # command line, making the actual argument 'DOLLARS=$${varname}'. + # At this stage, MAKEFLAGS is not yet involved. + @${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}' + +.if make(dollars_stage_1) +# At this point, the variable 'DOLLARS' contains '$${varname}', which +# evaluates to a literal '$' followed by '{varname}'. +. if ${DOLLARS} != "\${varname}" +. error +. endif +.endif +dollars_stage_1: + # At this point, the stage 1 make provides the environment variable + # 'MAKEFLAGS' to its child processes, even if the child process is not + # another make. + # + # expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}> + # + # The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage + # 2 make will see it as a single word. + @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>" + + # At this point, evaluating the environment variable 'MAKEFLAGS' leads + # to strange side effects as the string '\$\{varname\}' is interpreted + # as: + # + # \ a literal string of 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\}'. Make doesn't handle isolated '$' characters in + # strings well, instead each '$' has to be part of a '$$' or be part + # of a subexpression like '${VAR}'. + @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>' + + # The modifier ':q' preserves a '$$' in an expression value instead of + # expanding it to a single '$', but it's already too late, as that + # modifier applies after the expression has been evaluated. Except + # for debug logging, there is no way to process strings that contain + # isolated '$'. + @echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>' + + @${MAKE} -f ${MAKEFILE} dollars_stage_2 + +.if make(dollars_stage_2) +# At this point, the variable 'DOLLARS' contains '${varname}', and since +# 'varname' is undefined, that expression evaluates to an empty string. +. if ${DOLLARS} != "" +. error +. endif +varname= varvalue +. if ${DOLLARS} != "varvalue" +. error +. endif +. undef varname +.endif +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}'>' + + +# Demonstrates the implementation details of 'MAKEFLAGS', in particular that +# it is an environment variable rather than a global variable. +override_stage_0: + @${MAKE} -f ${MAKEFILE} STAGE=1 VAR=value override_stage_1 + +.if make(override_stage_1) +# While parsing the makefiles, 'MAKEFLAGS' is the value of the environment +# variable, in this case provided by stage 0. +. if ${MAKEFLAGS:M*} != "-r -k" +. error +. endif +MAKEFLAGS= overridden # temporarily override it +. if ${MAKEFLAGS} != "overridden" +. error +. endif +.undef MAKEFLAGS # make the environment variable visible again +. if ${MAKEFLAGS:M*} != "-r -k" +. error +. endif +.endif +override_stage_1: + @echo '$@: run MAKEFLAGS=<'${MAKEFLAGS:Q}'>' + @${MAKE} -f ${MAKEFILE} STAGE=2 override_stage_2 + +override_stage_2: + @echo '$@: STAGE=<${STAGE}> VAR=<${VAR}>' Index: src/usr.bin/make/unit-tests/varname-makeflags.exp diff -u src/usr.bin/make/unit-tests/varname-makeflags.exp:1.1 src/usr.bin/make/unit-tests/varname-makeflags.exp:1.2 --- src/usr.bin/make/unit-tests/varname-makeflags.exp:1.1 Sun Aug 16 12:07:52 2020 +++ src/usr.bin/make/unit-tests/varname-makeflags.exp Sat Feb 25 11:59:12 2023 @@ -1 +1,21 @@ +spaces_stage_0: MAKEFLAGS=< -r -k > +spaces_stage_0: env MAKEFLAGS=< -r -k > +spaces_stage_1: MAKEFLAGS=< -r -k -d 00000 -D VARNAME WITH SPACES > +spaces_stage_1: env 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=> +append_stage_0: MAKEFLAGS=< -r -k > +append_stage_1: MAKEFLAGS=< -r -k -D before-0 -D after-0 VAR0=value> +append_stage_2: MAKEFLAGS=< -r -k -D before-0 -D after-0 -D before-1 -D after-1 VAR0=value VAR1=value> +append_stage_3: MAKEFLAGS=< -r -k -D before-0 -D after-0 -D before-1 -D after-1 -D before-2 -D after-2 VAR0=value VAR1=value VAR2=value> +override_stage_1: run MAKEFLAGS=< -r -k STAGE=1 VAR=value> +override_stage_2: STAGE=<2> VAR=<value> exit status 0