varname-makeflags.mk revision 1.8 1 1.8 rillig # $NetBSD: varname-makeflags.mk,v 1.8 2023/06/01 07:27:30 rillig Exp $
2 1.1 rillig #
3 1.7 rillig # Tests for the environment variable 'MAKEFLAGS', from which additional
4 1.7 rillig # command line arguments are read before the actual command line arguments.
5 1.7 rillig #
6 1.7 rillig # After reading the makefiles and before making the targets, the arguments
7 1.7 rillig # that were collected in '.MAKEFLAGS' and '.MAKEOVERRIDES' are written back to
8 1.7 rillig # the environment variable 'MAKEFLAGS'.
9 1.1 rillig
10 1.6 rillig all: spaces_stage_0 dollars_stage_0 append_stage_0 override_stage_0
11 1.1 rillig
12 1.6 rillig
13 1.6 rillig .if !make(*stage*)
14 1.3 rillig
15 1.3 rillig # The unit tests are run with an almost empty environment. In particular,
16 1.7 rillig # the variable MAKEFLAGS is not set.
17 1.6 rillig . if ${MAKEFLAGS:Uundefined} != "undefined"
18 1.6 rillig . error
19 1.6 rillig . endif
20 1.3 rillig
21 1.3 rillig # The special variable .MAKEFLAGS is influenced though.
22 1.3 rillig # See varname-dot-makeflags.mk for more details.
23 1.6 rillig . if ${.MAKEFLAGS} != " -r -k"
24 1.6 rillig . error
25 1.6 rillig . endif
26 1.3 rillig
27 1.4 rillig
28 1.4 rillig # In POSIX mode, the environment variable MAKEFLAGS can contain letters only,
29 1.4 rillig # for compatibility. These letters are exploded to form regular options.
30 1.4 rillig OUTPUT!= env MAKEFLAGS=ikrs ${MAKE} -f /dev/null -v .MAKEFLAGS
31 1.6 rillig . if ${OUTPUT} != " -i -k -r -s -V .MAKEFLAGS"
32 1.6 rillig . error
33 1.6 rillig . endif
34 1.4 rillig
35 1.4 rillig # As soon as there is a single non-alphabetic character in the environment
36 1.4 rillig # variable MAKEFLAGS, it is no longer split. In this example, the word
37 1.4 rillig # "d0ikrs" is treated as a target, but the option '-v' prevents any targets
38 1.4 rillig # from being built.
39 1.5 sjg OUTPUT!= env MAKEFLAGS=d0ikrs ${MAKE} -r -f /dev/null -v .MAKEFLAGS
40 1.6 rillig . if ${OUTPUT} != " -r -V .MAKEFLAGS"
41 1.6 rillig . error ${OUTPUT}
42 1.6 rillig . endif
43 1.6 rillig
44 1.4 rillig .endif
45 1.4 rillig
46 1.4 rillig
47 1.6 rillig # When options are parsed, the option and its argument are appended as
48 1.6 rillig # separate words to the MAKEFLAGS for the child processes. Special characters
49 1.6 rillig # in the option arguments are not quoted though.
50 1.6 rillig spaces_stage_0:
51 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
52 1.6 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
53 1.6 rillig @${MAKE} -f ${MAKEFILE} spaces_stage_1 -d00000 -D"VARNAME WITH SPACES"
54 1.6 rillig
55 1.6 rillig # At this point, the 'VARNAME WITH SPACES' is no longer recognizable as a
56 1.6 rillig # single command line argument. In practice, variable names don't contain
57 1.6 rillig # spaces.
58 1.6 rillig spaces_stage_1:
59 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
60 1.6 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
61 1.6 rillig
62 1.6 rillig
63 1.6 rillig # Demonstrate that '$' characters are altered when they are passed on to child
64 1.6 rillig # make processes via MAKEFLAGS.
65 1.6 rillig dollars_stage_0:
66 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
67 1.6 rillig
68 1.6 rillig # The '$$$$' becomes a literal '$$' when building the '${MAKE}'
69 1.6 rillig # command line, making the actual argument 'DOLLARS=$${varname}'.
70 1.6 rillig # At this stage, MAKEFLAGS is not yet involved.
71 1.6 rillig @${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}'
72 1.6 rillig
73 1.6 rillig .if make(dollars_stage_1)
74 1.6 rillig # At this point, the variable 'DOLLARS' contains '$${varname}', which
75 1.6 rillig # evaluates to a literal '$' followed by '{varname}'.
76 1.6 rillig . if ${DOLLARS} != "\${varname}"
77 1.6 rillig . error
78 1.6 rillig . endif
79 1.6 rillig .endif
80 1.6 rillig dollars_stage_1:
81 1.6 rillig # At this point, the stage 1 make provides the environment variable
82 1.6 rillig # 'MAKEFLAGS' to its child processes, even if the child process is not
83 1.6 rillig # another make.
84 1.6 rillig #
85 1.6 rillig # expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
86 1.6 rillig #
87 1.6 rillig # The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage
88 1.6 rillig # 2 make will see it as a single word.
89 1.6 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
90 1.6 rillig
91 1.6 rillig # At this point, evaluating the environment variable 'MAKEFLAGS' leads
92 1.6 rillig # to strange side effects as the string '\$\{varname\}' is interpreted
93 1.6 rillig # as:
94 1.6 rillig #
95 1.6 rillig # \ a literal string of a single backslash
96 1.6 rillig # $\ the value of the variable named '\'
97 1.6 rillig # {varname\} a literal string
98 1.6 rillig #
99 1.8 rillig # Since the variable named '\' is not defined, the resulting value is
100 1.6 rillig # '\{varname\}'. Make doesn't handle isolated '$' characters in
101 1.6 rillig # strings well, instead each '$' has to be part of a '$$' or be part
102 1.6 rillig # of a subexpression like '${VAR}'.
103 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
104 1.6 rillig
105 1.6 rillig # The modifier ':q' preserves a '$$' in an expression value instead of
106 1.6 rillig # expanding it to a single '$', but it's already too late, as that
107 1.6 rillig # modifier applies after the expression has been evaluated. Except
108 1.6 rillig # for debug logging, there is no way to process strings that contain
109 1.6 rillig # isolated '$'.
110 1.6 rillig @echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>'
111 1.6 rillig
112 1.6 rillig @${MAKE} -f ${MAKEFILE} dollars_stage_2
113 1.6 rillig
114 1.6 rillig .if make(dollars_stage_2)
115 1.6 rillig # At this point, the variable 'DOLLARS' contains '${varname}', and since
116 1.6 rillig # 'varname' is undefined, that expression evaluates to an empty string.
117 1.6 rillig . if ${DOLLARS} != ""
118 1.6 rillig . error
119 1.6 rillig . endif
120 1.6 rillig varname= varvalue
121 1.6 rillig . if ${DOLLARS} != "varvalue"
122 1.6 rillig . error
123 1.6 rillig . endif
124 1.6 rillig . undef varname
125 1.6 rillig .endif
126 1.6 rillig dollars_stage_2:
127 1.6 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
128 1.6 rillig @echo '$@: dollars=<'${DOLLARS:Q}'>'
129 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
130 1.6 rillig @${MAKE} -f ${MAKEFILE} dollars_stage_3
131 1.6 rillig
132 1.6 rillig dollars_stage_3:
133 1.6 rillig @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
134 1.6 rillig @echo '$@: dollars=<'${DOLLARS:Uundefined:Q}'>'
135 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
136 1.6 rillig
137 1.6 rillig
138 1.8 rillig # Demonstrates in which exact order the MAKEFLAGS are built from the parent
139 1.8 rillig # MAKEFLAGS and the flags from the command line, in particular that variable
140 1.8 rillig # assignments are passed at the end, after the options.
141 1.6 rillig append_stage_0:
142 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
143 1.6 rillig @${MAKE} -Dbefore-0 -f ${MAKEFILE} append_stage_1 VAR0=value -Dafter-0
144 1.6 rillig
145 1.6 rillig append_stage_1:
146 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
147 1.6 rillig @${MAKE} -Dbefore-1 -f ${MAKEFILE} append_stage_2 VAR1=value -Dafter-1
148 1.6 rillig
149 1.6 rillig append_stage_2:
150 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
151 1.6 rillig @${MAKE} -Dbefore-2 -f ${MAKEFILE} append_stage_3 VAR2=value -Dafter-2
152 1.6 rillig
153 1.6 rillig append_stage_3:
154 1.6 rillig @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
155 1.6 rillig
156 1.6 rillig
157 1.6 rillig # Demonstrates the implementation details of 'MAKEFLAGS', in particular that
158 1.6 rillig # it is an environment variable rather than a global variable.
159 1.6 rillig override_stage_0:
160 1.6 rillig @${MAKE} -f ${MAKEFILE} STAGE=1 VAR=value override_stage_1
161 1.6 rillig
162 1.6 rillig .if make(override_stage_1)
163 1.6 rillig # While parsing the makefiles, 'MAKEFLAGS' is the value of the environment
164 1.6 rillig # variable, in this case provided by stage 0.
165 1.6 rillig . if ${MAKEFLAGS:M*} != "-r -k"
166 1.6 rillig . error
167 1.6 rillig . endif
168 1.6 rillig MAKEFLAGS= overridden # temporarily override it
169 1.6 rillig . if ${MAKEFLAGS} != "overridden"
170 1.6 rillig . error
171 1.6 rillig . endif
172 1.6 rillig .undef MAKEFLAGS # make the environment variable visible again
173 1.6 rillig . if ${MAKEFLAGS:M*} != "-r -k"
174 1.6 rillig . error
175 1.6 rillig . endif
176 1.6 rillig .endif
177 1.6 rillig override_stage_1:
178 1.6 rillig @echo '$@: run MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
179 1.6 rillig @${MAKE} -f ${MAKEFILE} STAGE=2 override_stage_2
180 1.6 rillig
181 1.6 rillig override_stage_2:
182 1.6 rillig @echo '$@: STAGE=<${STAGE}> VAR=<${VAR}>'
183