- Fix Savannah bug #19108

- Fix Savannah bug #17752
- Test suite:
  * When tests fail keep a "run" file containing the command invoked.
  * Support for the Valgrind "memcheck" and "massif" tools.
This commit is contained in:
Paul Smith 2009-06-10 02:21:09 +00:00
parent d4ee001292
commit c8840352ac
8 changed files with 210 additions and 115 deletions

View File

@ -1,5 +1,13 @@
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.

View File

@ -423,7 +423,6 @@ pattern_search (struct file *file, int archive,
for (ri = 0; ri < nrules; ri++)
{
struct file *f;
unsigned int failed = 0;
int check_lastslash;
int file_variables_set = 0;
@ -678,7 +677,7 @@ pattern_search (struct file *file, int archive,
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;

170
remake.c
View File

@ -370,10 +370,11 @@ complain (const struct file *file)
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"));
@ -464,83 +465,94 @@ update_file_1 (struct file *file, unsigned int depth)
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);
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;
/* Inherit dontcare flag from our parent. */
if (rebuilding_makefiles)
while (d)
{
dontcare = d->file->dontcare;
d->file->dontcare = file->dontcare;
FILE_TIMESTAMP mtime;
int maybe_make;
int dontcare = 0;
check_renamed (d->file);
mtime = file_mtime (d->file);
check_renamed (d->file);
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;
/* Inherit dontcare flag from our parent. */
if (rebuilding_makefiles)
{
dontcare = d->file->dontcare;
d->file->dontcare = file->dontcare;
}
dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);
/* Restore original dontcare flag. */
if (rebuilding_makefiles)
d->file->dontcare = dontcare;
if (! d->ignore_mtime)
must_make = maybe_make;
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 (!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;
}
dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);
/* Restore original dontcare flag. */
if (rebuilding_makefiles)
d->file->dontcare = dontcare;
if (! d->ignore_mtime)
must_make = maybe_make;
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 (!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;
}
/* Now we know whether this target needs updating.
@ -981,7 +993,7 @@ check_dep (struct file *file, unsigned int depth,
/* 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
@ -990,7 +1002,7 @@ check_dep (struct file *file, unsigned int depth,
if (file->command_state != cs_running)
set_command_state (file, cs_not_started);
lastd = 0;
ld = 0;
d = file->deps;
while (d != 0)
{
@ -1000,7 +1012,7 @@ check_dep (struct file *file, unsigned int depth,
{
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);
@ -1008,9 +1020,9 @@ check_dep (struct file *file, unsigned int depth,
}
else
{
lastd->next = d->next;
ld->next = d->next;
free_dep (d);
d = lastd->next;
d = ld->next;
}
continue;
}
@ -1029,7 +1041,7 @@ check_dep (struct file *file, unsigned int depth,
|| d->file->command_state == cs_deps_running)
deps_running = 1;
lastd = d;
ld = d;
d = d->next;
}

View File

@ -1,5 +1,21 @@
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.

View File

@ -12,7 +12,7 @@
# (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
@ -28,10 +28,15 @@
# 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...
@ -54,9 +59,16 @@ sub valid_option
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.
@ -148,6 +160,8 @@ sub run_make_with_options {
$command .= " $options";
}
$command_string = "$command\n";
if ($valgrind) {
print VALGRIND "\n\nExecuting: $command\n";
}
@ -155,7 +169,10 @@ sub run_make_with_options {
{
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);
@ -183,10 +200,12 @@ sub run_make_with_options {
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;
}
@ -195,19 +214,28 @@ sub run_make_with_options {
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 {
@ -334,11 +362,12 @@ sub set_more_defaults
# 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));

View File

@ -15,11 +15,13 @@ $dir =~ s,.*/([^/]+)$,../$1,;
# 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
@ -41,9 +43,7 @@ a: void
@exit 0
3.implicit-phony:
',
'',
'');
!, '', '');
# TEST #1: make sure files that are built via implicit rules are marked
# as targets (Savannah bug #12202).
@ -160,5 +160,35 @@ p1.% p2.%: %.orig
',
'', "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;

View File

@ -28,20 +28,6 @@ cc foo.o -o foo');
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!

View File

@ -6,7 +6,7 @@
# 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
@ -435,16 +435,19 @@ sub run_each_test
$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
@ -691,6 +694,7 @@ sub compare_output
print "DIFFERENT OUTPUT\n" if $debug;
&create_file (&get_basefile, $answer);
&create_file (&get_runfile, $command_string);
print "\nCreating Difference File ...\n" if $debug;
@ -698,6 +702,8 @@ sub compare_output
local($command) = "diff -c " . &get_basefile . " " . $logfile;
&run_command_with_output(&get_difffile,$command);
} else {
&rmfiles ();
}
$suite_passed = 0;
@ -828,7 +834,7 @@ sub run_command_with_output
{
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;
@ -1201,6 +1207,15 @@ sub get_difffile
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.