mirror of
https://github.com/mirror/make.git
synced 2024-12-28 05:40:10 +08:00
parent
f907a4d90c
commit
56653d8524
22
ChangeLog
22
ChangeLog
@ -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>
|
2009-09-28 Paul Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* doc/make.texi (Pattern Intro): Move the match algorithm
|
* doc/make.texi (Pattern Intro): Move the match algorithm
|
||||||
|
1
dep.h
1
dep.h
@ -43,6 +43,7 @@ struct dep
|
|||||||
unsigned int ignore_mtime : 1;
|
unsigned int ignore_mtime : 1;
|
||||||
unsigned int staticpattern : 1;
|
unsigned int staticpattern : 1;
|
||||||
unsigned int need_2nd_expansion : 1;
|
unsigned int need_2nd_expansion : 1;
|
||||||
|
unsigned int dontcare : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,6 +94,8 @@ struct file
|
|||||||
pattern-specific variables. */
|
pattern-specific variables. */
|
||||||
unsigned int considered:1; /* equal to 'considered' if file has been
|
unsigned int considered:1; /* equal to 'considered' if file has been
|
||||||
considered on current scan of goal chain */
|
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
2
read.c
@ -384,7 +384,7 @@ eval_makefile (const char *filename, int flags)
|
|||||||
filename = deps->file->name;
|
filename = deps->file->name;
|
||||||
deps->changed = flags;
|
deps->changed = flags;
|
||||||
if (flags & RM_DONTCARE)
|
if (flags & RM_DONTCARE)
|
||||||
deps->file->dontcare = 1;
|
deps->dontcare = 1;
|
||||||
|
|
||||||
if (expanded)
|
if (expanded)
|
||||||
free (expanded);
|
free (expanded);
|
||||||
|
71
remake.c
71
remake.c
@ -133,6 +133,9 @@ update_goal_chain (struct dep *goals)
|
|||||||
{
|
{
|
||||||
unsigned int ocommands_started;
|
unsigned int ocommands_started;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
|
file->dontcare = g->dontcare;
|
||||||
|
|
||||||
check_renamed (file);
|
check_renamed (file);
|
||||||
if (rebuilding_makefiles)
|
if (rebuilding_makefiles)
|
||||||
{
|
{
|
||||||
@ -206,6 +209,8 @@ update_goal_chain (struct dep *goals)
|
|||||||
When they are all finished, the goal is finished. */
|
When they are all finished, the goal is finished. */
|
||||||
any_not_updated |= !file->updated;
|
any_not_updated |= !file->updated;
|
||||||
|
|
||||||
|
file->dontcare = 0;
|
||||||
|
|
||||||
if (stop)
|
if (stop)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -293,8 +298,14 @@ update_file (struct file *file, unsigned int depth)
|
|||||||
change is possible below here until then. */
|
change is possible below here until then. */
|
||||||
if (f->considered == considered)
|
if (f->considered == considered)
|
||||||
{
|
{
|
||||||
DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
|
/* Check for the case where a target has been tried and failed but
|
||||||
return f->command_state == cs_finished ? f->update_status : 0;
|
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
|
/* This loop runs until we start commands for a double colon rule, or until
|
||||||
@ -311,7 +322,7 @@ update_file (struct file *file, unsigned int depth)
|
|||||||
|
|
||||||
/* If we got an error, don't bother with double_colon etc. */
|
/* If we got an error, don't bother with double_colon etc. */
|
||||||
if (status != 0 && !keep_going_flag)
|
if (status != 0 && !keep_going_flag)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (f->command_state == cs_running
|
if (f->command_state == cs_running
|
||||||
|| f->command_state == cs_deps_running)
|
|| f->command_state == cs_deps_running)
|
||||||
@ -342,25 +353,48 @@ update_file (struct file *file, unsigned int depth)
|
|||||||
/* Show a message stating the target failed to build. */
|
/* Show a message stating the target failed to build. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
complain (const struct file *file)
|
complain (struct file *file)
|
||||||
{
|
{
|
||||||
const char *msg_noparent
|
const char *msg_noparent
|
||||||
= _("%sNo rule to make target `%s'%s");
|
= _("%sNo rule to make target `%s'%s");
|
||||||
const char *msg_parent
|
const char *msg_parent
|
||||||
= _("%sNo rule to make target `%s', needed by `%s'%s");
|
= _("%sNo rule to make target `%s', needed by `%s'%s");
|
||||||
|
|
||||||
if (!keep_going_flag)
|
/* 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
|
||||||
if (file->parent == 0)
|
failed is not necessarily this file but could be one of its direct
|
||||||
fatal (NILF, msg_noparent, "", file->name, "");
|
or indirect dependencies. So traverse this file's dependencies and
|
||||||
|
find the one that actually caused the failure. */
|
||||||
|
|
||||||
fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
|
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 (file->parent == 0)
|
if (d == 0)
|
||||||
error (NILF, msg_noparent, "*** ", file->name, ".");
|
{
|
||||||
else
|
/* Didn't find any dependencies to complain about. */
|
||||||
error (NILF, msg_parent, "*** ", file->name, file->parent->name, ".");
|
if (!keep_going_flag)
|
||||||
|
{
|
||||||
|
if (file->parent == 0)
|
||||||
|
fatal (NILF, msg_noparent, "", file->name, "");
|
||||||
|
|
||||||
|
fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->parent == 0)
|
||||||
|
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. */
|
/* 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,
|
DBF (DB_VERBOSE,
|
||||||
_("Recently tried and failed to update file `%s'.\n"));
|
_("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.
|
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
|
If we're trying to build it again in the normal rebuild, print a
|
||||||
message now. */
|
message now. */
|
||||||
if (file->dontcare && !rebuilding_makefiles)
|
if (file->no_diag && !file->dontcare)
|
||||||
{
|
|
||||||
file->dontcare = 0;
|
|
||||||
complain (file);
|
complain (file);
|
||||||
}
|
|
||||||
|
|
||||||
return file->update_status;
|
return file->update_status;
|
||||||
}
|
}
|
||||||
@ -417,6 +448,10 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine whether the diagnostics will be issued should this update
|
||||||
|
fail. */
|
||||||
|
file->no_diag = file->dontcare;
|
||||||
|
|
||||||
++depth;
|
++depth;
|
||||||
|
|
||||||
/* Notice recursive update of the same file. */
|
/* Notice recursive update of the same 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>
|
2009-09-28 Paul Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* scripts/functions/shell: Add regression test for Savannah bug
|
* scripts/functions/shell: Add regression test for Savannah bug
|
||||||
|
@ -90,8 +90,6 @@ all: ; @:
|
|||||||
foo: bar; @:
|
foo: bar; @:
|
||||||
', '', '');
|
', '', '');
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
|
|
||||||
# Make sure that we don't die when the command fails but we dontcare.
|
# Make sure that we don't die when the command fails but we dontcare.
|
||||||
# (Savannah bug #13216).
|
# (Savannah bug #13216).
|
||||||
@ -117,4 +115,54 @@ include
|
|||||||
-include
|
-include
|
||||||
sinclude', '', '');
|
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;
|
1;
|
||||||
|
Loading…
Reference in New Issue
Block a user