mirror of
https://github.com/mirror/make.git
synced 2026-08-19 08:23:28 +08:00
[SV 64822, SV 36486] Fix appending to a pattern specific variable
Appending to a pattern specific variable produces an incorrect value in the presence of a command line definition or an env override of the variable. Also, fix pattern/target-specific appending to a variable with origin override. * At parse time record_target_var sets the value of a pattern specific variable to the value defined on command line or to the value of the env override. * Later, at build time, recursively_expand_for_file appends this value of the variable (set in record_target_var) to the command line value again, regardless of the origin of the variable. This patch modifies recursively_expand_for_file to avoid appending, unless the origin of the variable beats or equals the origin of one of the parent definitions of this variable. Reported by Rob <robw9739@gmail.com>, Brian Vandenberg <phantall@gmail.com>, Markus Oberhumer <markus@oberhumer.com>. * NEWS: Note the change. * src/variable.c (do_variable_definition): Avoid merging a pattern-specific variable with the parent definition when a command line or env override is present. * src/expand.c (recursively_expand_for_file): Avoid appending to a pattern-specific variable, unless the origin of this pattern-specific variable beats or equals the origin of one of the parent definitions of this variable. * doc/make.texi (Override Directive): Add missing cross-reference. * tests/scripts/variables/append: Add tests.
This commit is contained in:
committed by
Paul Smith
parent
a493d9ab6c
commit
07187db947
44
src/expand.c
44
src/expand.c
@@ -148,13 +148,14 @@ recursively_expand_for_file (struct variable *v, struct file *file)
|
||||
const floc **saved_varp;
|
||||
struct variable_set_list *savev = 0;
|
||||
int set_reading = 0;
|
||||
size_t nl = strlen (v->name);
|
||||
struct variable *parent = NULL;
|
||||
|
||||
/* If we're expanding to put into the environment of a shell function then
|
||||
ignore any recursion issues: for backward-compatibility we will use
|
||||
the value of the environment variable we were started with. */
|
||||
if (v->expanding && env_recursion)
|
||||
{
|
||||
size_t nl = strlen (v->name);
|
||||
char **ep;
|
||||
DB (DB_VERBOSE,
|
||||
(_("%s:%lu: not recursively expanding %s to export to shell function\n"),
|
||||
@@ -203,8 +204,49 @@ recursively_expand_for_file (struct variable *v, struct file *file)
|
||||
|
||||
v->expanding = 1;
|
||||
if (v->append)
|
||||
{
|
||||
/* Find a parent definition which is marked override. */
|
||||
struct variable_set_list *sl;
|
||||
for (sl = current_variable_set_list; sl && !parent; sl = sl->next)
|
||||
{
|
||||
struct variable *vp = lookup_variable_in_set (v->name, nl, sl->set);
|
||||
if (vp && vp != v && vp->origin == o_override)
|
||||
parent = vp;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent)
|
||||
/* PARENT is an override, V is appending. If V is also an override:
|
||||
override hello := first
|
||||
al%: override hello += second
|
||||
Then construct the value from its appended parts in the parent sets.
|
||||
Else if V is not an override:
|
||||
override hello := first
|
||||
al%: hello += second
|
||||
Then ignore the value of V and use the value of PARENT. */
|
||||
value = v->origin == o_override
|
||||
? allocated_variable_append (v)
|
||||
: xstrdup (parent->value);
|
||||
else if (v->origin == o_command || v->origin == o_env_override)
|
||||
/* Avoid appending to a pattern-specific variable, unless the origin of this
|
||||
pattern-specific variable beats or equals the origin of one of the parent
|
||||
definitions of this variable.
|
||||
This is needed, because if there is a command line definition or an env
|
||||
override, then the value defined in the makefile should only be appended
|
||||
in the case of a file override.
|
||||
In the presence of command line definition or env override and absence of
|
||||
makefile override, the value should be expanded, rather than appended. In
|
||||
this case, at parse time record_target_var already set the value of this
|
||||
pattern-specific variable to the value defined on the command line or to
|
||||
the env override value.
|
||||
User provided a command line definition or an env override.
|
||||
PARENT does not have an override directive, so ignore it. */
|
||||
value = allocated_expand_string (v->value);
|
||||
else if (v->append)
|
||||
/* Construct the value from its appended parts in the parent sets. */
|
||||
value = allocated_variable_append (v);
|
||||
else
|
||||
/* A definition without appending. */
|
||||
value = allocated_expand_string (v->value);
|
||||
v->expanding = 0;
|
||||
|
||||
|
||||
@@ -1432,29 +1432,56 @@ do_variable_definition (const floc *flocp, const char *varname, const char *valu
|
||||
case f_append:
|
||||
case f_append_value:
|
||||
{
|
||||
/* If we have += but we're in a target variable context, we want to
|
||||
append only with other variables in the context of this target. */
|
||||
if (scope)
|
||||
int override = 0;
|
||||
if (scope == s_global)
|
||||
v = lookup_variable (varname, strlen (varname));
|
||||
else
|
||||
{
|
||||
/* When appending in a target/pattern variable context, we want to
|
||||
append only with other variables in the context of this
|
||||
target/pattern. */
|
||||
append = 1;
|
||||
v = lookup_variable_in_set (varname, strlen (varname),
|
||||
current_variable_set_list->set);
|
||||
if (v)
|
||||
{
|
||||
/* Don't append from the global set if a previous non-appending
|
||||
target/pattern-specific variable definition exists. */
|
||||
if (!v->append)
|
||||
append = 0;
|
||||
|
||||
/* Don't append from the global set if a previous non-appending
|
||||
target-specific variable definition exists. */
|
||||
if (v && !v->append)
|
||||
append = 0;
|
||||
if (scope == s_pattern &&
|
||||
(v->origin == o_env_override || v->origin == o_command))
|
||||
{
|
||||
/* This is the case of multiple target/pattern specific
|
||||
definitions/appends, e.g.
|
||||
al%: hello := first
|
||||
al%: hello += second
|
||||
in the presence of a command line definition or an
|
||||
env override. Do not merge x->value and value here.
|
||||
For pattern-specific variables the values are merged in
|
||||
recursively_expand_for_file. */
|
||||
override = 1;
|
||||
append = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
v = lookup_variable (varname, strlen (varname));
|
||||
|
||||
if (v == 0)
|
||||
if (!v)
|
||||
{
|
||||
/* There was no old value.
|
||||
This becomes a normal recursive definition. */
|
||||
/* There was no old value: make this a recursive definition. */
|
||||
newval = value;
|
||||
flavor = f_recursive;
|
||||
}
|
||||
else if (override)
|
||||
{
|
||||
/* Command line definition / env override takes precedence over
|
||||
a pattern/target-specific append. */
|
||||
newval = value;
|
||||
/* Set flavor to f_recursive to recursively expand this variable
|
||||
at build time in recursively_expand_for_file. */
|
||||
flavor = f_recursive;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Paste the old and new values together in VALUE. */
|
||||
|
||||
Reference in New Issue
Block a user