diff --git a/ChangeLog b/ChangeLog index 177a2016..3b894add 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2009-09-30 Boris Kolpackov + + * 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 * doc/make.texi (Pattern Intro): Move the match algorithm diff --git a/dep.h b/dep.h index 305fb894..96964234 100644 --- a/dep.h +++ b/dep.h @@ -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; }; diff --git a/filedef.h b/filedef.h index 0d09e163..2881c0e8 100644 --- a/filedef.h +++ b/filedef.h @@ -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). */ }; diff --git a/read.c b/read.c index 2eb98fa1..7dd5090a 100644 --- a/read.c +++ b/read.c @@ -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); diff --git a/remake.c b/remake.c index a70cbeeb..67cde00e 100644 --- a/remake.c +++ b/remake.c @@ -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; } @@ -293,8 +298,14 @@ update_file (struct file *file, unsigned int depth) change is possible below here until then. */ if (f->considered == considered) { - DBF (DB_VERBOSE, _("Pruning file `%s'.\n")); - return f->command_state == cs_finished ? f->update_status : 0; + /* 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 @@ -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 (status != 0 && !keep_going_flag) - return status; + return status; if (f->command_state == cs_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. */ 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 (!keep_going_flag) - { - if (file->parent == 0) - fatal (NILF, msg_noparent, "", file->name, ""); + /* 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. */ - 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) - error (NILF, msg_noparent, "*** ", file->name, "."); - else - error (NILF, msg_parent, "*** ", file->name, file->parent->name, "."); + if (d == 0) + { + /* Didn't find any dependencies to complain about. */ + 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. */ @@ -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. */ diff --git a/tests/ChangeLog b/tests/ChangeLog index 5800d667..77b37e36 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2009-09-30 Boris Kolpackov + + * 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 * scripts/functions/shell: Add regression test for Savannah bug diff --git a/tests/scripts/features/include b/tests/scripts/features/include index 196a9879..7ad4112b 100644 --- a/tests/scripts/features/include +++ b/tests/scripts/features/include @@ -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;