varname-dot-makeflags.mk revision 1.4 1 1.4 rillig # $NetBSD: varname-dot-makeflags.mk,v 1.4 2023/02/25 10:41:14 rillig Exp $
2 1.1 rillig #
3 1.1 rillig # Tests for the special .MAKEFLAGS variable, which collects almost all
4 1.1 rillig # command line arguments and passes them on to any child processes via
5 1.1 rillig # the environment variable MAKEFLAGS (without leading '.').
6 1.2 rillig #
7 1.2 rillig # See also:
8 1.2 rillig # varname-dot-makeoverrides.mk
9 1.2 rillig
10 1.3 rillig all: spaces_stage_0 dollars_stage_0 append_stage_0
11 1.2 rillig
12 1.1 rillig
13 1.1 rillig # When options are parsed, the option and its argument are appended as
14 1.1 rillig # separate words to .MAKEFLAGS. Special characters in the option argument
15 1.2 rillig # are not quoted though. It seems to have not been necessary since at least
16 1.2 rillig # 1993.
17 1.2 rillig spaces_stage_0:
18 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
19 1.2 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
20 1.2 rillig @${MAKE} -f ${MAKEFILE} spaces_stage_1 -d00000 -D"VARNAME WITH SPACES"
21 1.2 rillig
22 1.2 rillig # At this point, the 'VARNAME WITH SPACES' is no longer recognizable as a
23 1.2 rillig # single command line argument. In practice, variable names don't contain
24 1.2 rillig # spaces.
25 1.2 rillig spaces_stage_1:
26 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
27 1.2 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
28 1.2 rillig
29 1.3 rillig
30 1.2 rillig # Demonstrate that '$' characters are altered when they are passed on to child
31 1.2 rillig # make processes via MAKEFLAGS.
32 1.2 rillig dollars_stage_0:
33 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
34 1.4 rillig
35 1.4 rillig # The '$$$$' becomes a literal '$$' when building the '${MAKE}'
36 1.4 rillig # command line, making the actual argument 'DOLLARS=$${varname}'.
37 1.4 rillig # At this stage, MAKEFLAGS is not yet involved.
38 1.2 rillig @${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}'
39 1.2 rillig
40 1.4 rillig .if make(dollars_stage_1)
41 1.4 rillig # At this point, the variable 'DOLLARS' contains '$${varname}', which
42 1.4 rillig # evaluates to a literal '$' followed by '{varname}'.
43 1.4 rillig . if ${DOLLARS} != "\${varname}"
44 1.4 rillig . error
45 1.4 rillig . endif
46 1.4 rillig .endif
47 1.2 rillig dollars_stage_1:
48 1.4 rillig # At this point, the stage 1 make provides the environment variable
49 1.4 rillig # 'MAKEFLAGS' to its child processes, even if the child process is not
50 1.4 rillig # another make.
51 1.4 rillig #
52 1.4 rillig # expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
53 1.4 rillig #
54 1.4 rillig # The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage
55 1.4 rillig # 2 make will see it as a single word.
56 1.2 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
57 1.2 rillig
58 1.4 rillig # At this point, evaluating the environment variable 'MAKEFLAGS' leads
59 1.4 rillig # to strange side effects as the string '\$\{varname\}' is interpreted
60 1.2 rillig # as:
61 1.2 rillig #
62 1.4 rillig # \ a literal string of a single backslash
63 1.2 rillig # $\ the value of the variable named '\'
64 1.2 rillig # {varname\} a literal string
65 1.2 rillig #
66 1.2 rillig # Since the variable name '\' is not defined, the resulting value is
67 1.4 rillig # '\{varname\}'. Make doesn't handle isolated '$' characters in
68 1.4 rillig # strings well, instead each '$' has to be part of a '$$' or be part
69 1.4 rillig # of a subexpression like '${VAR}'.
70 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
71 1.2 rillig
72 1.4 rillig # The modifier ':q' preserves a '$$' in an expression value instead of
73 1.4 rillig # expanding it to a single '$', but it's already too late, as that
74 1.4 rillig # modifier applies after the expression has been evaluated. Except
75 1.4 rillig # for debug logging, there is no way to process strings that contain
76 1.4 rillig # isolated '$'.
77 1.2 rillig @echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>'
78 1.2 rillig
79 1.2 rillig @${MAKE} -f ${MAKEFILE} dollars_stage_2
80 1.2 rillig
81 1.4 rillig .if make(dollars_stage_2)
82 1.4 rillig # At this point, the variable 'DOLLARS' contains '${varname}', and since
83 1.4 rillig # 'varname' is undefined, that expression evaluates to an empty string.
84 1.4 rillig . if ${DOLLARS} != ""
85 1.4 rillig . error
86 1.4 rillig . endif
87 1.4 rillig varname= varvalue
88 1.4 rillig . if ${DOLLARS} != "varvalue"
89 1.4 rillig . error
90 1.4 rillig . endif
91 1.4 rillig . undef varname
92 1.4 rillig .endif
93 1.2 rillig dollars_stage_2:
94 1.2 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
95 1.2 rillig @echo '$@: dollars=<'${DOLLARS:Q}'>'
96 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
97 1.2 rillig @${MAKE} -f ${MAKEFILE} dollars_stage_3
98 1.2 rillig
99 1.2 rillig dollars_stage_3:
100 1.2 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
101 1.2 rillig @echo '$@: dollars=<'${DOLLARS:Uundefined:Q}'>'
102 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
103 1.2 rillig
104 1.2 rillig
105 1.2 rillig # Demonstrates in which exact order the MAKEFLAGS are built together from the
106 1.2 rillig # parent MAKEFLAGS and the flags from the command line, in particular that
107 1.2 rillig # variable assignments are passed at the end, after the options.
108 1.2 rillig append_stage_0:
109 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
110 1.2 rillig @${MAKE} -Dbefore-0 -f ${MAKEFILE} append_stage_1 VAR0=value -Dafter-0
111 1.2 rillig
112 1.2 rillig append_stage_1:
113 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
114 1.2 rillig @${MAKE} -Dbefore-1 -f ${MAKEFILE} append_stage_2 VAR1=value -Dafter-1
115 1.2 rillig
116 1.2 rillig append_stage_2:
117 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
118 1.2 rillig @${MAKE} -Dbefore-2 -f ${MAKEFILE} append_stage_3 VAR2=value -Dafter-2
119 1.2 rillig
120 1.2 rillig append_stage_3:
121 1.2 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
122