2009-06-09 Paul Smith <psmith@gnu.org>
+ * remake.c (update_file_1): When rebuilding deps of FILE, also try
+ to rebuild the deps of all the also_make targets for that file.
+ Fixes Savannah bug #19108.
+
+ * implicit.c (pattern_search): Undo test for is_target, added by
+ BorisK on 21 Sep 2004. This goes against step 5c in the "Implicit
+ Rule Search Algorithm". Fixes Savannah bug #17752.
+
* main.c (clean_jobserver): Clear the jobserver_fds options and
set job_slots to the default when we clean up.
(define_makeflags): Return the new MAKEFLAGS value.
for (ri = 0; ri < nrules; ri++)
{
- struct file *f;
unsigned int failed = 0;
int check_lastslash;
int file_variables_set = 0;
so it might actually exist. */
/* @@ dep->changed check is disabled. */
- if (((f = lookup_file (name)) != 0 && f->is_target)
+ if (lookup_file (name) != 0
/*|| ((!dep->changed || check_lastslash) && */
|| file_exists_p (name))
continue;
static int
update_file_1 (struct file *file, unsigned int depth)
{
- register FILE_TIMESTAMP this_mtime;
+ FILE_TIMESTAMP this_mtime;
int noexist, must_make, deps_changed;
int dep_status = 0;
- register struct dep *d, *lastd;
+ struct dep *d, *ad;
+ struct dep amake;
int running = 0;
DBF (DB_VERBOSE, _("Considering target file `%s'.\n"));
file->cmds = default_file->cmds;
}
- /* Update all non-intermediate files we depend on, if necessary,
- and see whether any of them is more recent than this file. */
+ /* Update all non-intermediate files we depend on, if necessary, and see
+ whether any of them is more recent than this file. We need to walk our
+ deps, AND the deps of any also_make targets to ensure everything happens
+ in the correct order. */
- lastd = 0;
- d = file->deps;
- while (d != 0)
+ amake.file = file;
+ amake.next = file->also_make;
+ ad = &amake;
+ while (ad)
{
- FILE_TIMESTAMP mtime;
- int maybe_make;
- int dontcare = 0;
+ struct dep *lastd = 0;
- check_renamed (d->file);
+ /* Find the deps we're scanning */
+ d = ad->file->deps;
+ ad = ad->next;
- mtime = file_mtime (d->file);
- check_renamed (d->file);
+ while (d)
+ {
+ FILE_TIMESTAMP mtime;
+ int maybe_make;
+ int dontcare = 0;
- if (is_updating (d->file))
- {
- error (NILF, _("Circular %s <- %s dependency dropped."),
- file->name, d->file->name);
- /* We cannot free D here because our the caller will still have
- a reference to it when we were called recursively via
- check_dep below. */
- if (lastd == 0)
- file->deps = d->next;
- else
- lastd->next = d->next;
- d = d->next;
- continue;
- }
+ check_renamed (d->file);
- d->file->parent = file;
- maybe_make = must_make;
+ mtime = file_mtime (d->file);
+ check_renamed (d->file);
- /* Inherit dontcare flag from our parent. */
- if (rebuilding_makefiles)
- {
- dontcare = d->file->dontcare;
- d->file->dontcare = file->dontcare;
- }
+ if (is_updating (d->file))
+ {
+ error (NILF, _("Circular %s <- %s dependency dropped."),
+ file->name, d->file->name);
+ /* We cannot free D here because our the caller will still have
+ a reference to it when we were called recursively via
+ check_dep below. */
+ if (lastd == 0)
+ file->deps = d->next;
+ else
+ lastd->next = d->next;
+ d = d->next;
+ continue;
+ }
+ d->file->parent = file;
+ maybe_make = must_make;
- dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);
+ /* Inherit dontcare flag from our parent. */
+ if (rebuilding_makefiles)
+ {
+ dontcare = d->file->dontcare;
+ d->file->dontcare = file->dontcare;
+ }
- /* Restore original dontcare flag. */
- if (rebuilding_makefiles)
- d->file->dontcare = dontcare;
+ dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);
- if (! d->ignore_mtime)
- must_make = maybe_make;
+ /* Restore original dontcare flag. */
+ if (rebuilding_makefiles)
+ d->file->dontcare = dontcare;
- check_renamed (d->file);
+ if (! d->ignore_mtime)
+ must_make = maybe_make;
- {
- register struct file *f = d->file;
- if (f->double_colon)
- f = f->double_colon;
- do
- {
- running |= (f->command_state == cs_running
- || f->command_state == cs_deps_running);
- f = f->prev;
- }
- while (f != 0);
- }
+ check_renamed (d->file);
+
+ {
+ register struct file *f = d->file;
+ if (f->double_colon)
+ f = f->double_colon;
+ do
+ {
+ running |= (f->command_state == cs_running
+ || f->command_state == cs_deps_running);
+ f = f->prev;
+ }
+ while (f != 0);
+ }
- if (dep_status != 0 && !keep_going_flag)
- break;
+ if (dep_status != 0 && !keep_going_flag)
+ break;
- if (!running)
- /* The prereq is considered changed if the timestamp has changed while
- it was built, OR it doesn't exist. */
- d->changed = ((file_mtime (d->file) != mtime)
- || (mtime == NONEXISTENT_MTIME));
+ if (!running)
+ /* The prereq is considered changed if the timestamp has changed while
+ it was built, OR it doesn't exist. */
+ d->changed = ((file_mtime (d->file) != mtime)
+ || (mtime == NONEXISTENT_MTIME));
- lastd = d;
- d = d->next;
+ lastd = d;
+ d = d->next;
+ }
}
/* Now we know whether this target needs updating.
/* Otherwise, update all non-intermediate files we depend on, if
necessary, and see whether any of them is more recent than the
file on whose behalf we are checking. */
- struct dep *lastd;
+ struct dep *ld;
int deps_running = 0;
/* If this target is not running, set it's state so that we check it
if (file->command_state != cs_running)
set_command_state (file, cs_not_started);
- lastd = 0;
+ ld = 0;
d = file->deps;
while (d != 0)
{
{
error (NILF, _("Circular %s <- %s dependency dropped."),
file->name, d->file->name);
- if (lastd == 0)
+ if (ld == 0)
{
file->deps = d->next;
free_dep (d);
}
else
{
- lastd->next = d->next;
+ ld->next = d->next;
free_dep (d);
- d = lastd->next;
+ d = ld->next;
}
continue;
}
|| d->file->command_state == cs_deps_running)
deps_running = 1;
- lastd = d;
+ ld = d;
d = d->next;
}
2009-06-09 Paul Smith <psmith@gnu.org>
+ * scripts/features/patternrules: Test that dependencies of
+ "also_make" targets are created properly. Savannah bug #19108.
+
+ * test_driver.pl (compare_output): Create a "run" file for failed
+ tests containing the command that was run.
+ (get_runfile): New function.
+
+ * run_make_tests.pl (valid_option): Enhanced support for valgrind:
+ allow memcheck and massif tools.
+
+ * scripts/features/patternrules: Have to comment out a line in the
+ first test due to backing out a change that broke the implicit
+ rule search algorithm. Savannah bug #17752.
+ * scripts/misc/general4: Remove a test that is redundant with
+ patternrules.
+
* scripts/features/parallelism: Add a test for re-exec with
jobserver master override. Savannah bug #18124.
# (and others)
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
+
$valgrind = 0; # invoke make with valgrind
-$valgrind_args = '--num-callers=15 --tool=memcheck --leak-check=full';
+$valgrind_args = '';
+$memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full';
+$massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup';
$pure_log = undef;
+$command_string = '';
+
require "test_driver.pl";
# Some target systems might not have the POSIX module...
return 1;
}
- if ($option =~ /^-valgrind$/i) {
- $valgrind = 1;
- return 1;
+ if ($option =~ /^-(valgrind|memcheck)$/i) {
+ $valgrind = 1;
+ $valgrind_args = $memcheck_args;
+ return 1;
+ }
+
+ if ($option =~ /^-massif$/i) {
+ $valgrind = 1;
+ $valgrind_args = $massif_args;
+ return 1;
}
# This doesn't work--it _should_! Someone badly needs to fix this.
$command .= " $options";
}
+ $command_string = "$command\n";
+
if ($valgrind) {
print VALGRIND "\n\nExecuting: $command\n";
}
{
my $old_timeout = $test_timeout;
- $test_timeout = $timeout if $timeout;
+ $timeout and $test_timeout = $timeout;
+
+ # If valgrind is enabled, turn off the timeout check
+ $valgrind and $test_timeout = 0;
$code = &run_command_with_output($logname,$command);
if ($code != $expected_code) {
print "Error running $make_path (expected $expected_code; got $code): $command\n";
$test_passed = 0;
+ $runf = &get_runfile;
+ &create_file (&get_runfile, $command_string);
# If it's a SIGINT, stop here
if ($code & 127) {
print STDERR "\nCaught signal ".($code & 127)."!\n";
- exit($code);
+ ($code & 127) == 2 and exit($code);
}
return 0;
}
system "add_profile $make_path";
}
- 1;
+ return 1;
}
sub print_usage
{
&print_standard_usage ("run_make_tests",
- "[-make_path make_pathname] [-valgrind]",);
+ "[-make_path make_pathname] [-memcheck] [-massif]",);
}
sub print_help
{
- &print_standard_help ("-make_path",
- "\tYou may specify the pathname of the copy of make to run.");
+ &print_standard_help (
+ "-make_path",
+ "\tYou may specify the pathname of the copy of make to run.",
+ "-valgrind",
+ "-memcheck",
+ "\tRun the test suite under valgrind's memcheck tool.",
+ "\tChange the default valgrind args with the VALGRIND_ARGS env var.",
+ "-massif",
+ "\tRun the test suite under valgrind's massif toool.",
+ "\tChange the default valgrind args with the VALGRIND_ARGS env var."
+ );
}
sub get_this_pwd {
# Set up for valgrind, if requested.
if ($valgrind) {
+ my $args = $valgrind_args;
open(VALGRIND, "> valgrind.out")
|| die "Cannot open valgrind.out: $!\n";
# -q --leak-check=yes
- exists $ENV{VALGRIND_ARGS} and $valgrind_args = $ENV{VALGRIND_ARGS};
- $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $valgrind_args $make_path";
+ exists $ENV{VALGRIND_ARGS} and $args = $ENV{VALGRIND_ARGS};
+ $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $args $make_path";
# F_SETFD is 2
fcntl(VALGRIND, 2, 0) or die "fcntl(setfd) failed: $!\n";
system("echo Starting on `date` 1>&".fileno(VALGRIND));
# to match properly.
#
-run_make_test('
+run_make_test(q!
.PHONY: all
all: case.1 case.2 case.3
-a: void
+
+# We can't have this, due to "Implicit Rule Search Algorithm" step 5c
+#xxx: void
# 1 - existing file
%.1: void
@exit 0
3.implicit-phony:
-',
-'',
-'');
+!, '', '');
# TEST #1: make sure files that are built via implicit rules are marked
# as targets (Savannah bug #12202).
',
'', "foo.s1\np1.foo\n");
+# TEST 6: Make sure that non-target files are still eligible to be created
+# as part of implicit rule chaining. Savannah bug #17752.
+
+run_make_test(q!
+BIN = xyz
+COPY = $(BIN).cp
+SRC = $(BIN).c
+allbroken: $(COPY) $(BIN) ; @echo ok
+$(SRC): ; @echo 'main(){}' > $@
+%.cp: % ; @cp $< $@
+% : %.c ; @cp $< $@
+clean: ; @rm -rf $(SRC) $(COPY) $(BIN)
+!,
+ '', "ok\n");
+
+unlink(qw(xyz xyz.cp xyz.c));
+
+# TEST 7: Make sure that all prereqs of all "also_make" targets get created
+# before any of the things that depend on any of them. Savannah bug #19108.
+
+run_make_test(q!
+final: x ; @echo $@
+x: x.t1 x.t2 ; @echo $@
+x.t2: dep
+dep: ; @echo $@
+%.t1 %.t2: ; @echo $*.t1 ; echo $*.t2
+!,
+ '', "dep\nx.t1\nx.t2\nx\nfinal\n");
+
+
# This tells the test driver that the perl test script executed properly.
1;
unlink('foo.c');
-# Test other implicit rule searching
-
-&touch('bar');
-run_make_test('
-test.foo:
-%.foo : baz ; @echo done $<
-%.foo : bar ; @echo done $<
-fox: baz
-',
- '',
- 'done bar');
-unlink('bar');
-
-
# Test implicit rules with '$' in the name (see se_implicit)
run_make_test(q!
# Modified 92-02-11 through 92-02-22 by Chris Arthur to further generalize.
#
# Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-# 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
$logext = 'l';
$diffext = 'd';
$baseext = 'b';
+ $runext = 'r';
$extext = '';
} else {
$logext = 'log';
$diffext = 'diff';
$baseext = 'base';
+ $runext = 'run';
$extext = '.';
}
$log_filename = "$testpath.$logext";
$diff_filename = "$testpath.$diffext";
$base_filename = "$testpath.$baseext";
+ $run_filename = "$testpath.$runext";
$tmp_filename = "$testpath.$tmpfilesuffix";
&setup_for_test; # suite-defined
print "DIFFERENT OUTPUT\n" if $debug;
&create_file (&get_basefile, $answer);
+ &create_file (&get_runfile, $command_string);
print "\nCreating Difference File ...\n" if $debug;
local($command) = "diff -c " . &get_basefile . " " . $logfile;
&run_command_with_output(&get_difffile,$command);
+ } else {
+ &rmfiles ();
}
$suite_passed = 0;
{
my $filename = shift;
- print "\nrun_command_with_output($filename): @_\n" if $debug;
+ print "\nrun_command_with_output($filename,$runname): @_\n" if $debug;
&attach_default_output ($filename);
my $code = _run_command(@_);
&detach_default_output;
return ($diff_filename . &num_suffix ($num_of_logfiles));
}
+# This subroutine returns a command filename with a number appended
+# to the end corresponding to how many logfiles (and thus command files)
+# have been created in the current running test.
+
+sub get_runfile
+{
+ return ($run_filename . &num_suffix ($num_of_logfiles));
+}
+
# just like logfile, only a generic tmp filename for use by the test.
# they are automatically cleaned up unless -keep was used, or the test fails.
# Pass an argument of 1 to return the same filename as the previous call.