summaryrefslogtreecommitdiff
path: root/tests/scripts/features
diff options
context:
space:
mode:
Diffstat (limited to 'tests/scripts/features')
-rw-r--r--tests/scripts/features/archives7
-rw-r--r--tests/scripts/features/default_names2
-rw-r--r--tests/scripts/features/dircache31
-rw-r--r--tests/scripts/features/double_colon150
-rw-r--r--tests/scripts/features/errors29
-rw-r--r--tests/scripts/features/exec29
-rw-r--r--tests/scripts/features/export42
-rw-r--r--tests/scripts/features/grouped_targets74
-rw-r--r--tests/scripts/features/implicit_search483
-rw-r--r--tests/scripts/features/include270
-rw-r--r--tests/scripts/features/jobserver97
-rw-r--r--tests/scripts/features/load54
-rw-r--r--tests/scripts/features/loadapi103
-rw-r--r--tests/scripts/features/mult_rules22
-rw-r--r--tests/scripts/features/output-sync33
-rw-r--r--tests/scripts/features/parallelism95
-rw-r--r--tests/scripts/features/patternrules550
-rw-r--r--tests/scripts/features/reinvoke118
-rw-r--r--tests/scripts/features/se_explicit305
-rw-r--r--tests/scripts/features/se_implicit240
-rw-r--r--tests/scripts/features/se_statpat133
-rw-r--r--tests/scripts/features/statipattrules208
-rw-r--r--tests/scripts/features/targetvars155
-rw-r--r--tests/scripts/features/temp_stdin118
-rw-r--r--tests/scripts/features/varnesting12
-rw-r--r--tests/scripts/features/vpath139
-rw-r--r--tests/scripts/features/vpath245
-rw-r--r--tests/scripts/features/vpath341
-rw-r--r--tests/scripts/features/vpathgpath4
-rw-r--r--tests/scripts/features/vpathplus97
30 files changed, 3145 insertions, 541 deletions
diff --git a/tests/scripts/features/archives b/tests/scripts/features/archives
index dcd38e5..809bf21 100644
--- a/tests/scripts/features/archives
+++ b/tests/scripts/features/archives
@@ -35,16 +35,17 @@ my $ar = get_config('AR') || 'ar';
my $redir = '2>&1';
$redir = '' if $osname eq 'VMS';
-my $arflags = 'rv';
+# This is the value from src/default.c
+my $arflags = $osname eq 'aix' ? '-Xany -rv' : '-rv';
my $arvar = "AR=$ar";
# Newer versions of binutils can be built with --enable-deterministic-archives
# which forces all timestamps (among other things) to always be 0, defeating
# GNU make's archive support. See if ar supports the U option to disable it.
unlink('libxx.a');
-$_ = `$ar U$arflags libxx.a a1.o $redir`;
+$_ = `$ar ${arflags}U libxx.a a1.o $redir`;
if ($? == 0) {
- $arflags = 'Urv';
+ $arflags = "${arflags}U";
$arvar = "$arvar ARFLAGS=$arflags";
}
diff --git a/tests/scripts/features/default_names b/tests/scripts/features/default_names
index 2e83880..3ecbaab 100644
--- a/tests/scripts/features/default_names
+++ b/tests/scripts/features/default_names
@@ -15,7 +15,7 @@ open(MAKEFILE,"> makefile");
print MAKEFILE "SECOND: ; \@echo It chose makefile\n";
close(MAKEFILE);
-# DOS/WIN32/MacOSX platforms are case-insensitive / case-preserving, so
+# DOS/W32/MacOSX platforms are case-insensitive / case-preserving, so
# Makefile is the same file as makefile. Just test what we can here.
my $case_sensitive = 0;
diff --git a/tests/scripts/features/dircache b/tests/scripts/features/dircache
new file mode 100644
index 0000000..e5e8469
--- /dev/null
+++ b/tests/scripts/features/dircache
@@ -0,0 +1,31 @@
+# -*-mode: perl-*-
+
+$description = "Test the directory cache behavior.";
+
+# The first wildcard should bring the entire directory into the cache Then we
+# create a new file "behind make's back" then see if the next wildcard detects
+# it.
+
+run_make_test(q!
+_orig := $(wildcard ./*)
+$(shell echo > anewfile)
+_new := $(wildcard ./*)
+$(info diff=$(filter-out $(_orig),$(_new)))
+all:;@:
+!,
+ '', "diff=./anewfile\n");
+
+rmfiles('anewfile');
+
+run_make_test(q!
+_orig := $(wildcard ./*)
+$(file >anewfile)
+_new := $(wildcard ./*)
+$(info diff=$(filter-out $(_orig),$(_new)))
+all:;@:
+!,
+ '', "diff=./anewfile\n");
+
+rmfiles('anewfile');
+
+1;
diff --git a/tests/scripts/features/double_colon b/tests/scripts/features/double_colon
index 58f126f..a039b0a 100644
--- a/tests/scripts/features/double_colon
+++ b/tests/scripts/features/double_colon
@@ -12,12 +12,9 @@ We test these features:
Then we do the same thing for parallel builds: double-colon
targets should always be built serially.";
-# The Contents of the MAKEFILE ...
-
-open(MAKEFILE,"> $makefile");
-
-print MAKEFILE <<'EOF';
+# TEST 0: A simple double-colon rule that isn't the goal target.
+run_make_test(q!
all: baz
foo:: f1.h ; @echo foo FIRST
@@ -38,37 +35,23 @@ f1.h f2.h: ; @echo $@
d :: ; @echo ok
d :: d ; @echo oops
-
-EOF
-
-close(MAKEFILE);
-
-# TEST 0: A simple double-colon rule that isn't the goal target.
-
-&run_make_with_options($makefile, "all", &get_logfile, 0);
-$answer = "aaa\nbbb\n";
-&compare_output($answer, &get_logfile(1));
+!,
+ "all", "aaa\nbbb\n");
# TEST 1: As above, in parallel
if ($parallel_jobs) {
- &run_make_with_options($makefile, "-j10 all", &get_logfile, 0);
- $answer = "aaa\nbbb\n";
- &compare_output($answer, &get_logfile(1));
+ run_make_test(undef, "-j10 all", "aaa\nbbb\n");
}
# TEST 2: A simple double-colon rule that is the goal target
-&run_make_with_options($makefile, "bar", &get_logfile, 0);
-$answer = "aaa\naaa done\nbbb\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "bar", "aaa\naaa done\nbbb\n");
# TEST 3: As above, in parallel
if ($parallel_jobs) {
- &run_make_with_options($makefile, "-j10 bar", &get_logfile, 0);
- $answer = "aaa\naaa done\nbbb\n";
- &compare_output($answer, &get_logfile(1));
+ run_make_test(undef, "-j10 bar", "aaa\naaa done\nbbb\n");
}
# TEST 4: Each double-colon rule is supposed to be run individually
@@ -76,16 +59,12 @@ if ($parallel_jobs) {
&utouch(-5, 'f2.h');
&touch('foo');
-&run_make_with_options($makefile, "foo", &get_logfile, 0);
-$answer = "f1.h\nfoo FIRST\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "foo", "f1.h\nfoo FIRST\n");
# TEST 5: Again, in parallel.
if ($parallel_jobs) {
- &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
- $answer = "f1.h\nfoo FIRST\n";
- &compare_output($answer, &get_logfile(1));
+ run_make_test(undef, "-j10 foo", "f1.h\nfoo FIRST\n");
}
# TEST 6: Each double-colon rule is supposed to be run individually
@@ -94,32 +73,24 @@ if ($parallel_jobs) {
unlink('f2.h');
&touch('foo');
-&run_make_with_options($makefile, "foo", &get_logfile, 0);
-$answer = "f2.h\nfoo SECOND\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "foo", "f2.h\nfoo SECOND\n");
# TEST 7: Again, in parallel.
if ($parallel_jobs) {
- &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
- $answer = "f2.h\nfoo SECOND\n";
- &compare_output($answer, &get_logfile(1));
+ run_make_test(undef, "-j10 foo", "f2.h\nfoo SECOND\n");
}
# TEST 8: Test circular dependency check; PR/1671
-&run_make_with_options($makefile, "d", &get_logfile, 0);
-$answer = "ok\n$make_name: Circular d <- d dependency dropped.\noops\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "d", "ok\n$make_name: Circular d <- d dependency dropped.\noops\n");
# TEST 8: I don't grok why this is different than the above, but it is...
#
# Hmm... further testing indicates this might be timing-dependent?
#
#if ($parallel_jobs) {
-# &run_make_with_options($makefile, "-j10 biz", &get_logfile, 0);
-# $answer = "aaa\ntwo\nbbb\n";
-# &compare_output($answer, &get_logfile(1));
+# run_make_test(undef, "-j10 biz", "aaa\ntwo\nbbb\n");
#}
unlink('foo','f1.h','f2.h');
@@ -133,16 +104,17 @@ unlink('foo','f1.h','f2.h');
&touch('two');
run_make_test('
+.RECIPEPREFIX = >
.PHONY: all
all: result
result:: one
- @echo $^ >>$@
- @echo $^
+> @echo $^ >>$@
+> @echo $^
result:: two
- @echo $^ >>$@
- @echo $^
+> @echo $^ >>$@
+> @echo $^
',
'',
@@ -161,23 +133,25 @@ a\ xb :: ; @echo two
# Test 11: SV 44742 : All double-colon rules should be run in parallel build.
-run_make_test('result :: 01
- @echo update
- @touch $@
+run_make_test('
+.RECIPEPREFIX = >
+result :: 01
+> @echo update
+> @touch $@
result :: 02
- @echo update
- @touch $@
+> @echo update
+> @touch $@
result :: 03
- @echo update
- @touch $@
+> @echo update
+> @touch $@
result :: 04
- @echo update
- @touch $@
+> @echo update
+> @touch $@
result :: 05
- @echo update
- @touch $@
+> @echo update
+> @touch $@
01 02 03 04 05:
- @touch 01 02 03 04 05
+> @touch 01 02 03 04 05
',
'-j10 result', "update\nupdate\nupdate\nupdate\nupdate\n");
@@ -186,14 +160,10 @@ unlink('result', '01', '02', '03', '04', '05');
# Test 12: SV 44742 : Double-colon rules with parallelism
run_make_test('
-root: all
- echo root
-all::
- echo all_one
-all:: 3
- echo all_two
-%:
- sleep $*
+root: all ; echo root
+all:: ; echo all_one
+all:: 3 ; echo all_two
+%: ; sleep $*
',
'-rs -j2 1 2 root', "all_one\nall_two\nroot\n");
@@ -212,9 +182,49 @@ FORCE:
unlink('joe-is-forced');
+# sv 60188.
+# Even though test.x is explicitly mentioned, terminal pattern rules still
+# apply only if the prerequisite exists.
+touch('hello.z');
+
+# subtest 1. test.x is explicitly mentioned.
+run_make_test(q!
+all: hello.z
+%.z:: test.x ; touch $@
+%.x: ;
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.z');
+
+# subtest 2. hello.x is derived from the stem.
+touch('hello.z');
+
+run_make_test(q!
+all: hello.z
+%.z:: %.x; touch $@
+%.x: ; touch $@
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.z');
+
+# subtest 3
+# hello.x is explicitly mentioned on an unrelated rule and thus is not an
+# intermediate file.
+# Terminal pattern rules do not apply anyway and there is no rule to built
+# 'hello.x'.
+touch('hello.z');
+run_make_test(q!
+all: hello.z
+%.z:: %.x; touch $@
+%.x: ;
+unrelated: hello.x
+!,
+ '', "#MAKE#: *** No rule to make target 'hello.x', needed by 'hello.z'. Stop.\n", 512);
+
+unlink('hello.z');
+
+
# This tells the test driver that the perl test script executed properly.
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/features/errors b/tests/scripts/features/errors
index f236d51..2cdaf31 100644
--- a/tests/scripts/features/errors
+++ b/tests/scripts/features/errors
@@ -31,6 +31,18 @@ all:
!,
'', "hi\nthere\n#MAKE#: *** [#MAKEFILE#:5: all] Error 1", 512);
+# Windows error look completely different :-/
+
+sub errors_getinfo
+{
+ my ($cmd, $args) = @_;
+ if ($port_type eq 'W32') {
+ return (2, "process_begin: CreateProcess(NULL, $cmd $args, ...) failed.\nmake (e=2): The system cannot find the file specified.");
+ }
+
+ return (127, "#MAKE#: $cmd: $ERR_no_such_file");
+}
+
# TEST #3
# -------
@@ -38,35 +50,36 @@ all:
my $unk = './foobarbazbozblat';
unlink($unk);
-my $err = $ERR_no_such_file;
-
+my ($ernum, $erstr) = errors_getinfo($unk, "xx yy");
run_make_test(qq!
one: ; -$unk xx yy
-!,
- 'one', "$unk xx yy\n#MAKE#: $unk: $err\n#MAKE#: [#MAKEFILE#:2: one] Error 127 (ignored)\n");
+!, 'one',
+ "$unk xx yy\n$erstr\n#MAKE#: [#MAKEFILE#:2: one] Error $ernum (ignored)\n");
# TEST #4
# -------
+($ernum, $erstr) = errors_getinfo($unk, "aa bb");
run_make_test(qq!
two: ; $unk aa bb
!, 'two -i',
- "$unk aa bb\n#MAKE#: $unk: $err\n#MAKE#: [#MAKEFILE#:2: two] Error 127 (ignored)\n");
+ "$unk aa bb\n$erstr\n#MAKE#: [#MAKEFILE#:2: two] Error $ernum (ignored)\n");
# TEST #5
# -------
run_make_test(undef, 'two',
- "$unk aa bb\n#MAKE#: $unk: $err\n#MAKE#: *** [#MAKEFILE#:2: two] Error 127\n", 512);
+ "$unk aa bb\n$erstr\n#MAKE#: *** [#MAKEFILE#:2: two] Error $ernum\n", 512);
# SV #56918 : Test the unknown command as the second recipe line
+($ernum, $erstr) = errors_getinfo($unk, "qq rr");
run_make_test(qq!
three:
\t\@echo one
\t$unk qq rr
!, 'three',
- "one\n$unk qq rr\n#MAKE#: $unk: $err\n#MAKE#: *** [#MAKEFILE#:4: three] Error 127\n", 512);
+ "one\n$unk qq rr\n$erstr\n#MAKE#: *** [#MAKEFILE#:4: three] Error $ernum\n", 512);
# Try failing due to non-executable file
@@ -86,7 +99,7 @@ if ($ERR_nonexe_file) {
# Try failing by "running" a directory
if ($ERR_exe_dir) {
- mkdir('sd', 0775);
+ mkdir('sd', 0775) or print "mkdir: sd: $!\n";
run_make_test(q!
PATH := .
diff --git a/tests/scripts/features/exec b/tests/scripts/features/exec
index 91181f4..f139cf8 100644
--- a/tests/scripts/features/exec
+++ b/tests/scripts/features/exec
@@ -3,40 +3,49 @@
use warnings;
my $description = "Test that make can execute binaries as well as scripts with"
- ." various shabangs and without a shebang";
+ ." various shabangs and without a shbang";
my $details = "The various shells that this test uses are the default"
." /bin/sh, \$SHELL and the perl interpreter that is"
." executing this test program. The shells are used for the value"
- ." of SHELL inside the test makefile and also as a shebang in the"
+ ." of SHELL inside the test makefile and also as a shbang in the"
." executed script. There is also a test which executes a script"
- ." that has no shebang.";
+ ." that has no shbang.";
# Only bother with this on UNIX systems
$port_type eq 'UNIX' or return -1;
+$^O =~ /cygwin/ and return -1;
+my @shbangs = ('', '#!/bin/sh', "#!$perl_name");
+my @shells = ('', 'SHELL=/bin/sh');
+
+# Try whatever shell the user has, as long as it's not a C shell.
+# The C shell is not usable with make, due to not correctly handling
+# file descriptors and possibly other issues.
my $usersh = $origENV{SHELL};
-my $answer = 'hello, world';
+if ($usersh !~ /csh/) {
+ push @shbangs, ("#!$usersh");
+ push @shells, ("SHELL=$usersh");
+}
-my @shebangs = ('', '#!/bin/sh', "#!$usersh", "#!$perl_name");
-my @shells = ('', 'SHELL=/bin/sh', "SHELL=$usersh");
+my $answer = 'hello, world';
# tests [0-11]
# Have a makefile with various SHELL= exec a shell program with varios
-# shebangs or without a shebang at all.
+# shbangs or without a shbang at all.
my $stem = './exec.cmd';
my $k = 0;
-for my $shebang (@shebangs) {
+for my $shbang (@shbangs) {
for my $shell (@shells) {
my $cmd = $k ? "$stem.$k" : $stem;
++$k;
unlink $cmd;
open(CMD,"> $cmd");
- print CMD "$shebang\n";
+ print CMD "$shbang\n";
print CMD "printf \"$answer\\n\";\n";
close(CMD);
chmod 0700, $cmd;
- run_make_test(q!
+ run_make_test("# shbang=$shbang\n# shell=$shell" . q!
all:; @$(CMD)
!, "$shell CMD=$cmd", "$answer\n");
diff --git a/tests/scripts/features/export b/tests/scripts/features/export
index 81bff0c..ad58177 100644
--- a/tests/scripts/features/export
+++ b/tests/scripts/features/export
@@ -32,16 +32,17 @@ ifdef EXPORT_ALL_PSEUDO
.EXPORT_ALL_VARIABLES:
endif
+.RECIPEPREFIX := >
all:
- @echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)"
- @echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ"
+> @echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)"
+> @echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ"
',
'', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
# TEST 1: make sure vars inherited from the parent are exported
-$extraENV{FOO} = 1;
+$ENV{FOO} = 1;
&run_make_test(undef, '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
@@ -85,9 +86,10 @@ B = b
export $(FOO)
export $(B)ar
+.RECIPEPREFIX := >
all:
- @echo foo=$(foo) bar=$(bar)
- @echo foo=$$foo bar=$$bar
+> @echo foo=$(foo) bar=$(bar)
+> @echo foo=$$foo bar=$$bar
',
"", "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n");
@@ -108,9 +110,10 @@ export foo bar
unexport $(FOO)
unexport $(B)ar
+.RECIPEPREFIX := >
all:
- @echo foo=$(foo) bar=$(bar)
- @echo foo=$$foo bar=$$bar
+> @echo foo=$(foo) bar=$(bar)
+> @echo foo=$$foo bar=$$bar
',
'', "foo=f-ok bar=b-ok\nfoo= bar=\n");
@@ -140,7 +143,8 @@ all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J
# TEST 8: Test unexporting multiple variables on the same line
-@extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
+@args{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
+%ENV = (%ENV, %args);
&run_make_test('
A = a
@@ -174,7 +178,7 @@ a: ; @echo "\$$(export)=$(export) / \$$export=$$export"
',
'', "\$(export)=456 / \$export=456\n");
-# TEST 9: Check "export" as a target
+# TEST 10: Check "export" as a target
&run_make_test('
a: export
@@ -182,5 +186,25 @@ export: ; @echo "$@"
',
'', "export\n");
+# Check export and assignment of a variable on the same line
+
+$ENV{hello} = 'moon';
+
+run_make_test(q!
+all: ; @echo hello=$(hello) hello=$$hello
+export hello=sun
+!,
+ '', "hello=sun hello=sun\n");
+
+# Check unexport and assignment of a variable on the same line
+
+$ENV{hello} = 'moon';
+
+run_make_test(q!
+all: ; @echo hello=$(hello) hello=$$hello
+unexport hello=sun
+!,
+ '', "hello=sun hello=\n");
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/grouped_targets b/tests/scripts/features/grouped_targets
index 615e962..6b3c561 100644
--- a/tests/scripts/features/grouped_targets
+++ b/tests/scripts/features/grouped_targets
@@ -129,5 +129,79 @@ f g h&:: ; @echo Z
'',
"Z");
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate.
+
+touch('hello.z');
+touch('hello.q');
+
+# subtest 1
+# hello.x is not explicitly mentioned and thus is an intermediate file.
+run_make_test(q!
+all: hello.z
+%.z %.q: %.x ; touch $*.z $*.q
+%.x: ;
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 2
+# test.x is explicitly mentioned and thus is not an intermediate file.
+run_make_test(q!
+all: hello.z
+%.z %.q: %.x test.x ; @echo $*.z $*.q
+%.x: ;
+!, '', "hello.z hello.q\n");
+
+# subtest 3
+# hello.x is explicitly mentioned on an unrelated rule and thus is not an
+# intermediate file.
+run_make_test(q!
+all: hello.z
+%.z %.q: %.x; @echo $*.z $*.q
+%.x: ;
+unrelated: hello.x
+!, '', "hello.z hello.q\n");
+
+unlink('hello.z');
+unlink('hello.q');
+
+# SV 62809: Missing grouped target peer causes remake regardless of which
+# target caused the rule to run.
+touch(qw(gta)); # but not gtb
+run_make_test(q!
+gta gtb &: ; touch gta gtb
+!,
+ 'gta', "touch gta gtb\n");
+unlink(qw(gta gtb));
+
+# Ensure both goal targets are built if they depend on a grouped prereq
+touch(qw(gta)); # but not gtb
+run_make_test(q!
+x1 x2: ; touch $@
+
+x1: gta
+x2: gtb
+
+gta gtb &: ; touch gta gtb
+!,
+ 'x1 x2', "touch gta gtb\ntouch x1\ntouch x2\n");
+
+# Now everything should be up to date
+run_make_test(undef, 'x1 x2',
+ "#MAKE#: 'x1' is up to date.\n#MAKE#: 'x2' is up to date.");
+
+unlink(qw(x1 x2 gta gtb));
+
+# If an also-make file is older than a prerequisite build both
+
+utouch(-20, 'gtb');
+utouch(-10, 'pre');
+touch(qw(gta));
+run_make_test(q!
+gta gtb &: pre ; touch gta gtb
+!,
+ 'gta', "touch gta gtb\n");
+unlink(qw(pre gta gtb));
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/implicit_search b/tests/scripts/features/implicit_search
new file mode 100644
index 0000000..564dc5b
--- /dev/null
+++ b/tests/scripts/features/implicit_search
@@ -0,0 +1,483 @@
+# -*-perl-*-
+
+$description = "Test implicit rule search.";
+
+$details = "";
+
+# sv 48643
+# Each test has a %.c rule ahead of %.f rule.
+# hello.f exists and hello.c is missing.
+
+unlink('hello.c', 'hello.tsk', 'hello.o', 'hello.x');
+
+# Run every test with and without a suffix.
+my @suffixes = ('', '.o');
+# Run every test with single and double colon rules.
+my @rules = ('', ':');
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+touch('hello.f');
+
+# Test that make finds the intended implicit rule based on existence of a
+# prerequisite in the filesystem.
+#
+# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+# Test that make finds the intended implicit rule based on the explicit
+# prerequisite of the top goal and despite the existence of a
+# prerequisite in the filesystem.
+#
+# hello.c is an explicit prerequisite of the top target (hello.o or hello).
+# hello.c ought to exist.
+# hello.c prerequisite causes '%.o: %.c' rule to be chosen.
+run_make_test("
+hello$s: hello.c
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello$s'. Stop.\n",
+512);
+
+# Test that make finds the intended implicit rule when the implicit
+# prerequisite matches a target of an unrelated rule and despite the existence
+# of a prerequisite of the other rule candidate in the filesystem.
+#
+# hello.c matches 'hello.c:' rule. This makes hello.c a target and thus ought
+# to exist.
+# hello.c prerequisite causes '%.o: %.c' rule to be chosen.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+hello.c:; @#HELPER# fail 1
+", '-r', "fail 1\n#MAKE#: *** [#MAKEFILE#:5: hello.c] Error 1\n", 512);
+
+# Test that make finds the intended implicit rule based on existence of a
+# prerequisite in the filesystem, even when the prerequisite of another
+# candidate rule is mentioned explicitly on an unrelated rule.
+#
+# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen, even though hello.c
+# is mentioned explicitly on 'unrelated: hello.c'.
+# ought-to-exist does not apply to hello.c.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+unrelated: hello.c
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+# Test that make finds the intended implicit rule based on existence of a
+# prerequisite in the filesystem.
+#
+# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.
+# Despite '%.o: %.c hello.c' rule having explicit prerequisite hello.c.
+# ought-to-exist does not apply to hello.c.
+run_make_test("
+all: hello$s
+%$s:$r %.c hello.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.
+# '%.o: %.f hello.f' rule has explicit prerequisite hello.f.
+# ought-to-exist does not apply to hello.c.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f hello.f; \$(info hello.f)
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+# Rule '%: %.f' is chosen, because '%: %.f' requires no intermediates.
+# '%: %.c', on the other hand, requires intemediate hello.c to be built by the
+# default rule.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info \$<)
+%$s:$r %.f; \$(info \$<)
+.DEFAULT:; \$(info \$\@) true
+unrelated: hello.c
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+
+# hello.f is missing.
+# This time both hello.c and hello.f are missing and both '%: %.c' and '%: %.f'
+# require an intermediate.
+# The default rule builds intemerdiate hello.c.
+# '%: %.c' rule is chosen to build hello.
+unlink('hello.f');
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info \$<)
+%$s:$r %.f; \$(info \$<)
+.DEFAULT:; \@\$(info \$\@) #HELPER# fail 1
+unrelated: hello.c
+", '-r', "hello.c\nfail 1\n#MAKE#: *** [#MAKEFILE#:5: hello.c] Error 1\n", 512);
+
+# hello.f is missing.
+# No rule is found, because hello.c is not mentioned explicitly.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info \$<)
+%$s:$r %.f; \$(info \$<)
+.DEFAULT:; \@\$(info \$\@) #HELPER# fail 1
+", '-r', "hello$s\nfail 1\n#MAKE#: *** [#MAKEFILE#:5: hello$s] Error 1\n", 512);
+
+}
+}
+
+# Almost the same tests as above, but this time an intermediate is built.
+
+touch('hello.f');
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n";
+my $rcode = 512;
+if ($s or $r) {
+ $result = "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.";
+ $rcode = 0;
+}
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', "$result", $rcode);
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s hello$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', $result, $rcode);
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c hello$s; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', $result, $rcode);
+
+}
+}
+
+for my $r (@rules) {
+
+# Circular dependency hello.o <- hello.tsk is dropped.
+run_make_test("
+all: hello.tsk
+%.tsk: %.o; \$(info hello.tsk)
+%.o:$r %.c; \$(info hello.c)
+%.o:$r %.f %.tsk; \$(info hello.f)
+", '-r',
+"#MAKE#: Circular hello.o <- hello.tsk dependency dropped.\nhello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.");
+
+}
+
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+run_make_test("
+all: hello.tsk
+hello$s: hello.c
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello$s'. Stop.\n",
+512);
+}
+}
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n";
+if ($s or $r) {
+ $result = "fail 1\n#MAKE#: *** [#MAKEFILE#:6: hello.c] Error 1\n";
+}
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+hello.c:; @#HELPER# fail 1
+", '-r', $result, 512);
+}
+}
+
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+unrelated: hello$s
+", '-r', "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.");
+}
+}
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n";
+my $rcode = 512;
+if ($s or $r) {
+ $result = "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.";
+ $rcode = 0;
+}
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f hello.f; \$(info hello.f)
+", '-r', $result, $rcode);
+}
+}
+
+# One of the implicit rules has two prerequisites, hello.c and hello.x
+# hello.c does not qualify as ought to exit.
+# hello.x can be made from hello.z.
+# This test exersizes the break, which prevents making hello.x as an
+# intermediate from hello.z during compatibility search.
+unlink('hello.f');
+touch('hello.z');
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c %.x; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+unrelated: hello$s
+%.x:$r %.z; \$(info hello.z)
+", '-r',
+"#MAKE#: *** No rule to make target 'hello$s', needed by 'hello.tsk'. Stop.\n",
+512);
+}
+}
+
+# Test that prerequisite 'hello.x' mentioned explicitly on an unrelated rule is
+# not considered intermediate.
+touch('hello.tsk');
+unlink('hello.x');
+run_make_test("
+all: hello.tsk
+%.tsk: %.x; touch hello.tsk
+%.x: ;
+unrelated: hello.x
+", '-r', "touch hello.tsk\n");
+unlink('hello.tsk');
+
+touch ('hello.f');
+# Test implicit search of builtin rules.
+
+# %: %.c (and other builtin rules) are skipped.
+# %: %.f is chosen.
+run_make_test(q!
+all: hello
+!, 'FC="@echo f77" OUTPUT_OPTION=', "f77 hello.f -o hello\n");
+
+# %.o: %.c (and other builtin rules) are skipped.
+# %.o: %.f is chosen.
+run_make_test(q!
+all: hello.o
+!, 'FC="@echo f77" OUTPUT_OPTION=', "f77 -c hello.f\n");
+
+
+# %: %.c is chosen.
+# hello.c is an explicit prerequisite of the top target hello.
+# hello.c ought to exist.
+# hello.c prerequisite causes '%: %.c' rule to be chosen.
+run_make_test(q!
+hello: hello.c
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello'. Stop.\n",
+512);
+
+# %.o: %.c is chosen.
+# hello.c is an explicit prerequisite of the top target hello.o.
+# hello.c ought to exist.
+# hello.c prerequisite causes '%.o: %.c' rule to be chosen.
+run_make_test(q!
+hello.o: hello.c
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello.o'. Stop.\n",
+512);
+
+# %: %.c (and other builtin rules) are skipped.
+# %: %.f is chosen.
+# ought-to-exist does not apply to hello.c.
+run_make_test(q!
+all: hello
+unrelated: hello.c
+!, 'FC="@echo f77" OUTPUT_OPTION=', "f77 hello.f -o hello\n");
+
+# %.o: %.c (and other builtin rules) are skipped.
+# %.o: %.f is chosen.
+# ought-to-exist does not apply to hello.c.
+run_make_test(q!
+all: hello.o
+unrelated: hello.c
+!, 'FC="@echo f77" OUTPUT_OPTION=', "f77 -c hello.f\n");
+
+# builtin rule %.o: %.f is removed.
+# %.o: %.c (and other builtin rules) are skipped, because hello.c is missing.
+# ought-to-exist does not apply to hello.c.
+# %.o: %.c is chosen as a compatibility rule, because of hello.c.
+run_make_test(q!
+all: hello.o
+unrelated: hello.c
+%.o: %.f
+!, '',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello.o'. Stop.\n",
+512);
+
+
+# sv 17752.
+# In this test the builtin match-anything rule '%: %.f' is used to build
+# intermediate hello from hello.f, because hello is mentioned explicitly in
+# the makefile.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %; $(info $@ from $<)
+unrelated: hello
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"f77 hello.f -o hello\nhello.tsk from hello\n");
+
+# In this test the builtin match-anything rule %: %.f cannot be used to build
+# intermediate hello from hello.f, because hello is not mentioned explicitly in
+# the makefile.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %; $(info $@ from $<)
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n",
+512);
+
+# This is just like the one above, but compatibility rule '%.tsk: % %.x' has 2
+# prerequisites, '%' and '%.x'.
+# '%' expands to 'hello' and matches the explicit 'hello' on the unrelated rule.
+# '%.x' is an intermediate built from 'hello.xx' by rule '%.x: %.xx' during the
+# second pass (intermed_ok == 1) of compatibility search.
+# This test validates that compatibility search performs both intermed_ok == 0
+# and intermed_ok == 1 passes.
+unlink('hello.x');
+touch('hello.xx');
+run_make_test(q!
+all: hello.tsk
+%.tsk: % %.x; $(info $@ from $^)
+unrelated: hello
+%.x: %.xx; $(info $@ from $<)
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"f77 hello.f -o hello\nhello.x from hello.xx\nhello.tsk from hello hello.x\n");
+
+unlink('bye.o', 'bye.tsk', 'bye.x');
+# sv 21670.
+# Default recipe is used to build bye.o.
+run_make_test(q!
+all: bye.tsk
+%.tsk: %.o; $(info $@ from $<)
+.DEFAULT:; $(info bye.o)
+unrelated: bye.o
+!, '-r', "bye.o\nbye.tsk from bye.o\n#MAKE#: Nothing to be done for 'all'.");
+
+touch('bye.xx');
+# This is just like the one above, but compatibility rule '%.tsk: %.o %.x' has 2
+# prerequisites, '%.o' and '%.x'.
+# '%.o' expands to 'bye.o' and matches the explicit 'bye.o' on the unrelated rule.
+# '%.x' is an intermediate built from 'bye.xx' by rule '%.x: %.xx' during the
+# second pass (intermed_ok == 1) of compatibility search.
+# This test validates that compatibility search performs both intermed_ok == 0
+# and intermed_ok == 1 passes.
+run_make_test(q!
+all: bye.tsk
+%.tsk: %.o %.x; $(info $@ from $^)
+.DEFAULT:; $(info bye.o)
+unrelated: bye.o
+%.x: %.xx; $(info $@ from $<)
+!, '-r',
+"bye.o\nbye.x from bye.xx\nbye.tsk from bye.o bye.x\n#MAKE#: Nothing to be done for 'all'.");
+
+unlink('hello.f', 'hello.z', 'hello.xx', 'bye.xx');
+
+
+# A target specific variable causes the file to be entered to the database as a
+# prerequisite. Implicit search then treats this file as explicitly mentioned.
+# Test that implicit search keeps target specific variables of this file intact.
+# In this series of tests prerequisite 'hello.x' has a target specific variable
+# and is built as an intermediate. Implicit search treats 'hello.x' as
+# explicitly mentioned, but 'hello.x' does not qualify as ought-to-exist.
+unlink('hello.x', 'hello.tsk');
+
+# 'hello.x' is mentioned explicitly on the same implicit rule.
+run_make_test(q!
+all: hello.tsk
+%.tsk: hello.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags:=true
+!, '-r', "true\nhello.tsk\n");
+
+# Similar to the one above, but this time 'hello.x' is derived from the stem.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags:=true
+!, '-r', "true\nhello.tsk\n");
+
+# Similar to the one above, this time 'hello.x' is also mentioned explicitly on
+# an unrelated rule.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags:=true
+unrelated: hello.x
+!, '-r', "true\nhello.tsk\n");
+
+# 'hello.x' has a pattern specific variable.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+%.x: flags:=true
+!, '-r', "true\nhello.tsk\n");
+
+# 'hello.x' has a target specific variable and a pattern specific variable.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags+=good
+%.x: flags:=true
+!, '-r', "true good\nhello.tsk\n");
+
+# Intermediate prerequisite 'hello.x' has a target specific variable, a pattern
+# specfic variable, matches on both rules '%.tsk: %.x' and 'big_%.tsk: %.x'.
+run_make_test(q!
+all: hello.tsk big_hello.tsk
+%.tsk: %.x; $(info $@)
+big_%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags+=good
+%.x: flags:=true
+!, '-r', "true good\nhello.tsk\nbig_hello.tsk\n");
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/include b/tests/scripts/features/include
index 0c63c06..69d6718 100644
--- a/tests/scripts/features/include
+++ b/tests/scripts/features/include
@@ -8,16 +8,11 @@ Test extra whitespace at the end of the include, multiple -includes and
sincludes (should not give an error) and make sure that errors are reported
for targets that were also -included.";
-$makefile2 = &get_tmpfile;
+create_file('incl.mk', "ANOTHER: ; \@echo This is another included makefile\n");
-open(MAKEFILE,"> $makefile");
-
-# The contents of the Makefile ...
-
-print MAKEFILE <<EOF;
-\#Extra space at the end of the following file name
-include $makefile2
-all: ; \@echo There should be no errors for this makefile.
+run_make_test(qq!#Extra space at the end of the following file name
+include incl.mk ! . q!
+all: ; @echo There should be no errors for this makefile.
-include nonexistent.mk
-include nonexistent.mk
@@ -27,27 +22,12 @@ sinclude nonexistent-2.mk
sinclude makeit.mk
error: makeit.mk
-EOF
-
-close(MAKEFILE);
-
-
-open(MAKEFILE,"> $makefile2");
-
-print MAKEFILE "ANOTHER: ; \@echo This is another included makefile\n";
-
-close(MAKEFILE);
-
-# Create the answer to what should be produced by this Makefile
-&run_make_with_options($makefile, "all", &get_logfile);
-$answer = "There should be no errors for this makefile.\n";
-&compare_output($answer, &get_logfile(1));
+!,
+ "all", "There should be no errors for this makefile.\n");
-&run_make_with_options($makefile, "ANOTHER", &get_logfile);
-$answer = "This is another included makefile\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "ANOTHER", "This is another included makefile\n");
-$makefile = undef;
+unlink('incl.mk');
# Try to build the "error" target; this will fail since we don't know
# how to create makeit.mk, but we should also get a message (even though
@@ -64,6 +44,22 @@ error: foo.mk ; @echo $@
512
);
+# The same as above with an additional include directory.
+
+mkdir('hellod', 0777);
+
+run_make_test
+ ('
+-include foo.mk
+error: foo.mk ; @echo $@
+',
+ '-Ihellod',
+ "#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'. Stop.\n",
+ 512
+ );
+
+rmdir('hellod');
+
# Make sure that target-specific variables don't impact things. This could
# happen because a file record is created when a target-specific variable is
# set.
@@ -157,12 +153,50 @@ include inc1
include inc2
inc2:; echo > $@
!,
- '', "echo > inc2\necho > inc1\nDONE\n");
+ '', "echo > inc1\necho > inc2\nDONE\n");
rmfiles('inc1', 'inc2');
+# Test include of make-able file doesn't show an error.
+# Specify an additional include directory.
+
+mkdir('hellod', 0777);
+
+run_make_test(q!
+.PHONY: default
+default:; @echo DONE
+
+inc1:; echo > $@
+include inc1
+include inc2
+inc2:; echo > $@
+!,
+ '-Ihellod', "echo > inc1\necho > inc2\nDONE\n");
+
+rmfiles('inc1', 'inc2');
+
+# Test include of make-able file doesn't show an error.
+# inc1 and inc2 are present in the specified include directory.
+touch('hellod/inc1');
+touch('hellod/inc2');
+
+run_make_test(q!
+.PHONY: default
+default:; @echo DONE
+
+inc1:; echo > $@
+include inc1
+include inc2
+inc2:; echo > $@
+!,
+ '-Ihellod', "DONE\n");
+
+rmfiles('inc1', 'inc2', 'hellod/inc1', 'hellod/inc2');
+
+rmdir('hellod');
+
# No target gets correct error
-run_make_test('', '', '#MAKE#: *** No targets. Stop.', 512);
+run_make_test("\n", '', '#MAKE#: *** No targets. Stop.', 512);
# No target in included file either, still gets correct error.
touch('inc1.mk');
@@ -209,7 +243,7 @@ inc1:; echo > $@
include inc1
include inc2
!,
- '', "#MAKEFILE#:7: inc2: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'inc2'. Stop.\n", 512);
+ '', "echo > inc1\n#MAKEFILE#:7: inc2: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'inc2'. Stop.\n", 512);
rmfiles('inc1');
@@ -235,10 +269,34 @@ inc1: foo; echo > $@
'', "#MAKEFILE#:3: inc1: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'foo', needed by 'inc1'. Stop.\n", 512);
rmfiles('inc1');
+
+ # Check that included double-colon targets with no prerequisites aren't
+ # built. This should fail as hello.mk doesn't exist
+
+ run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+include hello.mk
+hello.mk:: ; echo 'FOO=bar' > $@
+!,
+ '', "#MAKEFILE#:4: hello.mk: $ERR_no_such_file", 512);
+
+ # Check that included phony targets aren't built.
+ # This should fail as hello.mk doesn't exist
+
+ run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+include hello.mk
+hello.mk: ; echo 'FOO=bar' > $@
+.PHONY: hello.mk
+!,
+ '', "#MAKEFILE#:4: hello.mk: $ERR_no_such_file", 512);
}
-# Including files that can't be read should show an error
if (defined $ERR_unreadable_file) {
+ # Including files that can't be read should show an error
+ unlink('inc1');
create_file('inc1', 'FOO := foo');
chmod 0000, 'inc1';
@@ -248,7 +306,18 @@ all:;@echo $(FOO)
!,
'', "#MAKEFILE#:2: inc1: $ERR_unreadable_file\n#MAKE#: *** No rule to make target 'inc1'. Stop.", 512);
-# Unreadable files that we know how to successfully recreate should work
+ # Including files that can't be read should show an error, even when there
+ # is a readable file in a subsequent include directory.
+ mkdir('hellod', 0777);
+ touch("hellod/inc1");
+
+ run_make_test(q!
+include inc1
+all:;@echo $(FOO)
+!,
+ '-Ihellod', "#MAKEFILE#:2: inc1: $ERR_unreadable_file\n#MAKE#: *** No rule to make target 'inc1'. Stop.", 512);
+
+ # Unreadable files that we know how to successfully recreate should work
run_make_test(sprintf(q!
all:;@echo $(FOO)
@@ -257,7 +326,140 @@ inc1:; @%s $@ && echo FOO := bar > $@
!, $CMD_rmfile),
'', "bar");
- rmfiles('inc1');
+ # Unreadable files that we know how to successfully recreate should work.
+ # Even when there is a readable file in an additional include directory.
+
+ unlink('inc1');
+ create_file('inc1', 'FOO := foo');
+ chmod 0000, 'inc1';
+
+ run_make_test(sprintf(q!
+all:;@echo $(FOO)
+include inc1
+inc1:; @%s $@ && echo FOO := bar > $@
+!, $CMD_rmfile),
+ '-Ihellod', "bar");
+
+ rmfiles('inc1', 'hellod/inc1');
+ rmdir('hellod');
+}
+
+# Check that the order of remaking include files is correct: should remake
+# them in the same order they were encountered in the makefile. SV 58735
+
+run_make_test(q!
+-include i1 i2
+-include i3
+-include i4
+%:;@echo $@
+all:;
+!,
+ '', "i1\ni2\ni3\ni4\n#MAKE#: 'all' is up to date.\n");
+
+# Check that included files work if created after the first include failed
+# https://savannah.gnu.org/bugs/?57676
+
+run_make_test(q!
+default:; @echo $(hello)
+-include hello.mk
+$(shell echo hello=world >hello.mk)
+include hello.mk
+!,
+ '', "world\n");
+
+unlink('hello.mk');
+
+# Check that included double-colon targets with no prerequisites aren't built.
+# This should succeed since hello.mk already exists
+
+touch('hello.mk');
+
+run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+include hello.mk
+hello.mk:: ; echo 'FOO=bar' > $@
+!,
+ '', 'FOO=');
+
+unlink('hello.mk');
+
+# Check that included double-colon targets with no prerequisites aren't built.
+# This should succeed due to -include
+
+run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+-include hello.mk
+hello.mk:: ; echo 'FOO=bar' > $@
+!,
+ '', 'FOO=');
+
+# Check that phony targets aren't built.
+# This should succeed since hello.mk already exists
+
+touch('hello.mk');
+
+run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+include hello.mk
+hello.mk: ; echo 'FOO=bar' > $@
+.PHONY: hello.mk
+!,
+ '', 'FOO=');
+
+unlink('hello.mk');
+
+# Check that included double-colon targets with no prerequisites aren't built.
+# This should succeed due to -include
+
+run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+-include hello.mk
+hello.mk: ; echo 'FOO=bar' > $@
+.PHONY: hello.mk
+!,
+ '', 'FOO=');
+
+# SV 56301 Verify pattern rules creating optional includes.
+# -k shouldn't matter when creating include files.
+
+run_make_test(q!
+all:; @echo hello
+-include inc_a.mk
+include inc_b.mk
+%_a.mk %_b.mk:; exit 1
+!,
+ '', "exit 1\n#MAKEFILE#:4: Failed to remake makefile 'inc_b.mk'.\n", 512);
+
+run_make_test(undef, '-k', "exit 1\n#MAKEFILE#:4: Failed to remake makefile 'inc_b.mk'.\n", 512);
+
+# It seems wrong to me that this gives a different error message, but at
+# least it doesn't keep going.
+run_make_test(q!
+all:; @echo hello
+include inc_a.mk
+-include inc_b.mk
+%_a.mk %_b.mk:; exit 1
+!,
+ '', "exit 1\n#MAKEFILE#:3: inc_a.mk: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:5: inc_a.mk] Error 1\n", 512);
+
+run_make_test(undef, '-k', "exit 1\n#MAKEFILE#:3: inc_a.mk: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:5: inc_a.mk] Error 1\n#MAKEFILE#:3: Failed to remake makefile 'inc_a.mk'.\n", 512);
+
+# Check the default makefiles... this requires us to invoke make with no
+# arguments. Also check MAKEFILES
+
+if ($port_type eq 'W32') {
+ $defaults = "GNUmakefile\nmakefile\nMakefile\nmakefile.mak";
+} else {
+ $defaults = "GNUmakefile\nmakefile\nMakefile";
}
+$ENV{MAKEFILES} = 'foobar barfoo';
+run_make_with_options(undef, ['-E', '%:;@echo $@', '-E', 'all:;', '-E', '-include bizbaz', '-E', '-include bazbiz'], get_logfile(0));
+$answer = "bizbaz\nbazbiz\nfoobar\nbarfoo\n$defaults\n#MAKE#: 'all' is up to date.\n";
+&compare_output(subst_make_string($answer), &get_logfile(1));
+
1;
diff --git a/tests/scripts/features/jobserver b/tests/scripts/features/jobserver
index 73d10d9..8ecbe34 100644
--- a/tests/scripts/features/jobserver
+++ b/tests/scripts/features/jobserver
@@ -25,17 +25,16 @@ all:;@echo $@: "/$(SHOW)/"
# Setting parallelism with the environment
# Command line should take precedence over the environment
-$extraENV{MAKEFLAGS} = "-j2 $np";
+$ENV{MAKEFLAGS} = "-j2 $np";
run_make_test(q!
SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))
recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all
all:;@echo $@: "/$(SHOW)/"
!,
'', "recurse: /-j2 --jobserver-auth=<auth> $np/\nall: /-j2 --jobserver-auth=<auth> $np/\n");
-delete $extraENV{MAKEFLAGS};
# Test override of -jN
-$extraENV{MAKEFLAGS} = "-j9 $np";
+$ENV{MAKEFLAGS} = "-j9 $np";
run_make_test(q!
SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))
recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -j3 -f #MAKEFILE# recurse2
@@ -43,7 +42,6 @@ recurse2: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all
all:;@echo $@: "/$(SHOW)/"
!,
"-j2 $np", "recurse: /-j2 --jobserver-auth=<auth> $np/\n#MAKE#[1]: warning: -j3 forced in submake: resetting jobserver mode.\nrecurse2: /-j3 --jobserver-auth=<auth> $np/\nall: /-j3 --jobserver-auth=<auth> $np/\n");
-delete $extraENV{MAKEFLAGS};
# Test override of -jN with -j
run_make_test(q!
@@ -64,17 +62,18 @@ all:;@echo $@: "/$(SHOW)/"
unlink('inc.mk');
run_make_test(q!
+.RECIPEPREFIX = >
-include inc.mk
recur:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @rm -f inc.mk
- @$(MAKE) -j2 -f #MAKEFILE# all
+#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+> @rm -f inc.mk
+> @$(MAKE) -j2 -f #MAKEFILE# all
all:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @echo $@
+#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+> @echo $@
inc.mk:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @echo 'FOO = bar' > $@
+#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+> @echo 'FOO = bar' > $@
!,
"$np -j2", "#MAKE#[1]: warning: -j2 forced in submake: resetting jobserver mode.\nall\n");
@@ -83,27 +82,79 @@ unlink('inc.mk');
# Test recursion which is hidden from make.
# See Savannah bug #39934
# Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474
-# Windows doesn't use a pipe, and doesn't close access, so this won't happen.
+# Environments that don't use a pipe won't close access, so this won't happen.
if ($port_type ne 'W32') {
- open(MAKEFILE,"> Makefile2");
- print MAKEFILE '
- vpath %.c ../
- foo:
- ';
- close(MAKEFILE);
+ create_file('Makefile2', "vpath %.c ../\n", "foo:\n");
run_make_test(q!
default: ; @ #MAKEPATH# -f Makefile2
!,
- "-j2 $np",
+ "--jobserver-style=pipe -j2 $np",
"#MAKE#[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.
#MAKE#[1]: Nothing to be done for 'foo'.");
rmfiles('Makefile2');
}
-1;
+# For Windows and named pipes, we don't need to worry about recursion
+if ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) {
+ create_file('Makefile2', "vpath %.c ../\n", "foo:\n");
+
+ run_make_test(q!
+default: ; @ #MAKEPATH# -f Makefile2
+!,
+ "-j2 $np",
+"#MAKE#[1]: Nothing to be done for 'foo'.");
+
+ rmfiles('Makefile2');
+}
+
+# Ensure enter/leave directory messages appear before jobserver warnings
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
+run_make_test(q!
+all: ; @$(MAKE) -C . -f #MAKEFILE# recurse -j1
+recurse: ; @echo hi
+!,
+ '-w -j2', "#MAKE#: Entering directory '#PWD#'
+#MAKE#[1]: Entering directory '#PWD#'
+#MAKE#[1]: warning: -j1 forced in submake: resetting jobserver mode.
+hi
+#MAKE#[1]: Leaving directory '#PWD#'
+#MAKE#: Leaving directory '#PWD#'\n");
+
+# Check for invalid jobserver-style options
+
+run_make_test(q!
+all: a
+all a: ; @echo $@
+!,
+ '--jobserver-style=foo -j8',
+ "#MAKE#: *** Unknown jobserver auth style 'foo'. Stop.", 512);
+
+# sv 62908.
+# Test that when mkfifo fails, make switches to pipe and succeeds.
+# Force mkfifo to fail by attempting to create a fifo in a non existent
+# directory.
+# run_make_test does not allow matching a multiline pattern, therefore run the
+# test twice.
+# First time look for /$ERR_no_such_file/ to ensure mkfifo failed.
+# Second time look for /Nothing to be done/ to ensure make succeeded.
+if (exists $FEATURES{'jobserver-fifo'}) {
+ $ENV{TMPDIR} = "nosuchdir";
+ run_make_test("all:\n", '-j2', "/$ERR_no_such_file/");
+
+ $ENV{TMPDIR} = "nosuchdir";
+ run_make_test(undef, '-j2', "/Nothing to be done/");
+
+ # Verify that MAKE_TMPDIR is preferred if provided
+ $ENV{MAKE_TMPDIR} = '.';
+ $ENV{TMPDIR} = 'nosuchdir';
+
+ run_make_test(q!
+recurse: ; @$(MAKE) -f #MAKEFILE# all
+all:;@echo "$$MAKEFLAGS"
+!,
+ "-j2 --no-print-directory", "/--jobserver-auth=fifo:\\./");
+}
+
+1;
diff --git a/tests/scripts/features/load b/tests/scripts/features/load
index fa4b86f..b462ed9 100644
--- a/tests/scripts/features/load
+++ b/tests/scripts/features/load
@@ -4,7 +4,7 @@ $description = "Test the load operator.";
$details = "Test dynamic loading of modules.";
# Don't do anything if this system doesn't support "load"
-exists $FEATURES{load} or return -1;
+exists $FEATURES{'load'} or return -1;
my $cc = get_config('CC');
if (! $cc) {
@@ -19,18 +19,22 @@ unlink(qw(testload.c testload.so));
open(my $F, '> testload.c') or die "open: testload.c: $!\n";
print $F <<'EOF' ;
-#include <string.h>
-#include <stdio.h>
-
#include "gnumake.h"
+char* getenv (const char*);
+
int plugin_is_GPL_compatible;
+int testload_gmk_setup (gmk_floc *);
+int explicit_setup (gmk_floc *);
+
int
testload_gmk_setup (gmk_floc *pos)
{
(void)pos;
gmk_eval ("TESTLOAD = implicit", 0);
+ if (getenv("TESTAPI_KEEP"))
+ return -1;
return 1;
}
@@ -39,6 +43,8 @@ explicit_setup (gmk_floc *pos)
{
(void)pos;
gmk_eval ("TESTLOAD = explicit", 0);
+ if (getenv("TESTAPI_KEEP"))
+ return -1;
return 1;
}
EOF
@@ -46,14 +52,14 @@ close($F) or die "close: testload.c: $!\n";
# Make sure we can compile
-my $cflags = get_config('CFLAGS');
-my $cppflags = get_config('CPPFLAGS');
-my $ldflags = get_config('LDFLAGS');
-my $sobuild = "$cc ".($srcdir? "-I$srcdir/src":'')." $cppflags $cflags -shared -fPIC $ldflags -o testload.so testload.c";
+my $cppflags = get_config('CPPFLAGS') . ($srcdir ? " -I$srcdir/src" : '');
+my $cflags = get_config('CFLAGS') . ' -fPIC';
+my $ldflags = get_config('LDFLAGS') . ' -shared';
+my $sobuild = "$cc $cppflags $cflags $ldflags -o testload.so testload.c";
my $clog = `$sobuild 2>&1`;
if ($? != 0) {
- $verbose and print "Failed to build testload.so:\n$sobuild\n$_";
+ $verbose and print "Failed to build testload.so:\n$sobuild\n$clog";
return -1;
}
@@ -76,7 +82,7 @@ all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
!,
'', "pre= post=testload.so explicit\n");
-# TEST 4
+# TEST 3
# Check multiple loads
run_make_test(q!
PRE := $(.LOADED)
@@ -87,7 +93,7 @@ all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
!,
'', "pre= post=testload.so implicit\n");
-# TEST 5
+# TEST 4
# Check auto-rebuild of loaded file that's out of date
utouch(-10, 'testload.so');
touch('testload.c');
@@ -112,6 +118,32 @@ all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
%.so: %.c ; @echo "rebuilding $@"; !.$sobuild,
'', "rebuilding testload.so\npre= post=testload.so explicit\n");
+# sv 63044.
+# Test that the loaded shared object is present in .LOADED when the setup
+# routine returns -1.
+$ENV{TESTAPI_KEEP} = 1;
+run_make_test(q!
+PRE := $(.LOADED)
+load testload.so
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+!,
+ '--warn-undefined-variables', "pre= post=testload.so implicit\n");
+
+# Check that we don't auto-rebuild of loaded file that's out of date
+# if we return -1 from the setup
+utouch(-10, 'testload.so');
+touch('testload.c');
+
+$ENV{TESTAPI_KEEP} = 1;
+run_make_test(q!
+PRE := $(.LOADED)
+load ./testload.so
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+testload.so: testload.c ; @echo "rebuilding $@"; !.$sobuild,
+ '', "pre= post=testload.so implicit\n");
+
unlink(qw(testload.c testload.so)) unless $keep;
# This tells the test driver that the perl test script executed properly.
diff --git a/tests/scripts/features/loadapi b/tests/scripts/features/loadapi
index ba14928..a72f1f1 100644
--- a/tests/scripts/features/loadapi
+++ b/tests/scripts/features/loadapi
@@ -24,8 +24,12 @@ print $F <<'EOF' ;
#include "gnumake.h"
+char *getenv (const char*);
+
int plugin_is_GPL_compatible;
+int testapi_gmk_setup ();
+
static char *
test_eval (const char *buf)
{
@@ -67,12 +71,26 @@ func_test (const char *funcname, unsigned int argc, char **argv)
}
int
-testapi_gmk_setup ()
+testapi_gmk_setup (const gmk_floc *floc)
{
+ const char *verbose = getenv ("TESTAPI_VERBOSE");
+
gmk_add_function ("test-expand", func_test, 1, 1, GMK_FUNC_DEFAULT);
gmk_add_function ("test-noexpand", func_test, 1, 1, GMK_FUNC_NOEXPAND);
gmk_add_function ("test-eval", func_test, 1, 1, GMK_FUNC_DEFAULT);
gmk_add_function ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.", func_test, 0, 0, 0);
+
+ if (verbose)
+ {
+ printf ("testapi_gmk_setup\n");
+
+ if (verbose[0] == '2')
+ printf ("%s:%lu\n", floc->filenm, floc->lineno);
+ }
+
+ if (getenv ("TESTAPI_KEEP"))
+ return -1;
+
return 1;
}
EOF
@@ -121,6 +139,89 @@ all:;@echo '$(test-noexpand $(TEST))'
!,
'', "\$(TEST)\n");
+
+# During all subsequent tests testapi.so exists.
+#
+my @loads = ('', q!
+load testapi.so
+load testapi.so
+-load testapi.so
+-load testapi.so
+$(eval load testapi.so)
+$(eval -load testapi.so)
+!);
+
+for my $extra_loads (@loads) {
+my $n = 5;
+if ($extra_loads) {
+ $n = 12;
+}
+# sv 63045.
+# Test that having unloaded a shared object make loads it again, even if the
+# shared object is not updated.
+$ENV{TESTAPI_VERBOSE} = 1;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; \$(info \$@)
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\ntestapi.so\ntestapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n");
+
+# sv 63045.
+# Same as above, but testapi_gmk_setup returned -1.
+$ENV{TESTAPI_KEEP} = 1;
+$ENV{TESTAPI_VERBOSE} = 1;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; \$(info \$@)
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n");
+
+# sv 63045.
+# Test that make exits, unless make can successfully update an unloaded shared
+# object.
+$ENV{TESTAPI_VERBOSE} = 1;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; @#HELPER# fail 1
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\nfail 1\n#MAKE#: *** [#MAKEFILE#:$n: testapi.so] Error 1\n", 512);
+
+# sv 63045.
+# Same as above, but testapi_gmk_setup returned -1.
+$ENV{TESTAPI_KEEP} = 1;
+$ENV{TESTAPI_VERBOSE} = 1;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; @#HELPER# fail 1
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n");
+
+# sv 63100.
+# Test that make supplies the correct floc when the shared object is loaded
+# again.
+$ENV{TESTAPI_VERBOSE} = 2;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; \$(info \$@)
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\n#MAKEFILE#:2\ntestapi.so\ntestapi_gmk_setup\n#MAKEFILE#:2\nhello\n#MAKE#: 'all' is up to date.\n");
+}
+
unlink(qw(testapi.c testapi.so)) unless $keep;
# This tells the test driver that the perl test script executed properly.
diff --git a/tests/scripts/features/mult_rules b/tests/scripts/features/mult_rules
index e706e17..bddd501 100644
--- a/tests/scripts/features/mult_rules
+++ b/tests/scripts/features/mult_rules
@@ -69,10 +69,20 @@ $answer = "EXTRA EXTRA\n";
unlink("defs.h","test.h","config.h","extra.h");
-1;
-
-
-
-
-
+# sv 62650.
+# Test the message that make prints when a file found by directory search
+# is preferred over the local one.
+run_make_test(q!
+vpath hello.c src
+all: hello.c; $(info $@ from $^)
+hello.c: ; $(info 1 $@)
+src/hello.c: ; $(info 2 $@)
+!, '',
+ "#MAKEFILE#:4: Recipe was specified for file 'hello.c' at #MAKEFILE#:4,
+#MAKEFILE#:4: but 'hello.c' is now considered the same file as 'src/hello.c'.
+#MAKEFILE#:4: Recipe for 'hello.c' will be ignored in favor of the one for 'src/hello.c'.
+2 src/hello.c
+all from src/hello.c
+#MAKE#: 'all' is up to date.\n");
+1;
diff --git a/tests/scripts/features/output-sync b/tests/scripts/features/output-sync
index 1d09174..13a54ca 100644
--- a/tests/scripts/features/output-sync
+++ b/tests/scripts/features/output-sync
@@ -116,20 +116,24 @@ EOF
close(MAKEFILE);
# Test per-make synchronization.
+# Note we have to sleep again here after starting the foo makefile before
+# starting the bar makefile, otherwise the "entering/leaving" messages for the
+# submakes might be ordered differently than we expect.
+
unlink(@syncfiles);
run_make_test(qq!
all: make-foo make-bar
make-foo: ; \$(MAKE) -C foo
-make-bar: ; \$(MAKE) -C bar!,
+make-bar: ; #HELPER# -q sleep 1 ; \$(MAKE) -C bar!,
'-j -Orecurse',
"#MAKEPATH# -C foo
#MAKE#[1]: Entering directory '#PWD#/foo'
foo: start
foo: end
#MAKE#[1]: Leaving directory '#PWD#/foo'
-#MAKEPATH# -C bar
+#HELPER# -q sleep 1 ; #MAKEPATH# -C bar
#MAKE#[1]: Entering directory '#PWD#/bar'
bar: start
bar: end
@@ -338,5 +342,30 @@ all:: ; @./foo bar baz
'-O', "#MAKE#: ./foo: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:2: all] Error 127\n", 512);
}
+if ($port_type eq 'UNIX') {
+# POSIX doesn't require sh to set PPID so test this
+my $cmd = create_command();
+add_options($cmd, '-f', '/dev/null', '-E', q!all:;@echo $$PPID!);
+my $fout = 'ppidtest.out';
+run_command_with_output($fout, @$cmd);
+$_ = read_file_into_string($fout);
+chomp($_);
+if (/^[0-9]+$/) {
+use POSIX ();
+# SV 63157.
+# Test that make removes temporary files, even when a signal is received.
+# The general test_driver postprocessing will ensure the temporary file used
+# to synchronize output and the jobserver fifo are both removed.
+# sleep is needed to let make write its "... Terminated" message to the log
+# file.
+run_make_test(q!
+pid:=$(shell echo $$PPID)
+all:; @kill -TERM $(pid) && sleep 16
+!, '-O -j2', '/#MAKE#: \*\*\* \[#MAKEFILE#:3: all] Terminated/', POSIX::SIGTERM);
+}
+
+unlink($fout);
+}
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/parallelism b/tests/scripts/features/parallelism
index 08f94a6..98ee8a3 100644
--- a/tests/scripts/features/parallelism
+++ b/tests/scripts/features/parallelism
@@ -7,46 +7,47 @@ if (!$parallel_jobs) {
return -1;
}
-run_make_test("
+run_make_test(q!
all : def_1 def_2 def_3
-def_1 : ; \@#HELPER# file ONE wait THREE out TWO
-def_2 : ; \@#HELPER# wait FOUR file THREE
-def_3 : ; \@#HELPER# wait ONE file FOUR",
+def_1 : ; @#HELPER# file ONE wait THREE out TWO
+def_2 : ; @#HELPER# wait FOUR file THREE
+def_3 : ; @#HELPER# wait ONE file FOUR!,
'-j4', "file ONE\nwait ONE\nfile FOUR\nwait FOUR\nfile THREE\nwait THREE\nTWO");
rmfiles(qw(ONE TWO THREE FOUR));
# Verify -j added to MAKEFLAGS in the makefile
-run_make_test("
+run_make_test(q!
MAKEFLAGS += -j4
all : def_1 def_2 def_3
-def_1 : ; \@#HELPER# file ONE wait THREE out TWO
-def_2 : ; \@#HELPER# wait FOUR file THREE
-def_3 : ; \@#HELPER# wait ONE file FOUR",
+def_1 : ; @#HELPER# file ONE wait THREE out TWO
+def_2 : ; @#HELPER# wait FOUR file THREE
+def_3 : ; @#HELPER# wait ONE file FOUR!,
'', "file ONE\nwait ONE\nfile FOUR\nwait FOUR\nfile THREE\nwait THREE\nTWO");
rmfiles(qw(ONE TWO THREE FOUR));
# Command line should take precedence
-run_make_test("
+run_make_test(q!
MAKEFLAGS += -j2
all : def_1 def_2 def_3
-def_1 : ; \@#HELPER# file ONE wait THREE out TWO
-def_2 : ; \@#HELPER# wait FOUR file THREE
-def_3 : ; \@#HELPER# wait ONE file FOUR",
+def_1 : ; @#HELPER# file ONE wait THREE out TWO
+def_2 : ; @#HELPER# wait FOUR file THREE
+def_3 : ; @#HELPER# wait ONE file FOUR!,
'-j4', "file ONE\nwait ONE\nfile FOUR\nwait FOUR\nfile THREE\nwait THREE\nTWO");
rmfiles(qw(ONE TWO THREE FOUR));
# Test parallelism with included files. Here we sleep/echo while
# building the included files, to test that they are being built in
# parallel.
-run_make_test("
-all: 1 2; \@#HELPER# out success
+run_make_test(q!
+all: 1 2; @#HELPER# out success
-include 1.inc 2.inc
+.RECIPEPREFIX := >
1.inc:
-\t\@#HELPER# file ONE.inc wait THREE.inc file TWO.inc
-\t\@echo '1: ; \@#HELPER# file ONE wait THREE file TWO' > \$\@
+> @#HELPER# file ONE.inc wait THREE.inc file TWO.inc
+> @echo '1: ; @#HELPER# file ONE wait THREE file TWO' > $@
2.inc:
-\t\@#HELPER# wait ONE.inc file THREE.inc
-\t\@echo '2: ; \@#HELPER# wait ONE file THREE' > \$\@",
+> @#HELPER# wait ONE.inc file THREE.inc
+> @echo '2: ; @#HELPER# wait ONE file THREE' > $@!,
"-j4",
"file ONE.inc\nwait ONE.inc\nfile THREE.inc\nwait THREE.inc\nfile TWO.inc\nfile ONE\nwait ONE\nfile THREE\nwait THREE\nfile TWO\nsuccess\n", 0, 7);
rmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));
@@ -54,17 +55,17 @@ rmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));
# Test parallelism with included files--this time recurse first and make
# sure the jobserver works.
-run_make_test("
-recurse: ; \@\$(MAKE) --no-print-directory -f #MAKEFILE# INC=yes all
-all: 1 2; \@#HELPER# out success
+run_make_test(q!
+recurse: ; @$(MAKE) --no-print-directory -f #MAKEFILE# INC=yes all
+all: 1 2; @#HELPER# out success
INC = no
-ifeq (\$(INC),yes)
+ifeq ($(INC),yes)
-include 1.inc 2.inc
endif
-1.inc: ; \@#HELPER# file ONE.inc wait THREE.inc file TWO.inc; echo '1: ; \@#HELPER# file ONE wait THREE file TWO' > \$\@
-2.inc: ; \@#HELPER# wait ONE.inc file THREE.inc; echo '2: ; \@#HELPER# wait ONE file THREE' > \$\@",
+1.inc: ; @#HELPER# file ONE.inc wait THREE.inc file TWO.inc; echo '1: ; @#HELPER# file ONE wait THREE file TWO' > $@
+2.inc: ; @#HELPER# wait ONE.inc file THREE.inc; echo '2: ; @#HELPER# wait ONE file THREE' > $@!,
"-j4",
"file ONE.inc\nwait ONE.inc\nfile THREE.inc\nwait THREE.inc\nfile TWO.inc\nfile ONE\nwait ONE\nfile THREE\nwait THREE\nfile TWO\nsuccess\n", 0, 7);
rmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));
@@ -74,47 +75,42 @@ rmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));
# function in an exported recursive variable. I added some code to check
# for this situation and print a message if it occurred. This test used
# to trigger this code when I added it but no longer does after the fix.
-# We have to increase the timeout from the default (5s) on this test.
-run_make_test("
-export HI = \$(shell \$(\$\@.CMD))
+run_make_test(q!
+export HI = $(shell $($@.CMD))
first.CMD = #HELPER# out hi
second.CMD = #HELPER# sleep 4
.PHONY: all first second
all: first second
-first second: ; \@#HELPER# out \$\@ sleep 1 out \$\@",
- '-j2', "first\nsleep 1\nfirst\nsecond\nsleep 1\nsecond", 0, 7);
+first second: ; @#HELPER# out $@ sleep 1 out $@!,
+ '-j2', "first\nsleep 1\nfirst\nsecond\nsleep 1\nsecond", 0);
# Michael Matz <matz@suse.de> reported a bug where if make is running in
# parallel without -k and two jobs die in a row, but not too close to each
# other, then make will quit without waiting for the rest of the jobs to die.
-run_make_test("
+run_make_test(q!
.PHONY: all fail.1 fail.2 fail.3 ok
all: fail.1 ok fail.2 fail.3
-.RECIPEPREFIX := >
-
-fail.1 fail.2 fail.3:
-> \@#HELPER# sleep \$(patsubst fail.%,%,\$\@)
-> \@#HELPER# out Fail
-> \@#HELPER# fail 1
+fail.1: ; @#HELPER# -q sleep 1 out $@ file fail.1 fail 1
+fail.2: ; @#HELPER# -q sleep 2 out $@ wait fail.1 file fail.2 fail 1
+fail.3: ; @#HELPER# -q sleep 3 out $@ wait fail.2 file fail.3 fail 1
-ok:
-> \@#HELPER# sleep 4
-> \@#HELPER# out OK",
- '-rR -j5', "sleep 1\nFail\nfail 1
-#MAKE#: *** [#MAKEFILE#:10: fail.1] Error 1
+ok: ; @#HELPER# -q sleep 4 wait fail.3 out OK!,
+ '-rR -j5', "fail.1\nfail 1
+#MAKE#: *** [#MAKEFILE#:5: fail.1] Error 1
#MAKE#: *** Waiting for unfinished jobs....
-sleep 2\nFail\nfail 1
-#MAKE#: *** [#MAKEFILE#:10: fail.2] Error 1
-sleep 3\nFail\nfail 1
-#MAKE#: *** [#MAKEFILE#:10: fail.3] Error 1
-sleep 4\nOK",
+fail.2\nfail 1
+#MAKE#: *** [#MAKEFILE#:6: fail.2] Error 1
+fail.3\nfail 1
+#MAKE#: *** [#MAKEFILE#:7: fail.3] Error 1
+OK",
512);
+rmfiles(qw(fail.1 fail.2 fail.3));
# Test for Savannah bug #15641.
#
@@ -148,7 +144,7 @@ rmfiles('target');
# TEST #11: Make sure -jN from MAKEFLAGS is processed even when we re-exec
# See Savannah bug #33873
-$extraENV{MAKEFLAGS} = '-j4';
+$ENV{MAKEFLAGS} = '-j4';
run_make_test(q!
things = thing1 thing2
@@ -160,7 +156,6 @@ inc.mk: ; @touch $@
!,
'', "file thing2start\nwait thing2start\nfile thing1start\nwait thing1start\nfile thing2end\nwait thing2end\nthing1end\n");
-delete $extraENV{MAKEFLAGS};
rmfiles(qw(inc.mk thing1start thing1end thing2start thing2end));
# Ensure intermediate/secondary files are not pruned incorrectly.
@@ -191,7 +186,7 @@ fff1.mk: ; touch $@
!,
'-j2', "touch fff1.mk\nfile TWO\nwait TWO\nfile ONE\n");
-unlink('fff1.mk', 'ONE', 'TWO');
+rmfiles('fff1.mk', 'ONE', 'TWO');
# Test if a sub-make needs to re-exec and the makefile is built via
# sub-make. Reported by Masahiro Yamada <yamada.masahiro@socionext.com>
@@ -212,7 +207,7 @@ endif
!,
'--no-print-directory -j2', "touch fff1.mk\nfile TWO\nwait TWO\nfile ONE\nrecurse\n");
-unlink('fff1.mk', 'ONE', 'TWO');
+rmfiles('fff1.mk', 'ONE', 'TWO');
# Make sure that all jobserver FDs are closed if we need to re-exec the
diff --git a/tests/scripts/features/patternrules b/tests/scripts/features/patternrules
index 6510c38..0b35408 100644
--- a/tests/scripts/features/patternrules
+++ b/tests/scripts/features/patternrules
@@ -18,32 +18,32 @@ $dir =~ s,.*/([^/]+)$,../$1,;
run_make_test(q!
.PHONY: all
-all: case.1 case.2 case.3
+all: case.1 case.2 case.3 case.4
# We can't have this, due to "Implicit Rule Search Algorithm" step 5c
#xxx: void
# 1 - existing file
-%.1: void
- @exit 1
-%.1: #MAKEFILE#
- @exit 0
+%.1: void ; @exit 1
+%.1: #MAKEFILE# ; @exit 0
# 2 - phony
-%.2: void
- @exit 1
-%.2: 2.phony
- @exit 0
+%.2: void ; @exit 1
+%.2: 2.phony ; @exit 0
.PHONY: 2.phony
# 3 - implicit-phony
-%.3: void
- @exit 1
-%.3: 3.implicit-phony
- @exit 0
+%.3: void ; @exit 1
+%.3: 3.implicit-phony ; @exit 0
3.implicit-phony:
-!, '', '');
+
+# 4 - explicitly mentioned file made by an implicit rule
+%.4: void ; @exit 1
+%.4: test.x ; @exit 0
+%.x: ;
+!,
+ '', '');
# TEST #1: make sure files that are built via implicit rules are marked
# as targets (Savannah bug #12202).
@@ -55,18 +55,14 @@ TARGETS := foo foo.out
all: $(TARGETS)
-%: %.in
- @echo $@
+%: %.in ; @echo $@
-%.out: %
- @echo $@
+%.out: % ; @echo $@
foo.in: ; @:
',
-'',
-'foo
-foo.out');
+ '', "foo\nfoo.out");
# TEST #2: make sure intermediate files that also happened to be
@@ -75,23 +71,17 @@ foo.out');
run_make_test('
$(dir)/foo.o:
-$(dir)/foo.y:
- @echo $@
+$(dir)/foo.y: ; @echo $@
-%.c: %.y
- touch $@
+%.c: %.y ; touch $@
-%.o: %.c
- @echo $@
+%.o: %.c ; @echo $@
.PHONY: install
install: $(dir)/foo.c
',
-"dir=$dir",
-"$dir/foo.y
-touch $dir/foo.c
-$dir/foo.o");
+ "dir=$dir", "$dir/foo.y\ntouch $dir/foo.c\n$dir/foo.o");
unlink("$dir/foo.c");
@@ -109,9 +99,8 @@ run_make_test('
$(dir)/foo.bar:
',
-"dir=$dir",
-"#MAKE#: *** [#MAKEFILE#:6: $dir/foo.bar] Error 1",
-512);
+ "dir=$dir",
+ "#MAKE#: *** [#MAKEFILE#:6: $dir/foo.bar] Error 1", 512);
unlink("$dir/foo.bar");
@@ -123,25 +112,16 @@ run_make_test('
.PHONY: all
all: foo.c foo.o
-%.h %.c: %.in
- touch $*.h
- touch $*.c
+%.h %.c: %.in ; touch $*.h ; touch $*.c
-%.o: %.c %.h
- echo $+ >$@
+%.o: %.c %.h ; echo $+ >$@
-%.o: %.c
- @echo wrong rule
+%.o: %.c ; @echo wrong rule
-foo.in:
- touch $@
+foo.in: ; touch $@
',
-'',
-'touch foo.in
-touch foo.h
-touch foo.c
-echo foo.c foo.h >foo.o');
+ '', "touch foo.in\ntouch foo.h ; touch foo.c\necho foo.c foo.h >foo.o\nrm foo.h");
unlink('foo.in', 'foo.h', 'foo.c', 'foo.o');
@@ -151,10 +131,8 @@ unlink('foo.in', 'foo.h', 'foo.c', 'foo.o');
run_make_test('
all: foo.s1 foo.s2 p1.foo p2.foo
-p1.% p2.%: %.orig
- @echo $@
-%.s1 %.s2: %.orig
- @echo $@
+p1.% p2.%: %.orig ; @echo $@
+%.s1 %.s2: %.orig ; @echo $@
.PHONY: foo.orig
',
@@ -215,16 +193,14 @@ run_make_test('
all: foo.x foo-mt.x
',
-'',
-"one\ntwo");
-
-1;
+ '', "one\ntwo");
# Test pattern rules building the same targets
-# See SV 54233. Rely on our standard test timeout to break the loop
+# See SV 54233.
touch('a.c');
+# a.lnk isn't listed as removed, because it's not actually created
run_make_test(q!
all: a.elf a.dbg
@@ -234,19 +210,467 @@ all: a.elf a.dbg
!,
'-j2', ": a.elf a.lnk\n: a.elf a.dbg\n");
-unlink('a.c');
+# SV 60435 : a.lnk is removed, because it is intermediate.
+run_make_test(q!
+all: a.elf a.dbg
+
+%.elf %.lnk: %.c ; touch $*.elf $*.lnk
+
+%.elf %.dbg: %.lnk ; touch $*.elf $*.dbg
+!,
+ '-j2', "touch a.elf a.lnk\ntouch a.elf a.dbg\nrm a.lnk\n");
+
+unlink('a.elf', 'a.dbg');
+
+# SV 60435 : a.lnk is not intermediate, because it is explicitly mentioned.
+run_make_test(q!
+all: a.elf a.dbg
+
+%.elf %.lnk: %.c ; touch $*.elf $*.lnk
+
+%.elf %.dbg: %.lnk ; touch $*.elf $*.dbg
+
+install: a.lnk
+.PHONY: install
+!,
+ '-j2', "touch a.elf a.lnk\ntouch a.elf a.dbg\n");
+
+unlink('a.c', 'a.elf', 'a.dbg', 'a.lnk');
# SV 56655: Test patterns matching files containing whitespace
touch('some file.yy');
run_make_test(q!
%.xx : %.yy ; @echo matched
-!, '"some file.xx"', "matched\n");
+!,
+ '"some file.xx"', "matched\n");
unlink('some file.xx', 'some file.yy');
+
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate.
+
+touch('hello.z');
+unlink('hello.x', 'test.x');
+
+# subtest 1
+# hello.x is not explicitly mentioned and thus is an intermediate file.
+run_make_test(q!
+all: hello.z
+%.z: %.x ; touch $@
+%.x: ;
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 2
+# test.x is explicitly mentioned and thus is not an intermediate file.
+run_make_test(q!
+all: hello.z
+%.z: %.x test.x ; touch $@
+%.x: ;
+!,
+ '', "touch hello.z");
+
+# subtest 3
+# hello.x is explicitly mentioned on an unrelated rule and thus is not an
+# intermediate file.
+touch('hello.z');
+run_make_test(q!
+all: hello.z
+%.z: %.x; touch $@
+%.x: ;
+unrelated: hello.x
+!,
+ '', "touch hello.z");
+
+unlink('hello.z');
+
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate, even when the builtin rules are used.
+
+touch('hello.x');
+touch('test.x');
+touch('hello.tsk');
+
+# subtest 1
+# hello.o is not explicitly mentioned and thus is an intermediate file.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.z ; @echo $@
+%.z : %.x ; @echo $@
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 2
+# test.z is explicitly mentioned and thus is not an intermediate file.
+# test.z is built first because until it's built we don't know if we
+# need to rebuild the intermediate hello.z
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.z test.z ; @echo $@
+%.z : %.x ; @echo $@
+!,
+ '', "test.z\nhello.z\nhello.tsk\n");
+
+# subtest 3
+# hello.o is not explicitly mentioned and thus is an intermediate file.
+run_make_test(q!
+all: hello.tsk
+dep:=%.o
+%.tsk: $(dep) ; @echo $@
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 4
+# Even when test.z is constructed from 2 variables it is still explicitly
+# mentioned and thus is not an intermediate file.
+# test.z is built first because until it's built we don't know if we
+# need to rebuild the intermediate hello.z
+run_make_test(q!
+all: hello.tsk
+name:=test
+suf:=.z
+%.tsk: %.z $(name)$(suf) ; @echo $@
+%.z: %.x ; @echo $@
+!,
+ '', "test.z\nhello.z\nhello.tsk\n");
+
+unlink('hello.x', 'test.x', 'hello.tsk');
+
+# Test that chained pattern rules with multiple targets remove all intermediate
+# files.
+# sv 60435.
+
+# subtest 1.
+# a.1 and a.2 are intermediate and should be removed.
+
+run_make_test(q!
+a.4:
+%.4: %.1 %.15 ; cat $^ >$@
+%.1 %.15: ; touch $*.1 $*.15
+!,
+ '', "touch a.1 a.15\ncat a.1 a.15 >a.4\nrm a.15 a.1");
+
+unlink('a.4');
+
+# subtest 2.
+# a.1 and a.2 are intermediate and should be removed.
+# a.3 is explicit and should not be removed.
+run_make_test(q!
+a.4:
+%.4: %.1 %.15 a.3 ; cat $^ >$@
+%.1 %.15: ; touch $*.1 $*.15
+%.3: ; touch $@
+!,
+ '', "touch a.3\ntouch a.1 a.15\ncat a.1 a.15 a.3 >a.4\nrm a.15 a.1");
+
+unlink('a.3', 'a.4');
+
+# subtest 3.
+# a.1 and a.2 are intermediate and should be removed.
+# a.3 is explicit and should not be removed.
+run_make_test(q!
+a.4:
+%.4: %.1 %.15 a.3 ; cat $^ >$@
+%.1 %.15 %.3: ; touch $*.1 $*.15 $*.3
+!,
+ '', "touch a.1 a.15 a.3\ncat a.1 a.15 a.3 >a.4\nrm a.15 a.1");
+
+unlink('a.3', 'a.4');
+
+# subtest 4.
+# a.1 and a.2 are intermediate and should be removed.
+# a.3 is explicit and should not be removed.
+run_make_test(q!
+a.4:
+%.4: %.1 %.15 a.3 ; cat $^ >$@
+%.3 %.1 %.15: ; touch $*.1 $*.15 $*.3
+!,
+ '', "touch a.1 a.15 a.3\ncat a.1 a.15 a.3 >a.4\nrm a.15 a.1");
+
+unlink('a.3', 'a.4');
+
+# subtest 5.
+# a.1 and a.2 are intermediate and should be removed.
+# a.3 is explicit and should not be removed.
+run_make_test(q!
+a.4:
+%.4: a.3 %.1 %.15 ; cat $^ >$@
+%.1 %.15 %.3: ; touch $*.1 $*.15 $*.3
+!,
+ '', "touch a.1 a.15 a.3\ncat a.3 a.1 a.15 >a.4\nrm a.15 a.1");
+
+unlink('a.3', 'a.4');
+
+# subtest 6.
+# a.2 is intermediate and should be removed.
+# a.1 is mentioned explicitly on an unrelated rule and should not be removed.
+run_make_test(q!
+a.3:
+%.3: %.1 %.2 ; cat $^ >$@
+%.1 %.2: ; touch $*.1 $*.2
+install: a.1
+.PHONY: install
+!,
+ '', "touch a.1 a.2\ncat a.1 a.2 >a.3\nrm a.2");
+
+unlink('a.1', 'a.3');
+
+# Test removal of intermediate files.
+
+# subtest 1.
+# hello.x is removed, because it is intermediate.
+run_make_test(q!
+hello.tsk:
+%.tsk: %.x; touch $@
+%.x: ; touch $@
+!,
+ '', "touch hello.x\ntouch hello.tsk\nrm hello.x");
+
+unlink('hello.tsk');
+
+# subtest 2.
+# Even though hello.x is intermediate, it is not removed, because it is not
+# created.
+touch('hello.x');
+
+run_make_test(q!
+hello.tsk:
+%.tsk: %.x; touch $@
+%.x: ; touch $@
+!,
+ '', "touch hello.tsk");
+
+unlink('hello.x', 'hello.tsk');
+
+# subtest 2.
+# Even though hello.x is intermediate, it is not removed, because it is not
+# created.
+run_make_test(q!
+hello.tsk:
+%.tsk: %.x; touch $@
+%.x: ; : $@
+!,
+ '', ": hello.x\ntouch hello.tsk");
+
+unlink('hello.tsk');
+
+# A target explicitly listed as a prerequisite of a pattern rule, is still
+# considered mentioned and "ought to exist".
+
+run_make_test(q!
+1.all: 1.q ; touch $@
+%.q: 1.r ; touch $@
+%.r: ; touch $@
+!,
+ '', "touch 1.r\ntouch 1.q\ntouch 1.all\n");
+
+unlink('1.all', '1.q', '1.r');
+
+# SV 63098: Verify that missing also_made in pattern rules gives a warning but
+# doesn't fail.
+
+run_make_test(q!
+%a %b : ; touch $*a
+!,
+ 'gta', "touch gta\n#MAKEFILE#:2: warning: pattern recipe did not update peer target 'gtb'.\n");
+unlink(qw(gta));
+
+# We don't warn if we didn't update the file
+utouch(-10, qw(gta));
+run_make_test(q!
+%a %b : xyzzy ; $(OP)
+xyzzy: ;
+ifdef RUN
+OP = @echo no
+endif
+!,
+ '-rR gta', "#MAKE#: 'gta' is up to date.\n");
+
+run_make_test(undef, '-rR gta RUN=1', "no\n");
+unlink(qw(gta));
+
+run_make_test(q!
+all:;
+include gta
+%a %b : ; touch $*a
+!,
+ '', "touch gta\n#MAKEFILE#:4: warning: pattern recipe did not update peer target 'gtb'.\n#MAKE#: 'all' is up to date.");
+unlink(qw(gta));
+
+run_make_test(q!
+%.c %.h : %.y; touch $*.c
+%.o: %.c; touch $@
+foo.y: ; touch $@
+!,
+ 'foo.o', "touch foo.y\ntouch foo.c\n#MAKEFILE#:2: warning: pattern recipe did not update peer target 'foo.h'.\ntouch foo.o\nrm foo.c");
+unlink(qw(foo.y foo.c foo.o));
+
+if (0) {
+# SV 12078: Missing grouped pattern peer causes remake regardless of which
+# target caused the rule to run.
+touch(qw(gta)); # but not gtb
+run_make_test(q!
+%a %b : ; touch $*a $*b
+!,
+ 'gta', "touch gta gtb\n");
+unlink(qw(gta gtb));
+
+# Ensure both goal targets are built if they depend on a grouped pattern
+touch(qw(gta)); # but not gtb
+run_make_test(q!
+x y: ; touch $@
+
+x: gta
+y: gtb
+
+%a %b : ; touch $*a $*b
+!,
+ 'x y', "touch gta gtb\ntouch x\ntouch y\n");
+
+# Now everything should be up to date
+run_make_test(undef, 'x y',
+ "#MAKE#: 'x' is up to date.\n#MAKE#: 'y' is up to date.");
+
+unlink(qw(x y gta gtb));
+
+# sv 12078 : make sure we notice when all targets need to be rebuilt
+# a.1st exists but b.1st doesn't: make sure a.2nd is out of date as well
+
+utouch(-20, 'a.1st');
+utouch(-10, 'a.2nd', 'b.2nd');
+
+run_make_test(q!
+1st := a.1st b.1st
+2nd := ${1st:.1st=.2nd}
+.PHONY: all
+all: ${2nd}
+a.% b.% : ; touch a.$* b.$*
+${2nd}: %.2nd: %.1st ; cp $< $@
+!
+ , '', "touch a.1st b.1st\ncp a.1st a.2nd\ncp b.1st b.2nd\n");
+
+unlink(qw(a.1st b.1st a.2nd b.2nd));
+
+# Variation: b.1st exists but is newer
+
+utouch(-20, 'a.1st');
+utouch(-10, 'a.2nd', 'b.2nd');
+touch(qw(b.1st));
+
+run_make_test(undef, '', "cp b.1st b.2nd\n");
+
+unlink(qw(a.1st b.1st a.2nd b.2nd));
+}
+
+# sv 62206.
+
+# The following combinations are generated with and without second expansion.
+# 1.
+# all: bye.x
+# %.x: ...
+#
+# 2.
+# all: lib/bye.x
+# %.x: ...
+#
+# 3.
+# all: lib/bye.x
+# lib/%.x: ...
+#
+# The following combination is not generated, because there is no rule to
+# build bye.x, no stem substitution takes place, not of interest of this test.
+# 4.
+# all: bye.x
+# lib/%.x: ...
+
+my @dir = ('', 'lib/'); # With and without last slash.
+my @secondexpansion = ('', '.SECONDEXPANSION:');
+
+for my $se (@secondexpansion) {
+for my $d (@dir) { # The directory of the prerequisite of 'all'.
+for my $r (@dir) { # The directory of the target in the rule definition.
+(!$d && $r) && next; # Combination 4.
+my $dollar = $se ? '$' : '';
+
+# The prerequisite should only have directory if the prerequisite of 'all' has
+# it and if the prequisite pattern in the rule definition does not have it.
+# That is combination 2.
+my $pdir = $d && !$r ? $d : '';
+
+my $prereqs = "${pdir}bye.1";
+
+# One func, one %.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(firstword %.1); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+$prereqs = "${pdir}bye.1 ${pdir}bye.2";
+
+# Multiple funcs, each has one %.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(firstword %.1) $dollar\$(firstword %.2); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+$prereqs = "${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4";
+
+# Multiple funcs, each has multiple %.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(wordlist 1, 99, %.1 %.2) $dollar\$(wordlist 1, 99, %.3 %.4); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+$prereqs = "${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4";
+
+# Nested functions.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(wordlist 1, 99, $dollar\$(wordlist 1, 99, %.1 %.2)) $dollar\$(wordlist 1, 99, $dollar\$(wordlist 1,99, %.3 %.4)); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+$prereqs = "${pdir}bye1%2% ${pdir}bye ${pdir}3bye4%5 ${pdir}6bye ${pdir}bye7%8 ${pdir}bye9 ${pdir}bye10% ${pdir}11bye12 13";
+
+# Multiple funcs, each has multiple words, each word has multiple %, sole %,
+# various corner cases.
+# Make should substitute the first % and only the first % in each word with the
+# stem.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(wordlist 1, 99, %1%2% % 3%4%5 6%) %7%8 %9 $dollar\$(wordlist 1, 99, %10% 11%12) 13; \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+if ($port_type eq 'UNIX') {
+# Test that make does not use some hardcoded array of a finite size on stack.
+# Long prerequisite name. This prerequisite name is over 66K long.
+my $prefix = 'abcdefgh' x 128 x 33; # 33K long.
+my $suffix = 'stuvwxyz' x 128 x 33; # 33K long.
+$prereqs = "${pdir}${prefix}bye${suffix}.1 ${pdir}${prefix}bye${suffix}.2";
+
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(wordlist 1, 99, ${prefix}%${suffix}.1 ${prefix}%${suffix}.2); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+}
+
+}
+}
+}
+
# This tells the test driver that the perl test script executed properly.
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/features/reinvoke b/tests/scripts/features/reinvoke
index d2a1f50..07cbbfb 100644
--- a/tests/scripts/features/reinvoke
+++ b/tests/scripts/features/reinvoke
@@ -17,9 +17,7 @@ $omkfile = $makefile;
run_make_test('
all: ; @echo running rules.
-#MAKEFILE# incl.mk: incl-1.mk
- @echo rebuilding $@
- @echo >> $@
+#MAKEFILE# incl.mk: incl-1.mk ; @echo rebuilding $@; echo >> $@
include incl.mk',
'', "rebuilding incl.mk\nrunning rules.\n");
@@ -45,17 +43,17 @@ all: ; @echo hello
a : b ; echo >> $@
-b : c ; [ -f $@ ] || echo >> $@
+b : c ; test -f $@ || echo >> $@
c: ; echo >> $@
include $(F)',
- 'F=a', "[ -f b ] || echo >> b\nhello\n");
+ 'F=a', "test -f b || echo >> b\nhello\n");
# Now try with the file we're not updating being the actual file we're
# including: this and the previous one test different parts of the code.
-run_make_test(undef, 'F=b', "[ -f b ] || echo >> b\nhello\n");
+run_make_test(undef, 'F=b', "test -f b || echo >> b\nhello\n");
&rmfiles('a','b','c');
@@ -74,9 +72,109 @@ foo30723: ; @touch $@
unlink('foo30723');
+# If ANY makefile is rebuilt then we should re-exec
+
+run_make_test('
+all: ; @echo RESTARTS=$(MAKE_RESTARTS)
+
+m1.d: ; @echo $@; touch $@
+
+m2.d: m1.d ; @test -f $< || { echo $@; touch $@; }
+
+include m1.d
+-include m2.d
+',
+ '', "m1.d\nRESTARTS=1\n");
+
+unlink('m1.d', 'm2.d');
+
+# Same as before but be sure we get error messages for un-created makefiles
+run_make_test('
+all: ; @echo RESTARTS=$(MAKE_RESTARTS)
+
+m1.d: ; @echo $@; touch $@
+
+m2.d: m1.d ; @test -f $< || { echo $@; touch $@; }
+
+include m1.d m2.d
+', '',
+ # This runs afoul of https://savannah.gnu.org/bugs/?61226
+ 0 ? "m1.d\n#MAKEFILE#:8: m2.d: $ERR_no_such_file"
+ : "m1.d\nRESTARTS=1",
+ 0 ? 512 : 0);
+
+unlink('m1.d', 'm2.d');
+
+# sv 61226.
+# This set of four cases tests two aspects of make.
+#
+# 1. If a rule has no prerequisites or recipe, and the target of the rule is a
+# nonexistent file, then make imagines this target to have been updated
+# whenever its rule is run.
+#
+# 2. Make does not re-execute itself in this case of imagined target.
+#
+# Test case 1.
+# Make imagines hello.d was updated by a rule without recipe and without
+# prereqs.
+# This should succeed.
+# Make should not re-execute itself.
+run_make_test('
+hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
+hello.d:
+include hello.d
+', '', "RESTARTS=\n#MAKE#: 'hello.o' is up to date.");
+
+# Test case 2.
+# Make imagines hello.d was updated by a rule with a recipe and without
+# prereqs.
+# This should succeed.
+# Make should not re-execute itself.
+run_make_test('
+hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
+hello.d:; $(info $@)
+include hello.d
+', '', "hello.d\nRESTARTS=\n#MAKE#: 'hello.o' is up to date.");
+
+&touch('hello.td');
+# Test case 3.
+# Make imagines hello.d was updated by a rule without a recipe and with
+# prereqs.
+# This should succeed.
+# Make should not re-execute itself.
+run_make_test('
+hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
+hello.d: hello.td
+include hello.d
+', '', "RESTARTS=\n#MAKE#: 'hello.o' is up to date.");
+
+# Test case 4.
+# Same test as three tests above, but the rule has both recipe and prereqs.
+# Make should report this error.
+run_make_test('
+hello.o: hello.d; $(info $@)
+hello.d: hello.td; $(info $@)
+include hello.d
+', '',
+ # This runs afoul of https://savannah.gnu.org/bugs/?61226
+ 0 ? "hello.d\n#MAKEFILE#:4: hello.d: $ERR_no_such_file"
+ : "hello.d\nhello.o\n#MAKE#: 'hello.o' is up to date.",
+ 0 ? 512 : 0);
+
+unlink('hello.td');
+
+# Test DV 62088 : make sure we don't re-invoke for stdin makefiles.
+# The test framework doesn't seem to have a good way to do this.
+
+create_file('input.mk', "all:;\$(info all)\n");
+
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "input.mk: $!\n";
+
+run_make_test('', '-sf -', "all\n");
+
+close(STDIN);
+unlink('input.mk');
+
# This tells the test driver that the perl test script executed properly.
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/features/se_explicit b/tests/scripts/features/se_explicit
index c28641c..d1247d4 100644
--- a/tests/scripts/features/se_explicit
+++ b/tests/scripts/features/se_explicit
@@ -185,9 +185,9 @@ foo: $$@.o ;
# Not creating libcat.a here prevents segfault,
libcat.a: ; @touch $@
!,
- '', q!#MAKEFILE#:16: Recipe was specified for file '-lcat' at #MAKEFILE#:19,
+ '', q!#MAKEFILE#:16: Recipe was specified for file '-lcat' at #MAKEFILE#:16,
#MAKEFILE#:16: but '-lcat' is now considered the same file as 'libcat.a'.
-#MAKEFILE#:16: Recipe for 'libcat.a' will be ignored in favor of the one for '-lcat'.!);
+#MAKEFILE#:16: Recipe for '-lcat' will be ignored in favor of the one for 'libcat.a'.!);
unlink('libcat.a');
# SV 28456 : Don't reset $$< for default recipes
@@ -200,4 +200,305 @@ biz: $$(info $$<)
!,
'', "baz\n#MAKE#: Nothing to be done for 'biz'.\n");
+
+# sv 60659. Second expansion of automatic variables inside a function in the
+# prerequisite list.
+# $$@ expands to the target in the 1st and following rules.
+# $$<,$$^,$$+,$$|,$$?,$$*,$$% expand to the empty string in the prerequisite
+# list of the 1st rule.
+# $$<,$$^,$$+,$$|,$$?,$$*,$$% in the prerequisite list of the 2nd (and
+# following) rule expand to the values from the 1st rule.
+
+
+# subtest 1. Explicit rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+2.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 2. Explicit rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x 1.x
+15.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.x: 1.z 2.z 2.z | 3.z 4.z
+15.x 1.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=,%=
+@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 3. Grouped targets in explicit rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x
+15.x 1.x&: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=15.x,<=,^=,+=,|=,?=,*=,%=
+@=1.x,<=,^=,+=,|=,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 4. Grouped targets in explicit rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x 1.x
+15.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.x: 1.z 2.z 2.z | 3.z 4.z
+15.x 1.x&: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=,%=
+@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Double colon rules.
+# Because each double colon rule is independent of the other double colon rules
+# for the same target, each automatic variable in the prerequisite list, other
+# than $$@, second expands to the empty string in any rule, 1st, 2nd or later.
+
+# subtest 5. 1st double colon rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+2.x:: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 6. 2nd double colon rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x 1.x
+15.x:: 5.z 6.z 5.z | 7.z 7.z 8.z ;
+1.x:: 1.z 2.z 2.z | 3.z 4.z ;
+15.x 1.x:: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=15.x,<=,^=,+=,|=,?=,*=,%=
+@=1.x,<=,^=,+=,|=,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# sv 62324.
+# Integrity self check.
+run_make_test(q!
+.SECONDEXPANSION:
+all: bye.x
+bye.x: $$(firstword bye.1;
+!, '', "#MAKEFILE#:4: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+
+unlink('hello.tsk', 'test.o', 'bye.tsk', 'hello.o', 'hello.h', 'hello.q', 'bye.c', 'bye.o');
+
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the targets which
+# are not built.
+# Here, hello.tsk is built and its prerequisites are second expanded.
+# bye.tsk is not built and its prerequisites are not second expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Multipe rules per target.
+run_make_test(q!
+.SECONDEXPANSION:
+
+all: hello.tsk
+dep1:=hello.o
+dep2:=hello.h
+hello.tsk: $$(dep1)
+hello.tsk: $$(dep2); $(info $@ from $^)
+hello.o:; $(info $@)
+hello.h:; $(info $@)
+!, 'hello.tsk',
+"hello.h
+hello.o
+hello.tsk from hello.h hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Multiple targets per rule.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk bye.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Grouped targets.
+run_make_test(q!
+.SECONDEXPANSION:
+world.tsk: world.o $$(info 1 second expansion of $$@ prereqs)
+hello.tsk world.tsk &: hello.o $$(info 2 second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+world.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"2 second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+2 second expansion of world.tsk prereqs
+1 second expansion of world.tsk prereqs
+second expansion of world.o prereqs
+world.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Order only.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:| hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+bye.tsk:| bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+hello.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 1 rule per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk:: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 2 rules per targets.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: hello.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+hello.tsk:: hello.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+bye.tsk:: bye.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+bye.tsk:: bye.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+hello.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+hello.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+bye.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+bye.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+!, 'hello.tsk',
+"1 second expansion of hello.tsk prereqs
+1 second expansion of hello.o prereqs
+1 hello.o
+2 second expansion of hello.o prereqs
+2 hello.o
+1 hello.tsk from hello.o
+2 second expansion of hello.tsk prereqs
+2 hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Test that the prerequisites of 'hello.tsk' are second expanded once.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk hello.q
+hello.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+hello.q: hello.tsk $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+!, '',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+second expansion of hello.q prereqs
+hello.q from hello.tsk
+#MAKE#: Nothing to be done for 'all'.\n");
+
+# sv 62706.
+# Merge vpath file and local file.
+# Test that both sets of prerequisites from 'hello.c' rule and from
+# 'src/hello.c' rule are second expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+vpath hello.c src
+all: hello.c; $(info $@ from $^)
+hello.c: $$(info second expansion of hello.c prereqs); $(info 1 $@)
+src/hello.c: $$(info second expansion of src/hello.c prereqs); $(info 2 $@)
+!, '',
+"#MAKEFILE#:5: Recipe was specified for file 'hello.c' at #MAKEFILE#:5,
+#MAKEFILE#:5: but 'hello.c' is now considered the same file as 'src/hello.c'.
+#MAKEFILE#:5: Recipe for 'hello.c' will be ignored in favor of the one for 'src/hello.c'.
+second expansion of src/hello.c prereqs
+second expansion of hello.c prereqs
+2 src/hello.c
+all from src/hello.c
+#MAKE#: 'all' is up to date.\n");
+
+# sv 62706.
+# .DEFAULT.
+run_make_test(q!
+.SECONDEXPANSION:
+bye:=bye.c
+all: hello.o
+.DEFAULT: $$(info second expansion of prereqs of default recipe @ = $$@) ; $(info default recipe $@)
+!, '',
+"default recipe hello.o
+#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.1');
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:; exit 1
+unrelated: $$(shell touch hello.1);
+!, '',
+"exit 1
+#MAKE#: *** [#MAKEFILE#:3: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is explicit.
+# .SECONDARY marks hello.x as intermediate.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+.SECONDARY: hello.x
+all: hello.x
+hello.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
1;
diff --git a/tests/scripts/features/se_implicit b/tests/scripts/features/se_implicit
index 866d1fb..c9d7ca9 100644
--- a/tests/scripts/features/se_implicit
+++ b/tests/scripts/features/se_implicit
@@ -262,5 +262,245 @@ run_make_test(q!
!,
'q/ux', "q/u\nq/u\n");
+
+
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate.
+
+touch('hello.z');
+
+# subtest 1.
+# hello.x is derived from the stem and thus is an intermediate file.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=.x
+all: hello.z
+%.z: %$$(dep) ; @echo $@
+%.x: ;
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 2.
+# test.x is explicitly mentioned and thus is not an intermediate file.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=test.x
+all: hello.z
+%.z: %.x $$(dep) ; @echo $@
+%.x: ;
+!, '', "hello.z\n");
+
+# subtest 3.
+# make is building hello.z and does not second expand the prerequisites of rule
+# 'unrelated: $$(dep)'. '$$(dep)' stays not expanded and 'hello.x' is never
+# entered to the database. Make considers 'hello.x' intermediate while building
+# 'hello.z'. Because 'hello.z' is present and 'hello.x' is missing and
+# 'hello.x' is intermediate, there is no need to rebuild 'hello.z'.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=hello.x
+all: hello.z
+%.z: %.x; @echo $@
+%.x: ;
+unrelated: $$(dep)
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 4.
+# Just like subtest 3. $$(dep) is not second expanded. 'hello.x' is
+# intermediate.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=hello.x
+all: hello.z
+%.z: %.x; @echo $@
+%.x: ;
+%.q: $$(dep)
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.z');
+
+
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate, even when the builtin rules are used.
+
+touch('hello.x');
+touch('hello.tsk');
+
+# subtest 1.
+# hello.z is explicitly mentioned and thus is not an intermediate file.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=hello.z
+all: hello.tsk
+%.tsk: $$(dep) ; @echo $@
+%.z : %.x ; @echo $@
+!, '', "hello.z\nhello.tsk");
+
+# subtest 2.
+# hello.z is derived from the stem and thus is an intermediate file.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=.z
+all: hello.tsk
+%.tsk: %$$(dep) ; @echo $@
+%.z : %.x ; @echo $@
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.x');
+unlink('hello.tsk');
+
+
+# sv 60659. Second expansion of automatic variables inside a function in the
+# prerequisite list.
+# $$@ expands to the target in the 1st and following rules.
+# $$* expands to the stem in the 1st and following rules.
+# $$<,$$^,$$+,$$|,$$?,$$% expand to the empty string in the prerequisite list
+# of the 1st rule.
+# $$<,$$^,$$+,$$|,$$?,$$% in the prerequisite list of the 2nd (and following)
+# rule expand to the values from the 1st rule.
+# $$% cannot be used in prerequisites, because in pattern rules % is
+# substituted for stem.
+
+
+# subtest 1. Pattern rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+%.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=2
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 2. Pattern rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x 1.x
+2.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.x: 1.z 2.z 2.z | 3.z 4.z
+%.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=2
+@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 3. Static pattern rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+2.x: %.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=2
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 4. Static pattern rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x 1.x
+15.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.x: 1.z 2.z 2.z | 3.z 4.z
+15.x 1.x: %.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=15
+@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 5. Grouped targets in implicit rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+%.x %.xx&: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=2
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 6. Grouped targets in implicit rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x 1.xx
+2.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.xx: 1.z 2.z 2.z | 3.z 4.z
+%.x %.xx&: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=2
+@=1.xx,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 7. Double colon rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+%.x:: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+5.z 6.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=2
+#MAKE#: Nothing to be done for 'all'.\n");
+
+# sv 62324.
+# Integrity self check.
+run_make_test(q!
+.SECONDEXPANSION:
+all: bye.x
+%.x: $$(firstword %.1;
+!, '', "#MAKE#: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the rules which are
+# not tried during implicit search.
+# Here, make tries rules '%.tsk: %.o' and '%.o' and their prerequisites are
+# second expanded.
+# Rules '%.bin: %.x' and '%.x:' are not used in implicit search for 'hello.tsk'
+# and 'hello.o' and their prerequisites are not expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+%.bin: %.x $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+%.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+%.x: $$(info second expansion of $$@ prereqs); $(info $@)
+%.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, '-R hello.tsk',
+"second expansion of hello.o prereqs
+second expansion of hello.tsk prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk
+%.tsk: %.o; exit 1
+hello.o:;
+%.q: $$(shell touch hello.1);
+!, '',
+"exit 1
+#MAKE#: *** [#MAKEFILE#:4: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is implicit.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.\n");
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/se_statpat b/tests/scripts/features/se_statpat
index b1e59e1..935ff3f 100644
--- a/tests/scripts/features/se_statpat
+++ b/tests/scripts/features/se_statpat
@@ -91,17 +91,142 @@ baz.a.2
#
run_make_test(q!
.SECONDEXPANSION:
-foo$$bar: f%r: % $$*.1
- @echo '$*'
+foo$$bar: f%r: % $$*.1 ; @echo '$*'
-oo$$ba oo$$ba.1:
- @echo '$@'
+oo$$ba oo$$ba.1: ; @echo '$@'
!,
'', 'oo$ba
oo$ba.1
oo$ba
');
+# sv 62324.
+# Integrity self check.
+run_make_test(q!
+.SECONDEXPANSION:
+all: bye.x
+bye.x: %.x: $$(firstword %.1;
+!, '', "#MAKEFILE#:4: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+
+#unlink('hello.tsk', 'bye.tsk', 'hello.o', 'hello.q', 'bye.o');
+
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the targets which
+# are not built.
+# Here, hello.tsk is built and its prerequisites are second expanded.
+# bye.tsk is not built and its prerequisites are not second expanded.
+
+# Static pattern rules.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Order only prereqs.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: %.tsk:| %.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+bye.tsk: %.tsk:| %.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+hello.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 1 rule per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 2 rules per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: %.tsk: %.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+hello.tsk:: %.tsk: %.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+hello.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+hello.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+bye.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+bye.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+!, 'hello.tsk',
+"1 second expansion of hello.tsk prereqs
+1 second expansion of hello.o prereqs
+1 hello.o
+2 second expansion of hello.o prereqs
+2 hello.o
+1 hello.tsk from hello.o
+2 second expansion of hello.tsk prereqs
+2 hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Test that the prerequisites of 'hello.tsk' are second expanded once.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk hello.q
+hello.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+hello.q: %.q: %.tsk $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+!, '',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+second expansion of hello.q prereqs
+hello.q from hello.tsk
+#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.1');
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk
+hello.tsk: %.tsk: %.o; exit 1
+hello.o:;
+bye.tsk: %.tsk: $$(shell touch hello.1);
+!, '',
+"exit 1
+#MAKE#: *** [#MAKEFILE#:4: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is static pattern.
+# .SECONDARY marks hello.x as intermediate.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+.SECONDARY: hello.x
+all: hello.x
+hello.x: %.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\n#MAKE#: Nothing to be done for 'all'.\n");
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/statipattrules b/tests/scripts/features/statipattrules
index 3f363de..e4e118e 100644
--- a/tests/scripts/features/statipattrules
+++ b/tests/scripts/features/statipattrules
@@ -72,13 +72,15 @@ foo.baz: ;@:
# perprerequisite's stem (Savannah bug #16053).
#
run_make_test('
+.RECIPEPREFIX := >
+
all.foo.bar: %.foo.bar: %.one
all.foo.bar: %.bar: %.two
all.foo.bar:
- @echo $*
- @echo $^
+> @echo $*
+> @echo $^
.DEFAULT:;@:
',
@@ -92,6 +94,7 @@ all.one all.foo.two');
# (Savannah bug #16053).
#
run_make_test('
+.RECIPEPREFIX := >
.SECONDEXPANSION:
all.foo.bar: %.foo.bar: %.one $$*-one
@@ -99,8 +102,8 @@ all.foo.bar: %.foo.bar: %.one $$*-one
all.foo.bar: %.bar: %.two $$*-two
all.foo.bar:
- @echo $*
- @echo $^
+> @echo $*
+> @echo $^
.DEFAULT:;@:
',
@@ -108,4 +111,201 @@ all.foo.bar:
'all.foo
all.one all-one all.foo.two all.foo-two');
+# Test #8:
+# sv 60188.
+# Static pattern rules are considered explicit rules: no prerequisite of
+# a static pattern rule can ever be considered intermediate.
+
+touch('hello.z');
+
+# subtest 1
+run_make_test(q!
+hello.z: %.z: %.x ; @echo $@
+%.x: ;
+!, '', "hello.z\n");
+
+# subtest 2
+run_make_test(q!
+hello.z: %.z: %.x test.x ; @echo $@
+%.x: ;
+!, '', "hello.z\n");
+
+# subtest 3
+# 'hello.x' is mentioned explicitly on an unrelated rule.
+run_make_test(q!
+hello.z: %.z: %.x ; @echo $@
+%.x: ;
+unrelated: hello.x
+!, '', "hello.z\n");
+
+unlink('hello.z');
+
+# sv 17374 Ensure double-colon static pattern rules work
+
+touch(qw(a.src b.src));
+
+run_make_test(q!
+all: a.tgt b.tgt
+a.tgt b.tgt:: %.tgt : %.src ; cp $< $@
+!,
+ '', "cp a.src a.tgt\ncp b.src b.tgt\n");
+
+unlink(qw(a.src b.src a.tgt b.tgt));
+
+my @dir = ('', 'lib/'); # With and without last slash.
+my @secondexpansion = ('', '.SECONDEXPANSION:');
+
+# The following combinations are generated with and without second expansion.
+# 1.
+# all: bye.x
+# bye.x: %.x: ...
+#
+# 2.
+# all: lib/bye.x
+# lib/bye.x: %.x: ...
+#
+# 3.
+# all: lib/bye.x
+# lib/bye.x: lib/%.x: ...
+#
+# The following combination is not generated, because there is no rule to
+# build bye.x, no stem substitution takes place, not of interest of this test.
+# 4.
+# all: bye.x
+# bye.x: lib/%.x: ...
+#
+
+for my $se (@secondexpansion) {
+for my $d (@dir) { # The directory of the prerequisite of 'all'.
+for my $r (@dir) { # The directory of the prerequisite in the rule definition.
+(!$d && $r) && next; # Combination 4.
+my $dollar = $se ? '$' : '';
+
+# The prerequisite should only have directory if the prerequisite of 'all' has
+# it and if the prequisite pattern in the rule definition does not have it.
+# That is combination 2.
+my $pdir = $d && !$r ? $d : '';
+
+
+# One func, one %.
+my $prereqs = "${pdir}bye.1";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(firstword %.1); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Multiple funcs, each has one %.
+$prereqs = "${pdir}bye.1 ${pdir}bye.2";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(firstword %.1) $dollar\$(firstword %.2); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Multiple funcs, each has multiple %.
+$prereqs = "${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, %.1 %.2) $dollar\$(wordlist 1, 99, %.3 %.4); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Multiple funcs, each has multiple %, each prerequisite has multiple %.
+$prereqs = "${pdir}bye_%_%.1 ${pdir}bye_%_%.2 ${pdir}bye_%_%.3 ${pdir}bye_%_%.4";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, %_%_%.1 %_%_%.2) $dollar\$(wordlist 1, 99, %_%_%.3 %_%_%.4); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Nested functions.
+$prereqs = "${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, $dollar\$(wordlist 1, 99, %.1 %.2)) $dollar\$(wordlist 1, 99, $dollar\$(wordlist 1,99, %.3 %.4)); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Multiple funcs, each has multiple words, each word has multiple %, sole %,
+# various corner cases.
+# Make should substitude the first % and only the first % in each word with the
+# stem.
+$prereqs = "${pdir}bye1%2% ${pdir}bye 3${pdir}bye4%5 6${pdir}bye ${pdir}bye7%8 ${pdir}bye9 ${pdir}bye10% 11${pdir}bye12 13";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, %1%2% % 3%4%5 6%) %7%8 %9 $dollar\$(wordlist 1, 99, %10% 11%12) 13; \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+if ($port_type eq 'UNIX') {
+# Test that make does not use some hardcoded array of a finite size on stack.
+# Long prerequisite name. This prerequisite name is over 66K long.
+my $prefix = 'abcdefgh' x 128 x 33; # 33K long.
+my $suffix = 'stuvwxyz' x 128 x 33; # 33K long.
+$prereqs = "${prefix}${pdir}bye${suffix}.1 ${prefix}${pdir}bye${suffix}.2";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, ${prefix}%${suffix}.1 ${prefix}%${suffix}.2); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+}
+
+
+# Empty stem.
+$prereqs = "${pdir}.1";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%bye.x: $dollar\$(firstword %.1); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# A word expands to an empty prerequisite.
+run_make_test("
+$se
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(%); \$(info \$@ from \$^)
+", '', "${d}bye.x from \n#MAKE#: Nothing to be done for 'all'.\n");
+
+}
+}
+}
+
+# Escaped %.
+# The following combinations are generated without second expansion.
+# 1.
+# all: the%weird\\_hello_pattern\\.x
+# the\\%weird\\_hello_pattern\\.x: the\\%weird\\_%_pattern\\.x: ...
+#
+# 2.
+# all: lib/the%weird\\_hello_pattern\\.x
+# lib/the\\%weird\\_hello_pattern\\.x: lib/the\\%weird\\_%_pattern\\.x: ...
+#
+# Other combinations or second expansion are not tested, because escaped % is
+# not implemented for those.
+
+for my $d (@dir) {
+my $prereqs = "${d}the%weird\\\\_hello_pattern%\\\\.1 ${d}the%weird\\\\_hello_pattern%\\\\.2";
+run_make_test("
+.PHONY: $prereqs
+all: ${d}the%weird\\\\_hello_pattern\\\\.x
+${d}the\\%weird\\\\_hello_pattern\\\\.x: ${d}the\\%weird\\\\_%_pattern\\\\.x: \$(wordlist 1, 99, ${d}the\\%weird\\\\_%_pattern%\\\\.1 ${d}the\\%weird\\\\_%_pattern%\\\\.2); \$(info \$@ from \$^)
+", '', "${d}the%weird\\\\_hello_pattern\\\\.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+}
+
1;
diff --git a/tests/scripts/features/targetvars b/tests/scripts/features/targetvars
index 2929b2c..5088251 100644
--- a/tests/scripts/features/targetvars
+++ b/tests/scripts/features/targetvars
@@ -12,8 +12,9 @@ export BAR = bar
one: override FOO = one
one two: ; @echo $(FOO) $(BAR)
two: BAR = two
+.RECIPEPREFIX = >
three: ; BAR=1000
- @echo $(FOO) $(BAR)
+> @echo $(FOO) $(BAR)
# Some things that shouldn not be target vars
funk : override
funk : override adelic
@@ -86,7 +87,6 @@ run_make_test(undef, "foo.q bar.q", "qvar = rvar\nqvar =\n");
run_make_test(undef, "foo.t bar.s", "qvar = qvar\nqvar =\n");
-
# TEST #8
# For PR/1378: Target-specific vars don't inherit correctly
@@ -183,7 +183,7 @@ run_make_test(undef, 'foo PATTERN=yes', "ok ok foo pat\nok ok foo pat\n");
# (> make default buffer length)
run_make_test('
-base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if [ -f "build_information.generate" ]; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi )
+base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if test -f "build_information.generate" ; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi )
deals_changed_since: ; @echo $(BUILD_OBJ)
',
@@ -270,17 +270,158 @@ all: ; $sname >/dev/null
# Don't use the general PATH if not found on the target path
-$extraENV{PATH} = "$ENV{PATH}:sd";
+$ENV{PATH} = "$ENV{PATH}:sd";
+
+my ($ernum, $erstr);
+if ($port_type eq 'W32') {
+ $ernum = 1;
+ $erstr = "'$sname' is not recognized as an internal or external command,\noperable program or batch file.";
+} else {
+ $ernum = 127;
+ $erstr = "#MAKE#: $sname: $ERR_no_such_file";
+}
run_make_test(qq!
all: PATH := ..
all: ; $sname
!,
- '', "$sname\n#MAKE#: $sname: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:3: all] Error 127", 512);
+ '', "$sname\n$erstr\n#MAKE#: *** [#MAKEFILE#:3: all] Error $ernum", 512);
unlink("sd/$sname");
rmdir ('sd');
+# SV 59230: Conditional (non-)assignment of target-specific variables should
+# preserve export settings.
+
+$ENV{hello} = 'moon';
+run_make_test(q!
+all:; @echo hello=$$hello
+dummy: hello?=world
+!,
+ '', 'hello=moon');
+
+# SV 59230: Assignment of a global variable should not affect export of a
+# target specific variable.
+
+$ENV{hello} = "moon";
+run_make_test(q!
+all:; @echo hello=$$hello
+hello=sun
+dummy: hello?=world
+!,
+ '', 'hello=sun');
+
+# Support target-specific unexport
+
+$ENV{hello} = "moon";
+run_make_test(q!
+unexport hello=sun
+all: base exp
+base exp: ; @echo hello=$$hello
+exp: export hello=world
+!,
+ '', "hello=\nhello=world\n");
+
+$ENV{hello} = "moon";
+run_make_test(q!
+hello=sun
+all: base exp
+base exp: ; @echo hello=$$hello
+exp: unexport hello=world
+!,
+ '', "hello=sun\nhello=\n");
+
+run_make_test(q!
+all:; @echo hello=$$hello
+unexport hello=sun
+dummy: hello?=world
+!,
+ '', 'hello=');
+
+$ENV{hello} = "moon";
+run_make_test(q!
+all:; @echo hello=$$hello
+hello=sun
+dummy: unexport hello=world
+!,
+ '', 'hello=sun');
+
+run_make_test(q!
+all: mid
+mid: base
+
+ifeq ($(midexport),export)
+mid: export hello=mid
+else ifeq ($(midexport),unexport)
+mid: unexport hello=mid
+else
+mid: hello=mid
+endif
+
+ifeq ($(baseexport),export)
+base: export hello=base
+else ifeq ($(baseexport),unexport)
+base: unexport hello=base
+else
+base: hello=base
+endif
+
+all mid base:; @echo $@ make=$(hello) shell=$$hello
+!,
+ '', "base make=base shell=\nmid make=mid shell=\nall make= shell=\n");
+
+# Test base settings with env var
+$ENV{hello} = "environ";
+run_make_test(undef,
+ '', "base make=base shell=base\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'baseexport=export', "base make=base shell=base\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'baseexport=unexport', "base make=base shell=\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+# Test mid settings with env var
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'midexport=export', "base make=base shell=base\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'midexport=export baseexport=unexport', "base make=base shell=\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'midexport=unexport', "base make=base shell=\nmid make=mid shell=\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'midexport=unexport baseexport=export', "base make=base shell=base\nmid make=mid shell=\nall make=environ shell=environ\n");
+
+# Test base settings without env var
+run_make_test(undef,
+ 'baseexport=export', "base make=base shell=base\nmid make=mid shell=\nall make= shell=\n");
+
+run_make_test(undef,
+ 'baseexport=unexport', "base make=base shell=\nmid make=mid shell=\nall make= shell=\n");
+
+# Test mid settings with env var
+run_make_test(undef,
+ 'midexport=export', "base make=base shell=base\nmid make=mid shell=mid\nall make= shell=\n");
+
+run_make_test(undef,
+ 'midexport=export baseexport=unexport', "base make=base shell=\nmid make=mid shell=mid\nall make= shell=\n");
+
+run_make_test(undef,
+ 'midexport=unexport', "base make=base shell=\nmid make=mid shell=\nall make= shell=\n");
+
+run_make_test(undef,
+ 'midexport=unexport baseexport=export', "base make=base shell=base\nmid make=mid shell=\nall make= shell=\n");
+
+
+
# TEST #19: Test define/endef variables as target-specific vars
# run_make_test('
@@ -296,7 +437,3 @@ rmdir ('sd');
# '', "local\n");
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/features/temp_stdin b/tests/scripts/features/temp_stdin
new file mode 100644
index 0000000..b06df53
--- /dev/null
+++ b/tests/scripts/features/temp_stdin
@@ -0,0 +1,118 @@
+# -*-mode: perl-*-
+
+$description = "Test handling of temporary file created from stdin.";
+
+# These tests rely on the test_driver checking for leftover temporary content
+
+create_file('input.mk', "world:=1\n");
+create_file('bye.mk', "moon:=2\n");
+
+# sv 62118,62145.
+# Test that makes leaves no temp file when make code is piped to stdin and -v,
+# -h or an invalid option is specified.
+my @opts = ('-v', '-h', '--nosuchopt');
+my @exit_codes = (0, 0, 512);
+for my $i (0 .. $#opts) {
+ close(STDIN);
+ open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+ run_make_test(q!
+all:; $(info hello world)
+!,
+ "$opts[$i] -f-", "/uilt for /", $exit_codes[$i]);
+}
+
+# sv 62118,62145.
+# Test that a stdin temp file is removed.
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+run_make_test(q!
+all:; $(info world=$(world))
+!,
+ '-f-', "world=1\n#MAKE#: 'all' is up to date.\n");
+
+# sv 62118,62145.
+# Test that a stdin temp file is removed, even when make re-execs.
+# Also test that make honors TMPDIR to create the temp file.
+# Ensure touching bye.mk causes re-exec.
+&utouch(-600, 'bye.mk');
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+run_make_test(q!
+include bye.mk
+all:; $(info hello)
+$(MAKE_RESTARTS)bye.mk: force; touch $@
+force:
+!,
+ '-R --debug=b -f-', "/Re-executing.+?--temp-stdin=\Q$temppath\E/");
+
+if ($port_type eq 'UNIX') {
+# POSIX doesn't require sh to set PPID so test this
+my $cmd = create_command();
+add_options($cmd, '-f', '/dev/null', '-E', q!all:;@echo $$PPID!);
+my $fout = 'ppidtest.out';
+run_command_with_output($fout, @$cmd);
+$_ = read_file_into_string($fout);
+chomp($_);
+if (/^[0-9]+$/) {
+use POSIX ();
+
+# sv 63157.
+# Test that make removes the temporary file which holds make code from stdin,
+# even when a signal is received.
+# include bye.mk and bye.mk: rule is needed to cause make to keep the temporary
+# file for re-exec. Without re-exec make will remove the file before the signal
+# arrives.
+# sleep is needed to let make write its "... Terminated" message to the log
+# file.
+&utouch(-600, 'bye.mk');
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+run_make_test(q!
+include bye.mk
+pid:=$(shell echo $$PPID)
+all:;
+bye.mk: force; @kill -TERM $(pid) && sleep 16
+force:
+!, '-f-', '/#MAKE#: \*\*\* \[#MAKEFILE#:5: bye.mk] Terminated/', POSIX::SIGTERM);
+}
+unlink($fout);
+
+# sv 62118,62145.
+# Test that a stdin temp file is removed, when execvp fails to re-exec make.
+# In order to cause execvp to fail, copy the tested make binary to the temp
+# directory and take away the 'x' bit.
+use File::Spec;
+use File::Copy;
+
+my $tmakedir = File::Spec->catfile($cwdpath, 'tmakedir');
+mkdir($tmakedir, 0770);
+my $makecopy = File::Spec->catfile($tmakedir, 'make');
+copy("$mkpath", $makecopy);
+# Set file mode bits, because perl copy won't.
+chmod 0700, $makecopy;
+
+my @make_orig = @make_command;
+@make_command = ($makecopy);
+
+# Ensure touching bye.mk causes re-exec.
+&utouch(-600, 'bye.mk');
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+run_make_test("
+include bye.mk
+all:; \$(info hello)
+\$(MAKE_RESTARTS)bye.mk: force; touch \$@ && chmod u-x $makecopy
+force:
+",
+ "-f-", "touch bye.mk && chmod u-x $makecopy\nmake: $makecopy: $ERR_nonexe_file\n", 32512);
+
+@make_command = @make_orig;
+unlink($makecopy);
+rmdir($tmakedir);
+}
+
+close(STDIN);
+unlink('input.mk', 'bye.mk');
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/varnesting b/tests/scripts/features/varnesting
index d8f3ffb..0fbb332 100644
--- a/tests/scripts/features/varnesting
+++ b/tests/scripts/features/varnesting
@@ -9,8 +9,7 @@ variable2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z)))
-all:
- @echo $(a)
+all: ; @echo $(a)
',
'', "Hello\n");
@@ -21,15 +20,8 @@ all:
run_make_test('
VARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE)
-wololo:
- @$(VARIABLE)
+wololo: ; @$(VARIABLE)
',
'', "hi\n");
1;
-
-
-
-
-
-
diff --git a/tests/scripts/features/vpath b/tests/scripts/features/vpath
index ec24165..7c034b5 100644
--- a/tests/scripts/features/vpath
+++ b/tests/scripts/features/vpath
@@ -1,65 +1,34 @@
# -*-perl-*-
-$description = "The following test creates a makefile to test the \n"
- ."vpath directive which allows you to specify a search \n"
- ."path for a particular class of filenames, those that\n"
- ."match a particular pattern.";
-
-$details = "This tests the vpath directive by specifying search directories\n"
- ."for one class of filenames with the form: vpath pattern directories"
- ."\nIn this test, we specify the working directory for all files\n"
- ."that end in c or h. We also test the variables $@ (which gives\n"
- ."target name) and $^ (which is a list of all dependencies \n"
- ."including the directories in which they were found). It also\n"
- ."uses the function firstword used to extract just the first\n"
- ."dependency from the entire list.";
-
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "vpath %.c foo\n";
-print MAKEFILE "vpath %.c $workdir\n";
-print MAKEFILE "vpath %.h $workdir\n";
-print MAKEFILE "objects = main.o kbd.o commands.o display.o insert.o\n";
-print MAKEFILE "edit: \$(objects)\n";
-print MAKEFILE "\t\@echo cc -o \$@ \$^\n";
-print MAKEFILE "main.o : main.c defs.h\n";
-print MAKEFILE "\t\@echo cc -c \$(firstword \$^)\n";
-print MAKEFILE "kbd.o : kbd.c defs.h command.h\n";
-print MAKEFILE "\t\@echo cc -c kbd.c\n";
-print MAKEFILE "commands.o : command.c defs.h command.h\n";
-print MAKEFILE "\t\@echo cc -c commands.c\n";
-print MAKEFILE "display.o : display.c defs.h buffer.h\n";
-print MAKEFILE "\t\@echo cc -c display.c\n";
-print MAKEFILE "insert.o : insert.c defs.h buffer.h\n";
-print MAKEFILE "\t\@echo cc -c insert.c\n";
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
+$description = "Test vpath for particular classes of filenames.";
+$details = "";
@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
- "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
- "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
- "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
- "$workdir${pathsep}command.c");
+ "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
+ "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+ "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
+ "$workdir${pathsep}command.c");
&touch(@files_to_touch);
-&run_make_with_options($makefile,"",&get_logfile);
-
-# Create the answer to what should be produced by this Makefile
-$answer = "cc -c $workdir${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n"
- ."cc -c display.c\n"
- ."cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o "
- ."insert.o\n";
+run_make_test(q!
+vpath %.c foo
+vpath %.c #WORK#
+vpath %.h #WORK#
+objects = main.o kbd.o commands.o display.o insert.o
+edit: $(objects) ; @echo cc -o $@ $^
+main.o : main.c defs.h ; @echo cc -c $(firstword $^)
+kbd.o : kbd.c defs.h command.h ; @echo cc -c kbd.c
+commands.o : command.c defs.h command.h ; @echo cc -c commands.c
+display.o : display.c defs.h buffer.h ; @echo cc -c display.c
+insert.o : insert.c defs.h buffer.h ; @echo cc -c insert.c
+!,
+ '', "cc -c $workdir${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n"
+ ."cc -c display.c\ncc -c insert.c\n"
+ ."cc -o edit main.o kbd.o commands.o display.o insert.o\n");
-if (&compare_output($answer,&get_logfile(1)))
-{
- unlink @files_to_touch;
-}
+unlink(@files_to_touch);
# TEST 2: after vpath lookup ensure we don't get incorrect circular dependency
# warnings due to change of struct file ptr. Savannah bug #13529.
@@ -78,4 +47,68 @@ vpath-d/fail.te:
rmdir('vpath-d');
+# Test VPATH vs vpath
+
+run_make_test(q!
+VPATH = #WORK#:#PWD#
+vpath %.c foo
+vpath %.c #WORK#
+vpath %.c #PWD#
+vpath %.h #WORK#
+vpath %.c
+vpath
+all: ; @echo ALL IS WELL
+!,
+ '', "ALL IS WELL\n");
+
+# Test interaction of -lfoo and vpath
+
+my @dirs_to_make = qw(a1 b1 a2 b2 b3);
+for my $d (@dirs_to_make) {
+ mkdir($d, 0777);
+}
+
+my @files_to_touch = ("a1${pathsep}lib1.a",
+ "a1${pathsep}libc.a",
+ "b1${pathsep}lib1.so",
+ "a2${pathsep}lib2.a",
+ "b2${pathsep}lib2.so",
+ "lib3.a",
+ "b3${pathsep}lib3.so");
+&touch(@files_to_touch);
+
+my $answer = "a1${pathsep}lib1.a a1${pathsep}libc.a " .
+ "a2${pathsep}lib2.a lib3.a\n";
+if ($port_type eq 'VMS-DCL') {
+ $answer =~ s/ /,/g;
+}
+
+run_make_test('
+vpath %.h b3
+vpath %.a a1
+vpath %.so b1
+vpath % a2 b2
+vpath % b3
+all: -l1 -lc -l2 -l3; @echo $^
+',
+ '', $answer);
+
+unlink(@files_to_touch);
+for my $d (@dirs_to_make) {
+ rmdir($d);
+}
+
+# Check that if we find find files with VPATH, we don't do pattern search
+
+mkdir("vpa");
+
+run_make_test(q!
+VPATH = vpa
+%.x: ; @echo pattern $@
+vpa/foo.x: ; @echo vpath $@
+!,
+ 'foo.x', "vpath vpa/foo.x\n");
+
+rmdir("vpa");
+
1;
diff --git a/tests/scripts/features/vpath2 b/tests/scripts/features/vpath2
deleted file mode 100644
index c8de29b..0000000
--- a/tests/scripts/features/vpath2
+++ /dev/null
@@ -1,45 +0,0 @@
-$description = "This is part 2 in a series to test the vpath directive\n"
- ."It tests the three forms of the directive:\n"
- ." vpath pattern directive\n"
- ." vpath pattern (clears path associated with pattern)\n"
- ." vpath (clears all paths specified with vpath)\n";
-
-$details = "This test simply adds many search paths using various vpath\n"
- ."directive forms and clears them afterwards. It has a simple\n"
- ."rule to print a message at the end to confirm that the makefile\n"
- ."ran with no errors.\n";
-
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "VPATH = $workdir:$scriptdir\n";
-print MAKEFILE "vpath %.c foo\n";
-print MAKEFILE "vpath %.c $workdir\n";
-print MAKEFILE "vpath %.c $scriptdir\n";
-print MAKEFILE "vpath %.h $workdir\n";
-print MAKEFILE "vpath %.c\n";
-print MAKEFILE "vpath\n";
-print MAKEFILE "all:\n";
-print MAKEFILE "\t\@echo ALL IS WELL\n";
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile,"",&get_logfile);
-
-# Create the answer to what should be produced by this Makefile
-$answer = "ALL IS WELL\n";
-
-&compare_output($answer,&get_logfile(1));
-
-1;
-
-
-
-
-
-
-
-
-
diff --git a/tests/scripts/features/vpath3 b/tests/scripts/features/vpath3
deleted file mode 100644
index 839fb72..0000000
--- a/tests/scripts/features/vpath3
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*-perl-*-
-
-$description = "Test the interaction of the -lfoo feature and vpath";
-$details = "";
-
-my @dirs_to_make = qw(a1 b1 a2 b2 b3);
-for my $d (@dirs_to_make) {
- mkdir($d, 0777);
-}
-
-my @files_to_touch = ("a1${pathsep}lib1.a",
- "a1${pathsep}libc.a",
- "b1${pathsep}lib1.so",
- "a2${pathsep}lib2.a",
- "b2${pathsep}lib2.so",
- "lib3.a",
- "b3${pathsep}lib3.so");
-&touch(@files_to_touch);
-
-my $answer = "a1${pathsep}lib1.a a1${pathsep}libc.a " .
- "a2${pathsep}lib2.a lib3.a\n";
-if ($port_type eq 'VMS-DCL') {
- $answer =~ s/ /,/g;
-}
-
-run_make_test('
-vpath %.h b3
-vpath %.a a1
-vpath %.so b1
-vpath % a2 b2
-vpath % b3
-all: -l1 -lc -l2 -l3; @echo $^
-',
- '', $answer);
-
-unlink(@files_to_touch);
-for my $d (@dirs_to_make) {
- rmdir($d);
-}
-
-1;
diff --git a/tests/scripts/features/vpathgpath b/tests/scripts/features/vpathgpath
index 5e6217b..5c5996c 100644
--- a/tests/scripts/features/vpathgpath
+++ b/tests/scripts/features/vpathgpath
@@ -40,7 +40,7 @@ close(MAKEFILE);
$off = -500;
-sub touchfiles {
+sub gtouchfiles {
foreach (@_) {
($f = $_) =~ s,VP/,$VP,g;
&utouch($off, $f);
@@ -51,7 +51,7 @@ sub touchfiles {
# Run the general-case test
-&touchfiles("VP/foo.d", "VP/bar.d", "VP/foo.c", "VP/bar.c", "foo.b", "bar.d");
+&gtouchfiles("VP/foo.d", "VP/bar.d", "VP/foo.c", "VP/bar.c", "foo.b", "bar.d");
&run_make_with_options($makefile,"general",&get_logfile());
diff --git a/tests/scripts/features/vpathplus b/tests/scripts/features/vpathplus
index 978aecb..da16983 100644
--- a/tests/scripts/features/vpathplus
+++ b/tests/scripts/features/vpathplus
@@ -5,13 +5,23 @@ $details = "";
$VP = "$workdir$pathsep";
-open(MAKEFILE,"> $makefile");
+@touchedfiles = ();
+
+$off = -500;
-# The Contents of the MAKEFILE ...
+sub touchfiles {
+ foreach (@_) {
+ &utouch($off, $_);
+ $off += 10;
+ push(@touchedfiles, $_);
+ }
+}
-print MAKEFILE "VPATH = $VP\n";
+&touchfiles("$VP/foo.d", "$VP/bar.d", "$VP/foo.c", "$VP/bar.c", "foo.b", "bar.d");
-print MAKEFILE <<'EOMAKE';
+# Run the general-case test
+
+run_make_test(qq!VPATH = $VP! . q!
.SUFFIXES: .a .b .c .d
.PHONY: general rename notarget intermediate
@@ -20,12 +30,9 @@ print MAKEFILE <<'EOMAKE';
%.c:
%.d:
-%.a : %.b
- cat $^ > $@
-%.b : %.c
- cat $^ > $@ 2>/dev/null || exit 1
-%.c :: %.d
- cat $^ > $@
+%.a : %.b ; cat $^ > $@
+%.b : %.c ; cat $^ > $@ 2>/dev/null || exit 1
+%.c :: %.d ; cat $^ > $@
# General testing info:
@@ -39,71 +46,32 @@ rename: $(VPATH)/foo.c foo.d
# Target not made testing info:
notarget: notarget.b
-notarget.c: notarget.d
- -@echo "not creating $@ from $^"
+notarget.c: notarget.d ; -@echo "not creating $@ from $^"
# Intermediate files:
intermediate: inter.a
-
-EOMAKE
-
-close(MAKEFILE);
-
-@touchedfiles = ();
-
-$off = -500;
-
-sub touchfiles {
- foreach (@_) {
- &utouch($off, $_);
- $off += 10;
- push(@touchedfiles, $_);
- }
-}
-
-# Run the general-case test
-
-&touchfiles("$VP/foo.d", "$VP/bar.d", "$VP/foo.c", "$VP/bar.c", "foo.b", "bar.d");
-
-&run_make_with_options($makefile,"general",&get_logfile);
+!,
+ 'general', "cat bar.d > bar.c\ncat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1\n");
push(@touchedfiles, "bar.c");
-$answer = "cat bar.d > bar.c
-cat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1
-";
-&compare_output($answer,&get_logfile(1));
-
# Test rules that don't make the target correctly
&touchfiles("$VP/notarget.c", "notarget.b", "notarget.d");
-&run_make_with_options($makefile,"notarget",&get_logfile,512);
-
-$answer = "not creating notarget.c from notarget.d
-cat notarget.c > notarget.b 2>/dev/null || exit 1
-$make_name: *** [$makefile:13: notarget.b] Error 1
-";
-
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, 'notarget', "not creating notarget.c from notarget.d\ncat notarget.c > notarget.b 2>/dev/null || exit 1\n#MAKE#: *** [#MAKEFILE#:11: notarget.b] Error 1\n", 512);
# Test intermediate file handling (part 1)
&touchfiles("$VP/inter.d");
-&run_make_with_options($makefile,"intermediate",&get_logfile);
-
-push(@touchedfiles, "inter.a", "inter.b");
-
my $be = pack("L", 1) eq pack("N", 1);
my $intfiles = $be ? "inter.c inter.b" : "inter.b inter.c";
-$answer = "cat ${VP}inter.d > inter.c
-cat inter.c > inter.b 2>/dev/null || exit 1
-cat inter.b > inter.a
-rm $intfiles
-";
-&compare_output($answer,&get_logfile(1));
+
+run_make_test(undef, 'intermediate', "cat ${VP}inter.d > inter.c\ncat inter.c > inter.b 2>/dev/null || exit 1\ncat inter.b > inter.a\nrm $intfiles\n");
+
+push(@touchedfiles, "inter.a", "inter.b");
# Test intermediate file handling (part 2)
@@ -111,21 +79,10 @@ rm $intfiles
&utouch(-10, "$VP/inter.b");
&touch("$VP/inter.d");
-push(@touchedfiles, "$VP/inter.b", "$VP/inter.d");
-
-&run_make_with_options($makefile,"intermediate",&get_logfile);
+run_make_test(undef, 'intermediate', "cat ${VP}inter.d > inter.c\ncat inter.c > inter.b 2>/dev/null || exit 1\ncat inter.b > inter.a\nrm inter.c\n");
-$answer = "cat ${VP}inter.d > inter.c
-cat inter.c > inter.b 2>/dev/null || exit 1
-cat inter.b > inter.a
-rm inter.c
-";
-&compare_output($answer,&get_logfile(1));
+push(@touchedfiles, "$VP/inter.b", "$VP/inter.d");
unlink @touchedfiles unless $keep;
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End: