1 From dc2d963989b96161472b2cd38cef5d1f4851ea34 Mon Sep 17 00:00:00 2001
2 From: Dmitry Goncharov <dgoncharov@users.sf.net>
3 Date: Sun, 27 Nov 2022 14:09:17 -0500
4 Subject: [SV 63347] Always add command line variable assignments to MAKEFLAGS
6 This commit introduces two visible changes:
7 1. Keep command line variable assignments in MAKEFLAGS at all times,
8 even while parsing makefiles.
9 2. Define makeflags immediately when a makefile modifies MAKEFLAGS.
11 The new MAKEFLAGS and MAKEOVERRIDES initialization procedure:
12 1. decode_switches (argc, argv, o_command) is called to parse command
13 line variable assignments.
14 2. Command line variable assignments go through quote_for_env.
15 Initialize -*-command-variables-*- to the quoted values.
16 3. MAKEOVERRIDES is initialized to refer to -*-command-variables-*-
17 with origin o_env to keep the definitions in the database intact.
18 4. define_makeflags() is called which adds MAKEOVERRIDES to MAKEFLAGS.
19 5. Makefiles are parsed. If a makefile modifies MAKEFLAGS, the new
20 value of MAKEFLAGS is defined right away.
21 6. Env switches are decoded again as o_env. The definitions set by
22 decode_switches at step 1 stay intact, as o_command beats o_env.
24 We must preserve the original intact definitions in order to detect
25 failure cases; for example:
28 $ make hello='$(world'
29 makefile:1: *** unterminated variable reference. Stop.
31 * src/makeint.h: Declare enum variable_origin, struct variable and
32 define_makeflags(). Add parameter origin to decode_env_switches().
33 * src/main.c (define_makeflags): Remove "all". If a variable is
34 assigned on the command line then append MAKEOVERRIDES to MAKEFLAGS.
35 (decode_env_switches): Replace parameter env with origin.
36 (decode_switches): Replace parameter env with origin.
37 Treat origin == o_command as env == 0.
38 (handle_non_switch_argument): Replace parameter env with origin.
39 Treat origin == o_command as env == 0.
40 (main): Call decode_switches() with origin==o_command before parsing
41 makefiles. Call decode_switches() with origin==o_env after parsing
43 * src/variable.c (set_special_var): Define makeflags at parse time,
44 each time a makefile modifies MAKEFLAGS.
45 (do_variable_definition): Strip command line variable assignments from
46 MAKEFLAGS before appending extra flags. set_special_var() adds them
48 * tests/scripts/variables/MAKEFLAGS: Add tests.
50 src/main.c | 90 ++++++-------
52 src/variable.c | 72 ++++++----
53 tests/scripts/variables/MAKEFLAGS | 273 +++++++++++++++++++++++++++++++++-----
54 4 files changed, 336 insertions(+), 105 deletions(-)
56 diff --git a/src/main.c b/src/main.c
57 index b31ddd4..d8a7372 100644
60 @@ -105,8 +105,8 @@ double atof ();
61 static void clean_jobserver (int status);
62 static void print_data_base (void);
63 static void print_version (void);
64 -static void decode_switches (int argc, const char **argv, int env);
65 -static struct variable *define_makeflags (int all, int makefile);
66 +static void decode_switches (int argc, const char **argv,
67 + enum variable_origin origin);
68 static char *quote_for_env (char *out, const char *in);
69 static void initialize_global_hash_tables (void);
71 @@ -1572,13 +1572,13 @@ main (int argc, char **argv, char **envp)
72 /* Decode the switches. */
73 if (lookup_variable (STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME)))
75 - decode_env_switches (STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME));
76 + decode_env_switches (STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME), o_command);
78 /* Clear GNUMAKEFLAGS to avoid duplication. */
79 define_variable_cname (GNUMAKEFLAGS_NAME, "", o_env, 0);
82 - decode_env_switches (STRING_SIZE_TUPLE (MAKEFLAGS_NAME));
83 + decode_env_switches (STRING_SIZE_TUPLE (MAKEFLAGS_NAME), o_command);
86 /* People write things like:
87 @@ -1599,7 +1599,7 @@ main (int argc, char **argv, char **envp)
88 int env_slots = arg_job_slots;
89 arg_job_slots = INVALID_JOB_SLOTS;
91 - decode_switches (argc, (const char **)argv, 0);
92 + decode_switches (argc, (const char **)argv, o_command);
93 argv_slots = arg_job_slots;
95 if (arg_job_slots == INVALID_JOB_SLOTS)
96 @@ -2022,7 +2022,7 @@ main (int argc, char **argv, char **envp)
98 /* Set up the MAKEFLAGS and MFLAGS variables for makefiles to see.
99 Initialize it to be exported but allow the makefile to reset it. */
100 - define_makeflags (0, 0)->export = v_export;
101 + define_makeflags (0)->export = v_export;
103 /* Define the default variables. */
104 define_default_variables ();
105 @@ -2072,12 +2072,12 @@ main (int argc, char **argv, char **envp)
106 arg_job_slots = INVALID_JOB_SLOTS;
108 /* Decode switches again, for variables set by the makefile. */
109 - decode_env_switches (STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME));
110 + decode_env_switches (STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME), o_env);
112 /* Clear GNUMAKEFLAGS to avoid duplication. */
113 define_variable_cname (GNUMAKEFLAGS_NAME, "", o_override, 0);
115 - decode_env_switches (STRING_SIZE_TUPLE (MAKEFLAGS_NAME));
116 + decode_env_switches (STRING_SIZE_TUPLE (MAKEFLAGS_NAME), o_env);
118 decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
120 @@ -2260,7 +2260,7 @@ main (int argc, char **argv, char **envp)
122 /* Set up MAKEFLAGS and MFLAGS again, so they will be right. */
124 - define_makeflags (1, 0);
125 + define_makeflags (0);
127 /* Make each 'struct goaldep' point at the 'struct file' for the file
128 depended on. Also do magic for special targets. */
129 @@ -2420,7 +2420,7 @@ main (int argc, char **argv, char **envp)
132 /* Set up 'MAKEFLAGS' specially while remaking makefiles. */
133 - define_makeflags (1, 1);
134 + define_makeflags (1);
137 int orig_db_level = db_level;
138 @@ -2812,7 +2812,7 @@ main (int argc, char **argv, char **envp)
141 /* Set up 'MAKEFLAGS' again for the normal targets. */
142 - define_makeflags (1, 0);
143 + define_makeflags (0);
145 /* Set always_make_flag if -B was given. */
146 always_make_flag = always_make_set;
147 @@ -3000,7 +3000,7 @@ init_switches (void)
149 /* Non-option argument. It might be a variable definition. */
151 -handle_non_switch_argument (const char *arg, int env)
152 +handle_non_switch_argument (const char *arg, enum variable_origin origin)
156 @@ -3033,7 +3033,7 @@ handle_non_switch_argument (const char *arg, int env)
160 - v = try_variable_definition (0, arg, o_command, 0);
161 + v = try_variable_definition (0, arg, origin, 0);
164 /* It is indeed a variable definition. If we don't already have this
165 @@ -3053,11 +3053,12 @@ handle_non_switch_argument (const char *arg, int env)
166 command_variables = cv;
170 + else if (arg[0] != '\0' && origin == o_command)
172 - /* Not an option or variable definition; it must be a goal
173 - target! Enter it as a file and add it to the dep chain of
175 + /* Not an option or variable definition; it must be a goal target.
176 + Enter it as a file and add it to the dep chain of goals.
177 + Check ARG[0] because if the top makefile resets MAKEOVERRIDES
178 + then ARG points to an empty string in the submake. */
179 struct file *f = enter_file (strcache_add (expand_command_line_file (arg)));
182 @@ -3105,7 +3106,7 @@ handle_non_switch_argument (const char *arg, int env)
183 They came from the environment if ENV is nonzero. */
186 -decode_switches (int argc, const char **argv, int env)
187 +decode_switches (int argc, const char **argv, enum variable_origin origin)
190 const struct command_switch *cs;
191 @@ -3119,7 +3120,7 @@ decode_switches (int argc, const char **argv, int env)
193 /* Let getopt produce error messages for the command line,
194 but not for options from the environment. */
196 + opterr = origin == o_command;
197 /* Reset getopt's state. */
200 @@ -3135,7 +3136,7 @@ decode_switches (int argc, const char **argv, int env)
203 /* An argument not starting with a dash. */
204 - handle_non_switch_argument (coptarg, env);
205 + handle_non_switch_argument (coptarg, origin);
207 /* Bad option. We will print a usage message and die later.
208 But continue to parse the other options so the user can
209 @@ -3149,7 +3150,7 @@ decode_switches (int argc, const char **argv, int env)
210 this switch. We test this individually inside the
211 switch below rather than just once outside it, so that
212 options which are to be ignored still consume args. */
213 - int doit = !env || cs->env;
214 + int doit = origin == o_command || cs->env;
218 @@ -3299,9 +3300,9 @@ decode_switches (int argc, const char **argv, int env)
219 to be returned in order, this only happens when there is a "--"
220 argument to prevent later arguments from being options. */
221 while (optind < argc)
222 - handle_non_switch_argument (argv[optind++], env);
223 + handle_non_switch_argument (argv[optind++], origin);
226 + if (bad && origin == o_command)
229 /* If there are any options that need to be decoded do it now. */
230 @@ -3321,7 +3322,7 @@ decode_switches (int argc, const char **argv, int env)
234 -decode_env_switches (const char *envar, size_t len)
235 +decode_env_switches (const char *envar, size_t len, enum variable_origin origin)
237 char *varref = alloca (2 + len + 2);
238 char *value, *p, *buf;
239 @@ -3383,7 +3384,7 @@ decode_env_switches (const char *envar, size_t len)
242 /* Parse those words. */
243 - decode_switches (argc, argv, 1);
244 + decode_switches (argc, argv, origin);
247 /* Quote the string IN so that it will be interpreted as a single word with
248 @@ -3408,11 +3409,11 @@ quote_for_env (char *out, const char *in)
251 /* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the
252 - command switches. Include options with args if ALL is nonzero.
253 + command switches. Always include options with args.
254 Don't include options with the 'no_makefile' flag set if MAKEFILE. */
256 -static struct variable *
257 -define_makeflags (int all, int makefile)
259 +define_makeflags (int makefile)
261 const char ref[] = "MAKEOVERRIDES";
262 const char posixref[] = "-*-command-variables-*-";
263 @@ -3597,25 +3598,24 @@ define_makeflags (int all, int makefile)
264 p = mempcpy (p, evalref, CSTRLEN (evalref));
269 - /* If there are any overrides to add, write a reference to
270 - $(MAKEOVERRIDES), which contains command-line variable definitions.
271 - Separate the variables from the switches with a "--" arg. */
273 + /* If there are any overrides to add, write a reference to
274 + $(MAKEOVERRIDES), which contains command-line variable definitions.
275 + Separate the variables from the switches with a "--" arg. */
277 - const char *r = posix_pedantic ? posixref : ref;
278 - size_t l = strlen (r);
279 - v = lookup_variable (r, l);
280 + const char *r = posix_pedantic ? posixref : ref;
281 + size_t l = strlen (r);
282 + v = lookup_variable (r, l);
284 - if (v && v->value && v->value[0] != '\0')
286 - p = stpcpy (p, " -- ");
289 - p = mempcpy (p, r, l);
293 + if (v && v->value && v->value[0] != '\0')
295 + p = stpcpy (p, " -- ");
298 + p = mempcpy (p, r, l);
303 /* If there is a leading dash, omit it. */
304 if (flagstring[0] == '-')
305 diff --git a/src/makeint.h b/src/makeint.h
306 index c726abe..d6ac21b 100644
309 @@ -558,7 +558,11 @@ void out_of_memory (void) NORETURN;
310 #define ONS(_t,_a,_f,_n,_s) _t((_a), INTSTR_LENGTH + strlen (_s), \
313 -void decode_env_switches (const char*, size_t line);
314 +enum variable_origin;
315 +void decode_env_switches (const char*, size_t line,
316 + enum variable_origin origin);
318 +struct variable *define_makeflags (int makefile);
319 void temp_stdin_unlink (void);
320 void die (int) NORETURN;
321 void pfatal_with_name (const char *) NORETURN;
322 diff --git a/src/variable.c b/src/variable.c
323 index 0bd9963..d8bf428 100644
326 @@ -1215,7 +1215,7 @@ target_environment (struct file *file, int recursive)
329 static struct variable *
330 -set_special_var (struct variable *var)
331 +set_special_var (struct variable *var, enum variable_origin origin)
333 if (streq (var->name, RECIPEPREFIX_NAME))
335 @@ -1225,7 +1225,10 @@ set_special_var (struct variable *var)
336 cmd_prefix = var->value[0]=='\0' ? RECIPEPREFIX_DEFAULT : var->value[0];
338 else if (streq (var->name, MAKEFLAGS_NAME))
339 - decode_env_switches (STRING_SIZE_TUPLE(MAKEFLAGS_NAME));
341 + decode_env_switches (STRING_SIZE_TUPLE(MAKEFLAGS_NAME), origin);
342 + define_makeflags (rebuilding_makefiles);
347 @@ -1261,7 +1264,7 @@ do_variable_definition (const floc *flocp, const char *varname,
348 const char *value, enum variable_origin origin,
349 enum variable_flavor flavor, int target_var)
352 + const char *newval;
353 char *alloc_value = NULL;
356 @@ -1276,7 +1279,7 @@ do_variable_definition (const floc *flocp, const char *varname,
357 We have to allocate memory since otherwise it'll clobber the
358 variable buffer, and we may still need that if we're looking at a
359 target-specific variable. */
360 - p = alloc_value = allocated_variable_expand (value);
361 + newval = alloc_value = allocated_variable_expand (value);
365 @@ -1285,16 +1288,16 @@ do_variable_definition (const floc *flocp, const char *varname,
366 tokens to '$$' to resolve to '$' when recursively expanded. */
367 char *t = allocated_variable_expand (value);
368 char *np = alloc_value = xmalloc (strlen (t) * 2 + 1);
370 - while (p[0] != '\0')
372 + while (op[0] != '\0')
383 + newval = alloc_value;
387 @@ -1302,9 +1305,10 @@ do_variable_definition (const floc *flocp, const char *varname,
388 /* A shell definition "var != value". Expand value, pass it to
389 the shell, and store the result in recursively-expanded var. */
390 char *q = allocated_variable_expand (value);
391 - p = alloc_value = shell_result (q);
392 + alloc_value = shell_result (q);
394 flavor = f_recursive;
395 + newval = alloc_value;
399 @@ -1320,7 +1324,7 @@ do_variable_definition (const floc *flocp, const char *varname,
401 /* A recursive variable definition "var = value".
402 The value is used verbatim. */
408 @@ -1345,15 +1349,16 @@ do_variable_definition (const floc *flocp, const char *varname,
410 /* There was no old value.
411 This becomes a normal recursive definition. */
414 flavor = f_recursive;
418 /* Paste the old and new values together in VALUE. */
420 - size_t oldlen, vallen;
421 + size_t oldlen, vallen, alloclen;
427 @@ -1378,18 +1383,25 @@ do_variable_definition (const floc *flocp, const char *varname,
430 oldlen = strlen (v->value);
431 - p = alloc_value = xmalloc (oldlen + 1 + vallen + 1);
432 + alloclen = oldlen + 1 + vallen + 1;
433 + cp = alloc_value = xmalloc (alloclen);
437 - memcpy (alloc_value, v->value, oldlen);
438 - alloc_value[oldlen] = ' ';
441 + if (streq (varname, MAKEFLAGS_NAME)
442 + && (s = strstr (v->value, " -- ")))
443 + /* We found a separator in MAKEFLAGS. Ignore variable
444 + assignments: set_special_var() will reconstruct things. */
445 + cp = mempcpy (cp, v->value, s - v->value);
447 + cp = mempcpy (cp, v->value, oldlen);
451 - memcpy (&alloc_value[oldlen], val, vallen + 1);
453 + memcpy (cp, val, vallen + 1);
455 + newval = alloc_value;
459 @@ -1399,6 +1411,8 @@ do_variable_definition (const floc *flocp, const char *varname,
466 /* Many Unix Makefiles include a line saying "SHELL=/bin/sh", but
467 non-Unix systems don't conform to this default configuration (in
468 @@ -1440,16 +1454,16 @@ do_variable_definition (const floc *flocp, const char *varname,
472 - shellbase = strrchr (p, '/');
473 - bslash = strrchr (p, '\\');
474 + shellbase = strrchr (newval, '/');
475 + bslash = strrchr (newval, '\\');
476 if (!shellbase || bslash > shellbase)
478 - if (!shellbase && p[1] == ':')
480 + if (!shellbase && newval[1] == ':')
481 + shellbase = newval + 1;
486 + shellbase = newval;
488 /* Search for the basename of the shell (with standard
489 executable extensions) along the $PATH. */
490 @@ -1490,7 +1504,7 @@ do_variable_definition (const floc *flocp, const char *varname,
491 set no_default_sh_exe to indicate sh was found and
492 set new value for SHELL variable. */
494 - if (find_and_set_default_shell (p))
495 + if (find_and_set_default_shell (newval))
497 v = define_variable_in_set (varname, strlen (varname), default_shell,
498 origin, flavor == f_recursive,
499 @@ -1504,11 +1518,11 @@ do_variable_definition (const floc *flocp, const char *varname,
501 char *tp = alloc_value;
503 - alloc_value = allocated_variable_expand (p);
504 + alloc_value = allocated_variable_expand (newval);
506 if (find_and_set_default_shell (alloc_value))
508 - v = define_variable_in_set (varname, strlen (varname), p,
509 + v = define_variable_in_set (varname, strlen (varname), newval,
510 origin, flavor == f_recursive,
512 ? current_variable_set_list->set
513 @@ -1536,7 +1550,7 @@ do_variable_definition (const floc *flocp, const char *varname,
514 invoked in places where we want to define globally visible variables,
515 make sure we define this variable in the global set. */
517 - v = define_variable_in_set (varname, strlen (varname), p, origin,
518 + v = define_variable_in_set (varname, strlen (varname), newval, origin,
519 flavor == f_recursive || flavor == f_expand,
521 ? current_variable_set_list->set : NULL),
522 @@ -1546,7 +1560,7 @@ do_variable_definition (const floc *flocp, const char *varname,
526 - return v->special ? set_special_var (v) : v;
527 + return v->special ? set_special_var (v, origin) : v;
530 /* Parse P (a null-terminated string) as a variable definition.
531 diff --git a/tests/scripts/variables/MAKEFLAGS b/tests/scripts/variables/MAKEFLAGS
532 index a41f1cf..e81c327 100644
533 --- a/tests/scripts/variables/MAKEFLAGS
534 +++ b/tests/scripts/variables/MAKEFLAGS
535 @@ -65,79 +65,113 @@ rmdir('bar');
536 # Test that command line switches are all present in MAKEFLAGS.
542 @opts = ('i', 'k', 'n', 'q', 'r', 's', 'w', 'd');
543 exists $FEATURES{'check-symlink'} and push @opts, 'L';
544 +@flavors = ('=', ':=', ':::=', '+=-');
546 +for my $fl (@flavors) {
547 for my $opt (@opts) {
550 -all:; $(info makeflags='$(MAKEFLAGS)')
551 -!, "-$opt", "/makeflags='B$opt'/");
554 +all:; \$(info makeflags='\$(MAKEFLAGS)')
555 +", "-$opt", "/makeflags='B$opt'/");
559 # Switches which carry arguments.
560 @opts = (' -I/tmp', ' -Onone', ' --debug=b', ' -l2.5');
561 +for my $fl (@flavors) {
562 for my $opt (@opts) {
565 -all:; $(info makeflags='$(MAKEFLAGS)')
566 -!, "$opt", "/makeflags='B$opt'/");
569 +all:; \$(info makeflags='\$(MAKEFLAGS)')
570 +", "$opt", "/makeflags='B$opt'/");
574 # Long options which take no arguments.
576 @opts = (' --no-print-directory', ' --warn-undefined-variables', ' --trace');
577 +for my $fl (@flavors) {
578 for my $opt (@opts) {
581 -all:; $(info makeflags='$(MAKEFLAGS)')
582 -!, "$opt", "/makeflags='B$opt'/");
585 +all:; \$(info makeflags='\$(MAKEFLAGS)')
586 +", "$opt", "/makeflags='B$opt'/");
590 # Test that make filters out duplicates.
591 # Each option is specified in the makefile, env and on the command line.
592 @opts = (' -I/tmp', ' -Onone', ' --debug=b', ' -l2.5');
593 -$ENV{'MAKEFLAGS'} = $opt;
594 +for my $fl (@flavors) {
595 for my $opt (@opts) {
596 +$ENV{'MAKEFLAGS'} = $opt;
599 +MAKEFLAGS${fl}B $opt
600 all:; \$(info makeflags='\$(MAKEFLAGS)')
601 ", "$opt", "/makeflags='B$opt'/");
605 # Test that make filters out duplicates.
606 # Each option is specified in the makefile, env and on the command line.
607 # decode_switches reallocates when the number of parameters in sl->list exceeds 5.
608 # This test exercises the realloc branch.
609 +for my $fl (@flavors) {
610 $ENV{'MAKEFLAGS'} = '-I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6 -I2 -I2';
612 -MAKEFLAGS:=B -I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6 -I2 -I2
613 -all:; $(info makeflags='$(MAKEFLAGS)')
616 +MAKEFLAGS${fl}B -I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6 -I2 -I2
617 +all:; \$(info makeflags='\$(MAKEFLAGS)')
619 '-I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6',
620 "/makeflags='B -I1 -I2 -I3 -I4 -I5 -I6 -l2.5 -Onone --debug=b'/");
623 # A mix of multiple flags from env, the makefile and command line.
624 # Skip -L since it's not available everywhere
625 +for my $fl (@flavors) {
626 $ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn-undefined-variables --trace';
628 -MAKEFLAGS:=iknqrswd -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5
629 -all:; $(info makeflags='$(MAKEFLAGS)')
632 +MAKEFLAGS${fl}iknqrswd -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5
633 +all:; \$(info makeflags='\$(MAKEFLAGS)')
635 '-Onone -l2.5 -l2.5 -Onone -I/tmp -iknqrswd -i -n -s -k -I/tmp',
636 "/makeflags='Bdiknqrsw -I/tmp -l2.5 -Onone --trace --warn-undefined-variables'/");
639 -# Verify MAKEFLAGS are all available to shell functions
640 +# Verify MAKEFLAGS are all available to shell function at parse time.
641 +for my $fl (@flavors) {
642 +my $answer = 'Biknqrs -I/tmp -l2.5 -Onone --no-print-directory --warn-undefined-variables';
643 $ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn-undefined-variables';
645 -MAKEFLAGS := iknqrsw -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5 --no-print-directory
646 -XX := $(shell echo "$$MAKEFLAGS")
647 -all:; $(info makeflags='$(XX)')
649 - '-Onone -l2.5 -l2.5 -Onone -I/tmp -iknqrs -i -n -s -k -I/tmp',
650 - "makeflags='iknqrsw -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5 --no-print-directory'");
652 +MAKEFLAGS${fl}iknqrsw -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5 --no-print-directory
653 +\$(info at parse time '\$(MAKEFLAGS)')
654 +XX := \$(shell echo \"\$\$MAKEFLAGS\")
655 +all:; \$(info at build time makeflags='\$(XX)')
657 +'-Onone -l2.5 -l2.5 -Onone -I/tmp -iknqrs -i -n -s -k -I/tmp',
658 +"at parse time '$answer'
659 +at build time makeflags='$answer'");
662 +# Verify MAKEFLAGS and command line definitions are all available to shell function at parse time.
663 +for my $fl (@flavors) {
664 +$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn-undefined-variables';
665 +my $answer = 'Biknqrs -I/tmp -l2.5 -Onone --no-print-directory --warn-undefined-variables -- hello=world';
667 +MAKEFLAGS${fl}iknqrsw -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5 --no-print-directory
668 +\$(info at parse time '\$(MAKEFLAGS)')
669 +XX := \$(shell echo \"\$\$MAKEFLAGS\")
670 +all:; \$(info at build time makeflags='\$(XX)')
672 +'-Onone -l2.5 -l2.5 -Onone -I/tmp -iknqrs -i -n -s -k -I/tmp hello=world',
673 +"at parse time '$answer'
674 +at build time makeflags='$answer'");
677 # Verify that command line arguments are included in MAKEFLAGS
679 @@ -155,4 +189,183 @@ echo /erR --trace --no-print-directory -- FOO=bar/
680 /erR --trace --no-print-directory -- FOO=bar/");
684 +# Verify that command line arguments are included in MAKEFLAGS
685 +# when makefiles are parsed.
686 +my $answer = 'erR -- hello:=world FOO=bar';
688 +$(info $(MAKEFLAGS))
689 +all:; $(info $(MAKEFLAGS))
690 +!, '-e FOO=bar -r -R hello:=world',
693 +#MAKE#: 'all' is up to date.\n");
696 +# Same as above, with makefile setting the value of the same variables as
697 +# defined on the cli.
698 +my $answer = 'erR -- hello:=world FOO=bar';
700 +$(info $(MAKEFLAGS))
703 +$(info $(MAKEFLAGS))
704 +all:; $(info $(MAKEFLAGS))
705 +!, '-e FOO=bar -r -R hello:=world',
709 +#MAKE#: 'all' is up to date.\n");
712 +# Same as above, with makefile overriding the value of cli definition.
713 +my $answer = 'erR -- hello:=world FOO=bar';
715 +$(info $(MAKEFLAGS))
717 +override hello:=moon
719 +$(info $(MAKEFLAGS))
720 +all:; $(info $(MAKEFLAGS))
721 +!, '-e FOO=bar -r -R hello:=world',
725 +#MAKE#: 'all' is up to date.\n");
727 +# Same as above, and makefile overrides the value of cli definition.
728 +# resets MAKEOVERRIDES.
729 +my $answer = 'rR -- hello:=world FOO=bar';
731 +$(info $(MAKEFLAGS))
733 +override hello:=moon
735 +$(info $(MAKEFLAGS))
737 +$(info $(MAKEFLAGS))
738 +all:; $(info $(MAKEFLAGS))
739 +!, 'FOO=bar -r -R hello:=world',
743 +#MAKE#: 'all' is up to date.\n");
746 +# MAKEFLAGS set is env and makefile sets MAKEFLAGS and there is a command
748 +my $answer = ' -- bye=moon hello=world';
749 +$ENV{'MAKEFLAGS'} = 'hello=world';
751 +$(info $(MAKEFLAGS))
752 +all:; $(info $(MAKEFLAGS))
754 +" -- bye=moon hello=world
755 + -- bye=moon hello=world
756 +#MAKE#: 'all' is up to date.\n");
759 +# Conditional assignment and MAKEFLAGS.
760 +my $answer = 'B -- bye=moon hello=world';
761 +$ENV{'MAKEFLAGS'} = 'hello=world';
763 +$(info $(MAKEFLAGS))
765 +$(info $(MAKEFLAGS))
766 +all:; $(info $(MAKEFLAGS))
771 +#MAKE#: 'all' is up to date.\n");
774 +# MAKEFLAGS set is env and makefile sets MAKEFLAGS and there is a command
776 +for my $fl (@flavors) {
777 +my $answer = ' -- bye=moon hello=world';
778 +$ENV{'MAKEFLAGS'} = 'hello=world';
780 +\$(info \$(MAKEFLAGS))
782 +\$(info \$(MAKEFLAGS))
783 +all:; \$(info \$(MAKEFLAGS))
788 +#MAKE#: 'all' is up to date.\n");
792 +# Test changes introduced by makefiles to MAKEFLAGS.
793 +for my $fl (@flavors) {
794 +my $answer = 'rR --no-print-directory -- hello:=world FOO=bar';
796 +MAKEFLAGS+=--no-print-directory
797 +$(info $(MAKEFLAGS))
799 +$(info $(MAKEFLAGS))
800 +all:; $(info $(MAKEFLAGS))
801 +!, 'FOO=bar -r -R hello:=world',
805 +#MAKE#: 'all' is up to date.\n");
809 +# Test changes introduced by makefiles to MAKEFLAGS.
810 +# Same as above, but with -e.
811 +for my $fl (@flavors) {
812 +my $answer = 'erR -- hello:=world FOO=bar';
814 +MAKEFLAGS+=--no-print-directory
815 +$(info $(MAKEFLAGS))
817 +$(info $(MAKEFLAGS))
818 +all:; $(info $(MAKEFLAGS))
819 +!, '-e FOO=bar -r -R hello:=world',
823 +#MAKE#: 'all' is up to date.\n");
828 +create_file('bye/makefile',
830 +all:; $(info $(hello))');
833 +# Test that a cli definition takes precendence over a definition set in
836 +v:=$(shell $(MAKE) -C bye --no-print-directory)
838 +!, 'hello=world', "world #MAKE#[1]: 'all' is up to date.\n#MAKE#: 'all' is up to date.");
840 +# Same as above with the shell assignment operator.
842 +v \!= $(MAKE) -C bye --no-print-directory
844 +!, 'hello=world', "world #MAKE#[1]: 'all' is up to date.\n#MAKE#: 'all' is up to date.");
846 +unlink('bye/makefile');
850 +# Invalid command line variable definition.
852 +all:; $(info $(hello))
853 +!, 'hello=\'$(world\'', "#MAKEFILE#:2: *** unterminated variable reference. Stop.\n", 512);
856 +# An unused invalid command line variable definition is ignored.
859 +!, 'hello=\'$(world\'', "good\n#MAKE#: 'all' is up to date.\n");