From f2771aa614d3a826b70973217c33f605fb4cd0c2 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Mon, 19 Apr 2021 17:27:54 -0400 Subject: [PATCH] [SV 58341] Add non-trivial options to $(MAKEFLAGS) Previously only trivial (single-letter) options were available in $(MAKEFLAGS) when it is examined from inside a makefile (the full value was set before expanding recipes). Ensure that all options (but, not command line variable overrides!) are visible in the $(MAKEFLAGS) variable. In order to do this reset the default values of options, particularly options which are lists, before re-reading MAKEFLAGS after makefiles have been read. Otherwise we'll get duplicate values for options such as -I. Unfortunately there are complications here as well: sometimes (for jobserver options in particular) we modify the values of these options while running: we must not reset these modifications. * NEWS: Announce this change * src/main.c (main): Call new reset_switches() before re-parsing MAKEFLAGS. (reset_switches): Reset the value of non-special options to their defaults. (define_makeflags): Add non-special options into MAKEFLAGS even if 'all' is not set. --- NEWS | 5 +++ src/main.c | 111 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/NEWS b/NEWS index 53562605..5efa8bad 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,11 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=109&se rebuilt is the same order in which make processed them, and this is defined to be true in the GNU make manual. +* WARNING: Backward-incompatibility! + Previously only simple (one-letter) options were added to the MAKEFLAGS + variable that was visible while parsing makefiles. Now, all options + are available in MAKEFLAGS. + * WARNING: New build requirement GNU make utilizes facilities from GNU Gnulib: Gnulib requires certain C99 features in the C compiler and so these features are required by GNU make: diff --git a/src/main.c b/src/main.c index d16d17a7..0f8a66dd 100644 --- a/src/main.c +++ b/src/main.c @@ -104,6 +104,7 @@ double atof (); static void clean_jobserver (int status); static void print_data_base (void); static void print_version (void); +static void reset_switches (); static void decode_switches (int argc, const char **argv, int env); static void decode_env_switches (const char *envar, size_t len); static struct variable *define_makeflags (int all, int makefile); @@ -1690,10 +1691,8 @@ main (int argc, char **argv, char **envp) { /* There's no -j option on the command line: check authorization. */ if (jobserver_parse_auth (jobserver_auth)) - { - /* Success! Use the jobserver. */ - goto job_setup_complete; - } + /* Success! Use the jobserver. */ + goto job_setup_complete; /* Oops: we have jobserver-auth but it's invalid :(. */ O (error, NILF, _("warning: jobserver unavailable: using -j1. Add '+' to parent make rule.")); @@ -1993,6 +1992,9 @@ main (int argc, char **argv, char **envp) int old_builtin_variables_flag = no_builtin_variables_flag; int old_arg_job_slots = arg_job_slots; + /* Reset switches that are taken from MAKEFLAGS so we don't get dups. */ + reset_switches (); + arg_job_slots = INVALID_JOB_SLOTS; /* Decode switches again, for variables set by the makefile. */ @@ -2840,6 +2842,52 @@ print_usage (int bad) fprintf (usageto, _("Report bugs to \n")); } +/* Reset switches that come from MAKEFLAGS and go to MAKEFLAGS. + Before re-parsing MAKEFLAGS after reading makefiles, start from scratch. */ + +static void +reset_switches () +{ + const struct command_switch *cs; + + for (cs = switches; cs->c != '\0'; ++cs) + if (cs->value_ptr && cs->env && cs->toenv) + switch (cs->type) + { + case ignore: + break; + + case flag: + case flag_off: + if (cs->default_value) + *(int *) cs->value_ptr = *(int *) cs->default_value; + break; + + case positive_int: + case string: + /* These types are handled specially... leave them alone :( */ + break; + + case floating: + if (cs->default_value) + *(double *) cs->value_ptr = *(double *) cs->default_value; + break; + + case filename: + case strlist: + { + /* The strings are in the cache so don't free them. */ + struct stringlist *sl = *(struct stringlist **) cs->value_ptr; + if (sl) + sl->idx = 0; + } + break; + + default: + abort (); + } +} + /* Decode switches from ARGC and ARGV. They came from the environment if ENV is nonzero. */ @@ -3005,9 +3053,8 @@ decode_switches (int argc, const char **argv, int env) coptarg = argv[optind++]; if (doit) - *(double *) cs->value_ptr - = (coptarg != 0 ? atof (coptarg) - : *(double *) cs->noarg_value); + *(double *) cs->value_ptr = (coptarg != 0 ? atof (coptarg) + : *(double *) cs->noarg_value); break; } @@ -3201,9 +3248,9 @@ define_makeflags (int all, int makefile) && (*(unsigned int *) cs->value_ptr == *(unsigned int *) cs->default_value))) break; - else if (cs->noarg_value != 0 - && (*(unsigned int *) cs->value_ptr == - *(unsigned int *) cs->noarg_value)) + if (cs->noarg_value != 0 + && (*(unsigned int *) cs->value_ptr == + *(unsigned int *) cs->noarg_value)) ADD_FLAG ("", 0); /* Optional value omitted; see below. */ else { @@ -3215,22 +3262,17 @@ define_makeflags (int all, int makefile) break; case floating: - if (all) + if (cs->default_value != 0 + && (*(double *) cs->value_ptr == *(double *) cs->default_value)) + break; + if (cs->noarg_value != 0 + && (*(double *) cs->value_ptr == *(double *) cs->noarg_value)) + ADD_FLAG ("", 0); /* Optional value omitted; see below. */ + else { - if (cs->default_value != 0 - && (*(double *) cs->value_ptr - == *(double *) cs->default_value)) - break; - else if (cs->noarg_value != 0 - && (*(double *) cs->value_ptr - == *(double *) cs->noarg_value)) - ADD_FLAG ("", 0); /* Optional value omitted; see below. */ - else - { - char *buf = alloca (100); - sprintf (buf, "%g", *(double *) cs->value_ptr); - ADD_FLAG (buf, strlen (buf)); - } + char *buf = alloca (100); + sprintf (buf, "%g", *(double *) cs->value_ptr); + ADD_FLAG (buf, strlen (buf)); } break; @@ -3245,16 +3287,15 @@ define_makeflags (int all, int makefile) case filename: case strlist: - if (all) - { - struct stringlist *sl = *(struct stringlist **) cs->value_ptr; - if (sl != 0) - { - unsigned int i; - for (i = 0; i < sl->idx; ++i) - ADD_FLAG (sl->list[i], strlen (sl->list[i])); - } - } + { + struct stringlist *sl = *(struct stringlist **) cs->value_ptr; + if (sl != 0) + { + unsigned int i; + for (i = 0; i < sl->idx; ++i) + ADD_FLAG (sl->list[i], strlen (sl->list[i])); + } + } break; default: