mirror of
https://github.com/mirror/make.git
synced 2025-04-02 07:30:38 +08:00
[SV 64803] Set origin for unmodified variables after -e
Ensure the origin of all variables inherited from the environment is "environment override" if -e is given. Previously only variables that were set in the makefile had this origin. PDS: Most of these changes are from Dmitry but I slightly modified the algorithm: instead of rearranging the way in which MAKEFLAGS is parsed we reset the env_override value to the default before we re-parse MAKEFLAGS, then we set the origin of all env vars to the correct value based on the new setting. * NEWS: Mention the change for backward-compatibility. * src/main.c (main): Ensure MAKEFLAGS is always marked special. (reset_makeflags): Set env_overrides back to default before parsing MAKEFLAGS. (decode_switches): Call reset_env_override() to check for changes. * src/variable.h (reset_env_override): Declare a new function. * src/variable.c (reset_env_override): Go through all env variables and ensure the origin is correct based on env_overrides. (set_env_override): Helper function for the hash. * tests/scripts/functions/foreach: Fix tests. * tests/scripts/functions/let: Ditto. * tests/scripts/functions/origin: Ditto. * tests/scripts/options/dash-e: Add tests.
This commit is contained in:
parent
63b602e74f
commit
a382ac6cd1
5
NEWS
5
NEWS
@ -37,6 +37,11 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&se
|
|||||||
things like "ifeq ((foo,bar),)" are now syntax errors. Use a variable to
|
things like "ifeq ((foo,bar),)" are now syntax errors. Use a variable to
|
||||||
hide the comma if needed: "COMMA = ," / "ifeq ((foo$(COMMA)bar),)".
|
hide the comma if needed: "COMMA = ," / "ifeq ((foo$(COMMA)bar),)".
|
||||||
|
|
||||||
|
* WARNING: Backward-incompatibility!
|
||||||
|
If -e is given all environment variables will now have an origin of
|
||||||
|
"environment override" even if they are not otherwise set in the makefile.
|
||||||
|
See https://savannah.gnu.org/bugs/index.php?64803
|
||||||
|
|
||||||
* NOTE: Deprecated behavior.
|
* NOTE: Deprecated behavior.
|
||||||
The check in GNU Make 4.3 for suffix rules with prerequisites didn't check
|
The check in GNU Make 4.3 for suffix rules with prerequisites didn't check
|
||||||
single-suffix rules, only double-suffix rules. Add the missing check.
|
single-suffix rules, only double-suffix rules. Add the missing check.
|
||||||
|
12
src/main.c
12
src/main.c
@ -1445,6 +1445,7 @@ main (int argc, char **argv, char **envp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Initialize the special variables. */
|
/* Initialize the special variables. */
|
||||||
|
define_variable_cname ("MAKEFLAGS", "", o_default, 0)->special = 1;
|
||||||
define_variable_cname (".VARIABLES", "", o_default, 0)->special = 1;
|
define_variable_cname (".VARIABLES", "", o_default, 0)->special = 1;
|
||||||
/* define_variable_cname (".TARGETS", "", o_default, 0)->special = 1; */
|
/* define_variable_cname (".TARGETS", "", o_default, 0)->special = 1; */
|
||||||
define_variable_cname (".RECIPEPREFIX", "", o_default, 0)->special = 1;
|
define_variable_cname (".RECIPEPREFIX", "", o_default, 0)->special = 1;
|
||||||
@ -3090,6 +3091,8 @@ handle_non_switch_argument (const char *arg, enum variable_origin origin)
|
|||||||
void
|
void
|
||||||
reset_makeflags (enum variable_origin origin)
|
reset_makeflags (enum variable_origin origin)
|
||||||
{
|
{
|
||||||
|
/* Reset to default values. */
|
||||||
|
env_overrides = 0;
|
||||||
decode_env_switches (STRING_SIZE_TUPLE(MAKEFLAGS_NAME), origin);
|
decode_env_switches (STRING_SIZE_TUPLE(MAKEFLAGS_NAME), origin);
|
||||||
construct_include_path (include_dirs ? include_dirs->list : NULL);
|
construct_include_path (include_dirs ? include_dirs->list : NULL);
|
||||||
disable_builtins ();
|
disable_builtins ();
|
||||||
@ -3363,6 +3366,9 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
|
|||||||
|
|
||||||
/* Perform any special switch handling. */
|
/* Perform any special switch handling. */
|
||||||
run_silent = silent_flag;
|
run_silent = silent_flag;
|
||||||
|
|
||||||
|
/* Check variable priorities. */
|
||||||
|
reset_env_override ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decode switches from environment variable ENVAR (which is LEN chars long).
|
/* Decode switches from environment variable ENVAR (which is LEN chars long).
|
||||||
@ -3453,8 +3459,8 @@ quote_for_env (char *out, const char *in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Disable builtin variables and rules, if -R or -r is specified.
|
/* Disable builtin variables and rules, if -R or -r is specified.
|
||||||
* This function is called at parse time whenever MAKEFLAGS is modified and
|
This function is called at parse time whenever MAKEFLAGS is modified and
|
||||||
* also when the parsing phase is over. */
|
also when the parsing phase is over. */
|
||||||
|
|
||||||
static
|
static
|
||||||
void disable_builtins ()
|
void disable_builtins ()
|
||||||
@ -3837,7 +3843,7 @@ die (int status)
|
|||||||
verify_file_data_base ();
|
verify_file_data_base ();
|
||||||
|
|
||||||
/* Unload plugins before jobserver integrity check in case a plugin
|
/* Unload plugins before jobserver integrity check in case a plugin
|
||||||
* participates in jobserver. */
|
participates in jobserver. */
|
||||||
unload_all ();
|
unload_all ();
|
||||||
|
|
||||||
clean_jobserver (status);
|
clean_jobserver (status);
|
||||||
|
@ -564,9 +564,7 @@ lookup_variable (const char *name, size_t length)
|
|||||||
*nptr++ = '$';
|
*nptr++ = '$';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
*nptr++ = *sptr;
|
||||||
*nptr++ = *sptr;
|
|
||||||
}
|
|
||||||
sptr++;
|
sptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,12 +702,10 @@ initialize_file_variables (struct file *file, int reading)
|
|||||||
v->flavor = f_simple;
|
v->flavor = f_simple;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
v = do_variable_definition (
|
||||||
v = do_variable_definition (
|
&p->variable.fileinfo, p->variable.name, p->variable.value,
|
||||||
&p->variable.fileinfo, p->variable.name, p->variable.value,
|
p->variable.origin, p->variable.flavor,
|
||||||
p->variable.origin, p->variable.flavor,
|
p->variable.conditional, s_pattern);
|
||||||
p->variable.conditional, s_pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Also mark it as a per-target and copy export status. */
|
/* Also mark it as a per-target and copy export status. */
|
||||||
v->per_target = p->variable.per_target;
|
v->per_target = p->variable.per_target;
|
||||||
@ -1911,6 +1907,23 @@ warn_undefined (const char *name, size_t len)
|
|||||||
(int)len, name));
|
(int)len, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_env_override (const void *item, void *arg UNUSED)
|
||||||
|
{
|
||||||
|
struct variable *v = (struct variable *)item;
|
||||||
|
enum variable_origin old = env_overrides ? o_env : o_env_override;
|
||||||
|
enum variable_origin new = env_overrides ? o_env_override : o_env;
|
||||||
|
|
||||||
|
if (v->origin == old)
|
||||||
|
v->origin = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reset_env_override ()
|
||||||
|
{
|
||||||
|
hash_map_arg (&global_variable_set.table, set_env_override, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Print information for variable V, prefixing it with PREFIX. */
|
/* Print information for variable V, prefixing it with PREFIX. */
|
||||||
|
|
||||||
@ -1985,7 +1998,6 @@ print_variable (const void *item, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_auto_variable (const void *item, void *arg)
|
print_auto_variable (const void *item, void *arg)
|
||||||
{
|
{
|
||||||
@ -1995,7 +2007,6 @@ print_auto_variable (const void *item, void *arg)
|
|||||||
print_variable (item, arg);
|
print_variable (item, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_noauto_variable (const void *item, void *arg)
|
print_noauto_variable (const void *item, void *arg)
|
||||||
{
|
{
|
||||||
@ -2005,7 +2016,6 @@ print_noauto_variable (const void *item, void *arg)
|
|||||||
print_variable (item, arg);
|
print_variable (item, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Print all the variables in SET. PREFIX is printed before
|
/* Print all the variables in SET. PREFIX is printed before
|
||||||
the actual variable definitions (everything else is comments). */
|
the actual variable definitions (everything else is comments). */
|
||||||
|
|
||||||
|
@ -205,6 +205,7 @@ struct variable *define_variable_in_set (const char *name, size_t length,
|
|||||||
struct variable_set *set,
|
struct variable_set *set,
|
||||||
const floc *flocp);
|
const floc *flocp);
|
||||||
void warn_undefined (const char* name, size_t length);
|
void warn_undefined (const char* name, size_t length);
|
||||||
|
void reset_env_override (void);
|
||||||
|
|
||||||
/* Define a variable in the current variable set. */
|
/* Define a variable in the current variable set. */
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ all: auto for2
|
|||||||
auto : ; @echo $(av)
|
auto : ; @echo $(av)
|
||||||
for2: ; @echo $(fe)',
|
for2: ; @echo $(fe)',
|
||||||
'-e WHITE=WHITE CFLAGS=',
|
'-e WHITE=WHITE CFLAGS=',
|
||||||
"undefined file default file environment default file command line override automatic automatic
|
"undefined file default file environment override default file command line override automatic automatic
|
||||||
foo.o bletch.o null.o @.o garf.o .o .o undefined.o file.o default.o file.o environment.o default.o file.o command.o line.o override.o automatic.o automatic.o");
|
foo.o bletch.o null.o @.o garf.o .o .o undefined.o file.o default.o file.o environment.o override.o default.o file.o command.o line.o override.o automatic.o automatic.o");
|
||||||
|
|
||||||
# TEST 1: Test that foreach variables take precedence over global
|
# TEST 1: Test that foreach variables take precedence over global
|
||||||
# variables in a global scope (like inside an eval). Tests bug #11913
|
# variables in a global scope (like inside an eval). Tests bug #11913
|
||||||
|
@ -85,7 +85,7 @@ all: auto target
|
|||||||
auto: ; @echo $(let $(auto_var),,$(av)) $(av)
|
auto: ; @echo $(let $(auto_var),,$(av)) $(av)
|
||||||
$(let AR foo,bar foo ,$(eval $(value mktarget)))',
|
$(let AR foo,bar foo ,$(eval $(value mktarget)))',
|
||||||
'-e WHITE=WHITE CFLAGS=',
|
'-e WHITE=WHITE CFLAGS=',
|
||||||
"automatic automatic automatic automatic automatic automatic automatic automatic automatic undefined default environment default file command line override automatic automatic
|
"automatic automatic automatic automatic automatic automatic automatic automatic automatic undefined default environment override default file command line override automatic automatic
|
||||||
ar_foo _
|
ar_foo _
|
||||||
");
|
");
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ all: auto
|
|||||||
auto :
|
auto :
|
||||||
> @echo $(av)',
|
> @echo $(av)',
|
||||||
'-e WHITE=WHITE CFLAGS=',
|
'-e WHITE=WHITE CFLAGS=',
|
||||||
'undefined default environment default file command line override automatic
|
'undefined default environment override default file command line override automatic
|
||||||
undefined
|
undefined
|
||||||
default
|
default
|
||||||
environment
|
environment override
|
||||||
default
|
default
|
||||||
file
|
file
|
||||||
command line
|
command line
|
||||||
|
@ -21,4 +21,125 @@ recurse: ; @$(MAKE) -f #MAKEFILE#
|
|||||||
'-e --no-print-directory FOO=1 recurse',
|
'-e --no-print-directory FOO=1 recurse',
|
||||||
"FOO [command line]: 1\nFOO [command line]: 1\n#MAKE#[1]: 'all' is up to date.");
|
"FOO [command line]: 1\nFOO [command line]: 1\n#MAKE#[1]: 'all' is up to date.");
|
||||||
|
|
||||||
|
# SV 64803.
|
||||||
|
# Test that the origin of an env variable is 'enviroment override' when -e
|
||||||
|
# is set and the makefile does not modify the variable.
|
||||||
|
# First run the test without -e and then with -e.
|
||||||
|
|
||||||
|
mkdir('lib', 0777);
|
||||||
|
|
||||||
|
create_file('lib/makefile',
|
||||||
|
'$(info in submake value=$(hello), origin=$(origin hello))
|
||||||
|
all:; @echo "value=$(hello), origin=$(origin hello)"'."\n");
|
||||||
|
|
||||||
|
# No -e.
|
||||||
|
$ENV{hello} = 'world';
|
||||||
|
run_make_test(q!
|
||||||
|
.RECIPEPREFIX = >
|
||||||
|
$(info value=$(hello), origin=$(origin hello))
|
||||||
|
all:
|
||||||
|
> @echo "value=$(hello), origin=$(origin hello)"
|
||||||
|
> @$(MAKE) -C lib
|
||||||
|
.PHONY: lib all
|
||||||
|
!,
|
||||||
|
'-s',
|
||||||
|
"value=world, origin=environment\nvalue=world, origin=environment\n".
|
||||||
|
"in submake value=world, origin=environment\nvalue=world, origin=environment");
|
||||||
|
|
||||||
|
# -e is specified on the command line.
|
||||||
|
my @opts = ('-e', '--environment-overrides');
|
||||||
|
for my $opt (@opts) {
|
||||||
|
$ENV{hello} = 'world';
|
||||||
|
run_make_test(q!
|
||||||
|
.RECIPEPREFIX = >
|
||||||
|
$(info value=$(hello), origin=$(origin hello))
|
||||||
|
all:
|
||||||
|
> @echo "value=$(hello), origin=$(origin hello)"
|
||||||
|
> @$(MAKE) -C lib
|
||||||
|
.PHONY: lib all
|
||||||
|
!,
|
||||||
|
"-s $opt",
|
||||||
|
"value=world, origin=environment override\nvalue=world, origin=environment override\n".
|
||||||
|
"in submake value=world, origin=environment override\nvalue=world, origin=environment override");
|
||||||
|
}
|
||||||
|
|
||||||
|
# MAKEFLAGS from env affects top level make.
|
||||||
|
$ENV{hello} = 'world';
|
||||||
|
$ENV{MAKEFLAGS} = 'e';
|
||||||
|
run_make_test(q!
|
||||||
|
.RECIPEPREFIX = >
|
||||||
|
$(info value=$(hello), origin=$(origin hello))
|
||||||
|
all:
|
||||||
|
> @echo "value=$(hello), origin=$(origin hello)"
|
||||||
|
> @$(MAKE) -C lib
|
||||||
|
.PHONY: lib all
|
||||||
|
!,
|
||||||
|
"-s",
|
||||||
|
"value=world, origin=environment override\nvalue=world, origin=environment override\n".
|
||||||
|
"in submake value=world, origin=environment override\nvalue=world, origin=environment override");
|
||||||
|
|
||||||
|
# -e is passed to submake on the command line.
|
||||||
|
$ENV{hello} = 'world';
|
||||||
|
run_make_test(q!
|
||||||
|
.RECIPEPREFIX = >
|
||||||
|
$(info value=$(hello), origin=$(origin hello))
|
||||||
|
all:
|
||||||
|
> @echo "value=$(hello), origin=$(origin hello)"
|
||||||
|
> @$(MAKE) -e -C lib
|
||||||
|
.PHONY: lib all
|
||||||
|
!,
|
||||||
|
"-s",
|
||||||
|
"value=world, origin=environment\nvalue=world, origin=environment\n".
|
||||||
|
"in submake value=world, origin=environment override\nvalue=world, origin=environment override");
|
||||||
|
|
||||||
|
# MAKEFLAGS is reset for submake.
|
||||||
|
$ENV{hello} = 'world';
|
||||||
|
run_make_test(q!
|
||||||
|
.RECIPEPREFIX = >
|
||||||
|
$(info value=$(hello), origin=$(origin hello))
|
||||||
|
all:
|
||||||
|
> @echo "value=$(hello), origin=$(origin hello)"
|
||||||
|
> @$(MAKE) -C lib MAKEFLAGS=
|
||||||
|
.PHONY: lib all
|
||||||
|
!,
|
||||||
|
"-se",
|
||||||
|
"value=world, origin=environment override\nvalue=world, origin=environment override\n".
|
||||||
|
"in submake value=world, origin=environment\nvalue=world, origin=environment");
|
||||||
|
|
||||||
|
# Some MAKEFLAGS in top make env.
|
||||||
|
# This MAKEFLAGS does not conform to the format that make itself produces for
|
||||||
|
# submake. However, make still parses and honors this MAKEFLAGS.
|
||||||
|
# This test checks that make does not confuse 'e' in 'extramk' with '-e'.
|
||||||
|
$ENV{MAKEFLAGS} = 'r -Iextramk -k bye=moon';
|
||||||
|
$ENV{hello} = 'world';
|
||||||
|
run_make_test(q!
|
||||||
|
.RECIPEPREFIX = >
|
||||||
|
$(info value=$(hello), origin=$(origin hello))
|
||||||
|
all:
|
||||||
|
> @echo "value=$(hello), origin=$(origin hello)"
|
||||||
|
> @$(MAKE) -C lib
|
||||||
|
.PHONY: lib all
|
||||||
|
!,
|
||||||
|
"-s",
|
||||||
|
"value=world, origin=environment\nvalue=world, origin=environment\n".
|
||||||
|
"in submake value=world, origin=environment\nvalue=world, origin=environment");
|
||||||
|
|
||||||
|
# Some MAKEFLAGS in top make env.
|
||||||
|
# This MAKEFLAGS does not conform to the format that make itself produces for
|
||||||
|
# submake. However, make still parses and honors this MAKEFLAGS.
|
||||||
|
# This test checks that make detects '-e' in this MAKEFLAGS.
|
||||||
|
$ENV{MAKEFLAGS} = 'r -Iextramk -ke bye=moon';
|
||||||
|
$ENV{hello} = 'world';
|
||||||
|
run_make_test(q!
|
||||||
|
.RECIPEPREFIX = >
|
||||||
|
$(info value=$(hello), origin=$(origin hello))
|
||||||
|
all:
|
||||||
|
> @echo "value=$(hello), origin=$(origin hello)"
|
||||||
|
> @$(MAKE) -C lib
|
||||||
|
.PHONY: lib all
|
||||||
|
!,
|
||||||
|
"-s",
|
||||||
|
"value=world, origin=environment override\nvalue=world, origin=environment override\n".
|
||||||
|
"in submake value=world, origin=environment override\nvalue=world, origin=environment override");
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
Loading…
Reference in New Issue
Block a user