Fix Savannah bugs #15110, #25493, #12686, and #17740.

This commit is contained in:
Boris Kolpackov 2009-09-30 09:54:26 +00:00
parent f907a4d90c
commit 56653d8524
7 changed files with 135 additions and 21 deletions

View File

@ -1,3 +1,25 @@
2009-09-30 Boris Kolpackov <boris@codesynthesis.com>
* dep.h (dep): Add the DONTCARE bitfield.
* filedef.h (file):Add the NO_DIAG bitfield.
* read.c (eval_makefile): Set the DONTCARE flag in struct dep,
not struct file (a file can be a dependency of many targets,
some don't care, some do).
* remake.c (update_goal_chain): Propagate DONTCARE from struct
dep to struct file before updating the goal and restore it
afterwards.
(update_file): Don't prune the dependency graph if this target
has failed but the diagnostics hasn't been issued.
(complain): Scan the file's dependency graph to find the file
that caused the failure.
(update_file_1): Use NO_DIAG instead of DONTCARE to decide
whether to print diagnostics.
Fixes Savannah bugs #15110, #25493, #12686, and #17740.
2009-09-28 Paul Smith <psmith@gnu.org>
* doc/make.texi (Pattern Intro): Move the match algorithm

1
dep.h
View File

@ -43,6 +43,7 @@ struct dep
unsigned int ignore_mtime : 1;
unsigned int staticpattern : 1;
unsigned int need_2nd_expansion : 1;
unsigned int dontcare : 1;
};

View File

@ -94,6 +94,8 @@ struct file
pattern-specific variables. */
unsigned int considered:1; /* equal to 'considered' if file has been
considered on current scan of goal chain */
unsigned int no_diag:1; /* True if the file failed to update and no
diagnostics has been issued (dontcare). */
};

2
read.c
View File

@ -384,7 +384,7 @@ eval_makefile (const char *filename, int flags)
filename = deps->file->name;
deps->changed = flags;
if (flags & RM_DONTCARE)
deps->file->dontcare = 1;
deps->dontcare = 1;
if (expanded)
free (expanded);

View File

@ -133,6 +133,9 @@ update_goal_chain (struct dep *goals)
{
unsigned int ocommands_started;
int x;
file->dontcare = g->dontcare;
check_renamed (file);
if (rebuilding_makefiles)
{
@ -206,6 +209,8 @@ update_goal_chain (struct dep *goals)
When they are all finished, the goal is finished. */
any_not_updated |= !file->updated;
file->dontcare = 0;
if (stop)
break;
}
@ -292,10 +297,16 @@ update_file (struct file *file, unsigned int depth)
We won't reap_children until we start the next pass, so no state
change is possible below here until then. */
if (f->considered == considered)
{
/* Check for the case where a target has been tried and failed but
the diagnostics hasn't been issued. If we need the diagnostics
then we will have to continue. */
if (!(f->updated && f->update_status > 0 && !f->dontcare && f->no_diag))
{
DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
return f->command_state == cs_finished ? f->update_status : 0;
}
}
/* This loop runs until we start commands for a double colon rule, or until
the chain is exhausted. */
@ -342,13 +353,33 @@ update_file (struct file *file, unsigned int depth)
/* Show a message stating the target failed to build. */
static void
complain (const struct file *file)
complain (struct file *file)
{
const char *msg_noparent
= _("%sNo rule to make target `%s'%s");
const char *msg_parent
= _("%sNo rule to make target `%s', needed by `%s'%s");
/* If this file has no_diag set then it means we tried to update it
before in the dontcare mode and failed. The target that actually
failed is not necessarily this file but could be one of its direct
or indirect dependencies. So traverse this file's dependencies and
find the one that actually caused the failure. */
struct dep *d;
for (d = file->deps; d != 0; d = d->next)
{
if (d->file->updated && d->file->update_status > 0 && file->no_diag)
{
complain (d->file);
break;
}
}
if (d == 0)
{
/* Didn't find any dependencies to complain about. */
if (!keep_going_flag)
{
if (file->parent == 0)
@ -361,6 +392,9 @@ complain (const struct file *file)
error (NILF, msg_noparent, "*** ", file->name, ".");
else
error (NILF, msg_parent, "*** ", file->name, file->parent->name, ".");
file->no_diag = 0;
}
}
/* Consider a single `struct file' and update it as appropriate. */
@ -385,15 +419,12 @@ update_file_1 (struct file *file, unsigned int depth)
DBF (DB_VERBOSE,
_("Recently tried and failed to update file `%s'.\n"));
/* If the file we tried to make is marked dontcare then no message
/* If the file we tried to make is marked no_diag then no message
was printed about it when it failed during the makefile rebuild.
If we're trying to build it again in the normal rebuild, print a
message now. */
if (file->dontcare && !rebuilding_makefiles)
{
file->dontcare = 0;
if (file->no_diag && !file->dontcare)
complain (file);
}
return file->update_status;
}
@ -417,6 +448,10 @@ update_file_1 (struct file *file, unsigned int depth)
abort ();
}
/* Determine whether the diagnostics will be issued should this update
fail. */
file->no_diag = file->dontcare;
++depth;
/* Notice recursive update of the same file. */

View File

@ -1,3 +1,9 @@
2009-09-30 Boris Kolpackov <boris@codesynthesis.com>
* scripts/features/include: Add diagnostics issuing tests for
cases where targets have been updated and failed with the
dontcare flag. Savannah bugs #15110, #25493, #12686, #17740.
2009-09-28 Paul Smith <psmith@gnu.org>
* scripts/functions/shell: Add regression test for Savannah bug

View File

@ -90,8 +90,6 @@ all: ; @:
foo: bar; @:
', '', '');
1;
# Make sure that we don't die when the command fails but we dontcare.
# (Savannah bug #13216).
@ -117,4 +115,54 @@ include
-include
sinclude', '', '');
# Test that the diagnostics is issued even if the target has been
# tried before with the dontcare flag (direct dependency case).
#
run_make_test('
-include foo
all: bar
foo: baz
bar: baz
',
'',
"#MAKE#: *** No rule to make target `baz', needed by `bar'. Stop.\n",
512);
# Test that the diagnostics is issued even if the target has been
# tried before with the dontcare flag (indirect dependency case).
#
run_make_test('
-include foo
all: bar
foo: baz
bar: baz
baz: end
',
'',
"#MAKE#: *** No rule to make target `end', needed by `baz'. Stop.\n",
512);
# Test that the diagnostics is issued even if the target has been
# tried before with the dontcare flag (include/-include case).
#
run_make_test('
include bar
-include foo
all:
foo: baz
bar: baz
baz: end
',
'',
"#MAKEFILE#:2: bar: No such file or directory
#MAKE#: *** No rule to make target `end', needed by `baz'. Stop.\n",
512);
1;