+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
{
unsigned int ocommands_started;
int x;
+
+ file->dontcare = g->dontcare;
+
check_renamed (file);
if (rebuilding_makefiles)
{
When they are all finished, the goal is finished. */
any_not_updated |= !file->updated;
+ file->dontcare = 0;
+
if (stop)
break;
}
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
/* 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)
/* 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 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)
+ fatal (NILF, msg_noparent, "", file->name, "");
+
+ fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
+ }
+
if (file->parent == 0)
- fatal (NILF, msg_noparent, "", file->name, "");
+ error (NILF, msg_noparent, "*** ", file->name, ".");
+ else
+ error (NILF, msg_parent, "*** ", file->name, file->parent->name, ".");
- fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
+ file->no_diag = 0;
}
-
- if (file->parent == 0)
- error (NILF, msg_noparent, "*** ", file->name, ".");
- else
- error (NILF, msg_parent, "*** ", file->name, file->parent->name, ".");
}
/* Consider a single `struct file' and update it as appropriate. */
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;
}
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. */
foo: bar; @:
', '', '');
-1;
-
# Make sure that we don't die when the command fails but we dontcare.
# (Savannah bug #13216).
-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;