summaryrefslogtreecommitdiff
path: root/tests/scripts
diff options
context:
space:
mode:
authorKévin THIERRY <kevin.thierry@open.eurogiciel.org>2014-11-05 08:27:15 +0100
committerKévin THIERRY <kevin.thierry@open.eurogiciel.org>2014-11-05 08:27:15 +0100
commite15597c3e85dedc015ff923a88febd46a1551f71 (patch)
tree467fdb092d1fa76bcb63d4db653e8176dae24e62 /tests/scripts
parent9789b4dba120180760ec948089fc98ebab6eb28b (diff)
downloadmake-e15597c3e85dedc015ff923a88febd46a1551f71.tar.gz
make-e15597c3e85dedc015ff923a88febd46a1551f71.tar.bz2
make-e15597c3e85dedc015ff923a88febd46a1551f71.zip
Imported Upstream version 4.0upstream/4.0sandbox/kevinthierry/upstream
Diffstat (limited to 'tests/scripts')
-rw-r--r--tests/scripts/features/archives95
-rw-r--r--tests/scripts/features/default_names49
-rw-r--r--tests/scripts/features/double_colon9
-rw-r--r--tests/scripts/features/errors19
-rw-r--r--tests/scripts/features/escape30
-rw-r--r--tests/scripts/features/include12
-rw-r--r--tests/scripts/features/jobserver61
-rw-r--r--tests/scripts/features/load102
-rw-r--r--tests/scripts/features/loadapi112
-rw-r--r--tests/scripts/features/mult_rules2
-rw-r--r--tests/scripts/features/output-sync334
-rw-r--r--tests/scripts/features/parallelism104
-rw-r--r--tests/scripts/features/patspecific_vars10
-rw-r--r--tests/scripts/features/patternrules5
-rw-r--r--tests/scripts/features/recursion16
-rw-r--r--tests/scripts/features/reinvoke17
-rw-r--r--tests/scripts/features/rule_glob37
-rw-r--r--tests/scripts/features/se_explicit17
-rw-r--r--tests/scripts/features/se_implicit34
-rw-r--r--tests/scripts/features/shell_assignment65
-rw-r--r--tests/scripts/features/targetvars12
-rw-r--r--tests/scripts/features/utf811
-rw-r--r--tests/scripts/features/varnesting47
-rw-r--r--tests/scripts/features/vpath2
-rw-r--r--tests/scripts/features/vpath365
-rw-r--r--tests/scripts/features/vpathgpath2
-rw-r--r--tests/scripts/features/vpathplus1
-rw-r--r--tests/scripts/functions/call15
-rw-r--r--tests/scripts/functions/file101
-rw-r--r--tests/scripts/functions/filter-out32
-rw-r--r--tests/scripts/functions/foreach6
-rw-r--r--tests/scripts/functions/guile99
-rw-r--r--tests/scripts/functions/sort98
-rw-r--r--tests/scripts/functions/wildcard12
-rw-r--r--tests/scripts/functions/word26
-rw-r--r--tests/scripts/misc/bs-nl129
-rw-r--r--tests/scripts/misc/fopen-fail15
-rw-r--r--tests/scripts/misc/general32
-rw-r--r--tests/scripts/options/dash-B4
-rw-r--r--tests/scripts/options/dash-C8
-rw-r--r--tests/scripts/options/dash-I4
-rw-r--r--tests/scripts/options/dash-W4
-rw-r--r--tests/scripts/options/dash-k11
-rw-r--r--tests/scripts/options/dash-n80
-rw-r--r--tests/scripts/options/eval10
-rw-r--r--tests/scripts/options/print-directory33
-rw-r--r--tests/scripts/options/symlinks10
-rw-r--r--tests/scripts/options/warn-undefined-variables4
-rw-r--r--tests/scripts/targets/DEFAULT4
-rw-r--r--tests/scripts/targets/INTERMEDIATE4
-rw-r--r--tests/scripts/targets/ONESHELL19
-rw-r--r--tests/scripts/targets/POSIX28
-rw-r--r--tests/scripts/targets/SECONDARY11
-rw-r--r--tests/scripts/variables/DEFAULT_GOAL2
-rw-r--r--tests/scripts/variables/GNUMAKEFLAGS42
-rw-r--r--tests/scripts/variables/LIBPATTERNS2
-rw-r--r--tests/scripts/variables/MAKE4
-rw-r--r--tests/scripts/variables/MAKEFLAGS26
-rw-r--r--tests/scripts/variables/MAKE_RESTARTS4
-rw-r--r--tests/scripts/variables/SHELL19
-rw-r--r--tests/scripts/variables/define56
-rw-r--r--tests/scripts/variables/flavors20
-rw-r--r--tests/scripts/variables/private44
-rw-r--r--tests/scripts/variables/special2
64 files changed, 1894 insertions, 366 deletions
diff --git a/tests/scripts/features/archives b/tests/scripts/features/archives
new file mode 100644
index 0000000..a7ec881
--- /dev/null
+++ b/tests/scripts/features/archives
@@ -0,0 +1,95 @@
+# -*-mode: perl-*-
+
+$description = "Test GNU make's archive management features.";
+
+$details = "\
+This only works on systems that support it.";
+
+# If this instance of make doesn't support archives, skip it
+exists $FEATURES{archives} or return -1;
+
+# Create some .o files to work with
+utouch(-60, qw(a1.o a2.o a3.o));
+
+# Some versions of ar print different things on creation. Find out.
+my $created = `ar rv libxx.a a1.o 2>&1`;
+
+# Some versions of ar print different things on add. Find out.
+my $add = `ar rv libxx.a a2.o 2>&1`;
+$add =~ s/a2\.o/#OBJECT#/g;
+
+# Some versions of ar print different things on replacement. Find out.
+my $repl = `ar rv libxx.a a2.o 2>&1`;
+$repl =~ s/a2\.o/#OBJECT#/g;
+
+unlink('libxx.a');
+
+# Very simple
+run_make_test('all: libxx.a(a1.o)',
+ '', "ar rv libxx.a a1.o\n$created");
+
+# Multiple .o's. Add a new one to the existing library
+($_ = $add) =~ s/#OBJECT#/a2.o/g;
+run_make_test('all: libxx.a(a1.o a2.o)',
+ '', "ar rv libxx.a a2.o\n$_");
+
+# Touch one of the .o's so it's rebuilt
+utouch(-40, 'a1.o');
+($_ = $repl) =~ s/#OBJECT#/a1.o/g;
+run_make_test(undef, '', "ar rv libxx.a a1.o\n$_");
+
+# Use wildcards
+run_make_test('all: libxx.a(*.o)',
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# Touch one of the .o's so it's rebuilt
+utouch(-30, 'a1.o');
+($_ = $repl) =~ s/#OBJECT#/a1.o/g;
+run_make_test(undef, '', "ar rv libxx.a a1.o\n$_");
+
+# Use both wildcards and simple names
+utouch(-50, 'a2.o');
+($_ = $add) =~ s/#OBJECT#/a3.o/g;
+$_ .= "ar rv libxx.a a2.o\n";
+($_ .= $repl) =~ s/#OBJECT#/a2.o/g;
+run_make_test('all: libxx.a(a3.o *.o)', '',
+ "ar rv libxx.a a3.o\n$_");
+
+# Check whitespace handling
+utouch(-40, 'a2.o');
+($_ = $repl) =~ s/#OBJECT#/a2.o/g;
+run_make_test('all: libxx.a( a3.o *.o )', '',
+ "ar rv libxx.a a2.o\n$_");
+
+rmfiles(qw(a1.o a2.o a3.o libxx.a));
+
+# Check non-archive targets
+# See Savannah bug #37878
+run_make_test(q!
+all: foo(bar).baz
+foo(bar).baz: ; @echo '$@'
+!,
+ '', "foo(bar).baz\n");
+
+# Check renaming of archive targets.
+# See Savannah bug #38442
+
+mkdir('artest', 0777);
+touch('foo.vhd');
+
+run_make_test(q!
+DIR = artest
+vpath % $(DIR)
+default: lib(foo)
+(%): %.vhd ; @cd $(DIR) && touch $(*F) && $(AR) $(ARFLAGS) $@ $(*F) >/dev/null 2>&1 && rm $(*F)
+.PHONY: default
+!,
+ '', "");
+
+run_make_test(undef, '', "#MAKE#: Nothing to be done for 'default'.\n");
+
+unlink('foo.vhd');
+remove_directory_tree('artest');
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/default_names b/tests/scripts/features/default_names
index e53127e..2e83880 100644
--- a/tests/scripts/features/default_names
+++ b/tests/scripts/features/default_names
@@ -10,32 +10,35 @@ open(MAKEFILE,"> $makefile");
print MAKEFILE "FIRST: ; \@echo It chose GNUmakefile\n";
close(MAKEFILE);
-# DOS/WIN32 platforms preserve case, but Makefile is the same file as makefile.
-# Just test what we can here (avoid Makefile versus makefile test).
-
-if ($port_type eq 'UNIX') {
- # Create another makefile called "makefile"
- open(MAKEFILE,"> makefile");
- print MAKEFILE "SECOND: ; \@echo It chose makefile\n";
- close(MAKEFILE);
-}
-
-# Create another makefile called "Makefile"
-open(MAKEFILE,"> Makefile");
-print MAKEFILE "THIRD: ; \@echo It chose Makefile\n";
+# Create another makefile called "makefile"
+open(MAKEFILE,"> makefile");
+print MAKEFILE "SECOND: ; \@echo It chose makefile\n";
close(MAKEFILE);
+# DOS/WIN32/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;
+if (! -f 'Makefile') {
+ # Create another makefile called "Makefile"
+ $case_sensitive = 1;
+ open(MAKEFILE,"> Makefile");
+ print MAKEFILE "THIRD: ; \@echo It chose Makefile\n";
+ close(MAKEFILE);
+}
+
+run_make_with_options("","",&get_logfile);
+compare_output("It chose GNUmakefile\n",&get_logfile(1));
+unlink($makefile);
-&run_make_with_options("","",&get_logfile);
-&compare_output("It chose GNUmakefile\n",&get_logfile(1));
-unlink $makefile;
+run_make_with_options("","",&get_logfile);
+compare_output("It chose makefile\n",&get_logfile(1));
+unlink("makefile");
-if ($port_type eq 'UNIX') {
- &run_make_with_options("","",&get_logfile);
- &compare_output("It chose makefile\n",&get_logfile(1));
- unlink "makefile";
+if ($case_sensitive) {
+ run_make_with_options("","",&get_logfile);
+ compare_output("It chose Makefile\n",&get_logfile(1));
+ unlink("Makefile");
}
-&run_make_with_options("","",&get_logfile);
-&compare_output("It chose Makefile\n",&get_logfile(1));
-unlink "Makefile";
+1;
diff --git a/tests/scripts/features/double_colon b/tests/scripts/features/double_colon
index cad605d..1097775 100644
--- a/tests/scripts/features/double_colon
+++ b/tests/scripts/features/double_colon
@@ -151,5 +151,14 @@ two');
unlink('result','one','two');
+# TEST 10: check for proper backslash handling
+# Savannah bug #33399
+
+run_make_test('
+a\ xb :: ; @echo one
+a\ xb :: ; @echo two
+',
+ '', "one\ntwo\n");
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/errors b/tests/scripts/features/errors
index e372fe0..c0339cb 100644
--- a/tests/scripts/features/errors
+++ b/tests/scripts/features/errors
@@ -42,15 +42,17 @@ close(MAKEFILE);
unlink("cleanit");
$cleanit_error = `sh -c "$rm_command cleanit 2>&1"`;
+chomp $cleanit_error;
$delete_error_code = $? >> 8;
# TEST #1
# -------
-$answer = "$rm_command cleanit\n"
- . $cleanit_error
- ."$make_name: [clean] Error $delete_error_code (ignored)\n"
- ."$rm_command foo\n";
+$answer = "$rm_command cleanit
+$cleanit_error
+$makefile:2: recipe for target 'clean' failed
+$make_name: [clean] Error $delete_error_code (ignored)
+$rm_command foo\n";
&run_make_with_options($makefile,"",&get_logfile);
@@ -74,10 +76,11 @@ if (!$vos)
# TEST #2
# -------
-$answer = "$rm_command cleanit\n"
- . $cleanit_error
- ."$make_name: [clean2] Error $delete_error_code (ignored)\n"
- ."$rm_command foo\n";
+$answer = "$rm_command cleanit
+$cleanit_error
+$makefile:5: recipe for target 'clean2' failed
+$make_name: [clean2] Error $delete_error_code (ignored)
+$rm_command foo\n";
&run_make_with_options($makefile,"clean2 -i",&get_logfile);
diff --git a/tests/scripts/features/escape b/tests/scripts/features/escape
index 97a2994..bf069df 100644
--- a/tests/scripts/features/escape
+++ b/tests/scripts/features/escape
@@ -2,12 +2,10 @@
$description = "Test various types of escaping in makefiles.";
$details = "\
-Make sure that escaping of `:' works in target names.
+Make sure that escaping of ':' works in target names.
Make sure escaping of whitespace works in target names.
-Make sure that escaping of '#' works.";
-
-
-close(MAKEFILE);
+Make sure that escaping of '#' works.
+Make sure that backslash before non-special characters are kept.";
# TEST 1
@@ -26,7 +24,7 @@ foo\#bar.ext: ; @echo "foo#bar.ext = ($@)"',
run_make_test(undef,
'path=pre:',
- "#MAKEFILE#:2: *** target pattern contains no `%'. Stop.",
+ "#MAKEFILE#:2: *** target pattern contains no '%'. Stop.",
512);
# TEST 3: This one should work, since we escape the ":".
@@ -39,7 +37,7 @@ run_make_test(undef,
run_make_test(undef,
"'path=pre\\\\:'",
- "#MAKEFILE#:2: *** target pattern contains no `%'. Stop.",
+ "#MAKEFILE#:2: *** target pattern contains no '%'. Stop.",
512);
# TEST 5: This one should work
@@ -54,5 +52,23 @@ run_make_test(undef,
'sharp',
'foo#bar.ext = (foo#bar.ext)');
+# Test escaped colons in prerequisites
+# Quoting of backslashes in q!! is kind of messy.
+# Solaris sh does not properly handle backslashes even in '' so just
+# check the output make prints, not what the shell interprets.
+run_make_test(q!
+foo: foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar
+foo foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar: ; : '$@'
+!,
+ '', ": 'foo:bar'\n: 'foo\\:bar'\n: 'foo\\\\:bar'\n: 'foo'\n");
+
+# Test backslash before non-special chars: should be kept as-is
+
+run_make_test(q!
+all: ..\foo
+.DEFAULT: ; : '$@'
+!,
+ '', ": '..\\foo'\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 ba8908c..ee014bd 100644
--- a/tests/scripts/features/include
+++ b/tests/scripts/features/include
@@ -1,6 +1,6 @@
# -*-mode: perl; rm-trailing-spaces: nil-*-
-$description = "Test various forms of the GNU make `include' command.";
+$description = "Test various forms of the GNU make 'include' command.";
$details = "\
Test include, -include, sinclude and various regressions involving them.
@@ -60,7 +60,7 @@ run_make_test
error: foo.mk ; @echo $@
',
'',
- "#MAKE#: *** No rule to make target `foo.mk', needed by `error'. Stop.\n",
+ "#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'. Stop.\n",
512
);
@@ -128,7 +128,7 @@ foo: baz
bar: baz
',
'',
-"#MAKE#: *** No rule to make target `baz', needed by `bar'. Stop.\n",
+"#MAKE#: *** No rule to make target 'baz', needed by 'bar'. Stop.\n",
512);
# Test that the diagnostics is issued even if the target has been
@@ -144,7 +144,7 @@ bar: baz
baz: end
',
'',
-"#MAKE#: *** No rule to make target `end', needed by `baz'. Stop.\n",
+"#MAKE#: *** No rule to make target 'end', needed by 'baz'. Stop.\n",
512);
# Test that the diagnostics is issued even if the target has been
@@ -162,7 +162,7 @@ baz: end
',
'',
"#MAKEFILE#:2: bar: No such file or directory
-#MAKE#: *** No rule to make target `end', needed by `baz'. Stop.\n",
+#MAKE#: *** No rule to make target 'end', needed by 'baz'. Stop.\n",
512);
if ($all_tests) {
@@ -172,7 +172,7 @@ if ($all_tests) {
include foo
foo: ; @echo foo = bar > $@
!,
- '', "#MAKE#: `foo' is up to date.\n");
+ '', "#MAKE#: 'foo' is up to date.\n");
rmfiles('foo');
}
diff --git a/tests/scripts/features/jobserver b/tests/scripts/features/jobserver
new file mode 100644
index 0000000..cedd4b3
--- /dev/null
+++ b/tests/scripts/features/jobserver
@@ -0,0 +1,61 @@
+# -*-perl-*-
+
+$description = "Test jobserver.";
+
+$details = "These tests are ones that specifically are different when the
+jobserver feature is available. Most -j tests are the same whether or not
+jobserver is available, and those appear in the 'parallelism' test suite.";
+
+exists $FEATURES{'jobserver'} or return -1;
+
+if (!$parallel_jobs) {
+ return -1;
+}
+
+# Don't put --jobserver-fds into a re-exec'd MAKEFLAGS.
+# We can't test this directly because there's no way a makefile can
+# show the value of MAKEFLAGS we were re-exec'd with. We can intuit it
+# by looking for "disabling jobserver mode" warnings; we should only
+# get one from the original invocation and none from the re-exec.
+# See Savannah bug #18124
+
+unlink('inc.mk');
+
+run_make_test(q!
+-include inc.mk
+recur:
+# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+ @rm -f inc.mk
+ @$(MAKE) -j2 -f #MAKEFILE# all
+all:
+# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+ @echo $@
+inc.mk:
+# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+ @echo 'FOO = bar' > $@
+!,
+ '--no-print-directory -j2', "#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nall\n");
+
+unlink('inc.mk');
+
+# Test recursion when make doesn't think it exists.
+# See Savannah bug #39934
+# Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474
+
+open(MAKEFILE,"> Makefile2");
+print MAKEFILE '
+vpath %.c ../
+foo:
+';
+close(MAKEFILE);
+
+run_make_test(q!
+default: ; @ #MAKEPATH# -f Makefile2
+!,
+ '-j2 --no-print-directory',
+"#MAKE#[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.
+#MAKE#[1]: Nothing to be done for 'foo'.");
+
+rmfiles('Makefile2');
+
+1;
diff --git a/tests/scripts/features/load b/tests/scripts/features/load
new file mode 100644
index 0000000..2e3f263
--- /dev/null
+++ b/tests/scripts/features/load
@@ -0,0 +1,102 @@
+# -*-perl-*-
+$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;
+
+my $sobuild = '$(CC) '.($srcdir? "-I$srcdir":'').' -g -shared -fPIC -o $@ $<';
+
+# First build a shared object
+# Provide both a default and non-default load symbol
+
+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"
+
+int plugin_is_GPL_compatible;
+
+int
+testload_gmk_setup (gmk_floc *pos)
+{
+ gmk_eval ("TESTLOAD = implicit", 0);
+ return 1;
+}
+
+int
+explicit_setup (gmk_floc *pos)
+{
+ gmk_eval ("TESTLOAD = explicit", 0);
+ return 1;
+}
+EOF
+close($F) or die "close: testload.c: $!\n";
+
+# Make sure we can compile
+run_make_test('testload.so: testload.c ; @'.$sobuild, '', '');
+
+# TEST 1
+run_make_test(q!
+PRE := $(.LOADED)
+load testload.so
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+!,
+ '', "pre= post=testload.so implicit\n");
+
+# TEST 2
+# Load using an explicit function
+run_make_test(q!
+PRE := $(.LOADED)
+load ./testload.so(explicit_setup)
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+!,
+ '', "pre= post=testload.so explicit\n");
+
+# TEST 4
+# Check multiple loads
+run_make_test(q!
+PRE := $(.LOADED)
+load ./testload.so
+load testload.so(explicit_setup)
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+!,
+ '', "pre= post=testload.so implicit\n");
+
+# TEST 5
+# Check auto-rebuild of loaded file that's out of date
+utouch(-10, 'testload.so');
+touch('testload.c');
+
+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,
+ '', "rebuilding testload.so\npre= post=testload.so implicit\n");
+
+# TEST 5
+# Check auto-rebuild of loaded file when it doesn't exist
+unlink('testload.so');
+
+run_make_test(q!
+PRE := $(.LOADED)
+-load ./testload.so(explicit_setup)
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+%.so: %.c ; @echo "rebuilding $@"; !.$sobuild,
+ '', "rebuilding testload.so\npre= post=testload.so explicit\n");
+
+unlink(qw(testload.c testload.so)) unless $keep;
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/loadapi b/tests/scripts/features/loadapi
new file mode 100644
index 0000000..6d3b03f
--- /dev/null
+++ b/tests/scripts/features/loadapi
@@ -0,0 +1,112 @@
+# -*-perl-*-
+$description = "Test the shared object load API.";
+
+$details = "Verify the different aspects of the shared object API.";
+
+# Don't do anything if this system doesn't support "load"
+exists $FEATURES{load} or return -1;
+
+my $sobuild = '$(CC) '.($srcdir? "-I$srcdir":'').' -g -shared -fPIC -o $@ $<';
+
+# First build a shared object
+# Provide both a default and non-default load symbol
+
+unlink(qw(testapi.c testapi.so));
+
+open(my $F, '> testapi.c') or die "open: testapi.c: $!\n";
+print $F <<'EOF' ;
+#include <string.h>
+#include <stdio.h>
+
+#include "gnumake.h"
+
+int plugin_is_GPL_compatible;
+
+static char *
+test_eval (const char *buf)
+{
+ gmk_eval (buf, 0);
+ return NULL;
+}
+
+static char *
+test_expand (const char *val)
+{
+ return gmk_expand (val);
+}
+
+static char *
+test_noexpand (const char *val)
+{
+ char *str = gmk_alloc (strlen (val));
+ strcpy (str, val);
+ return str;
+}
+
+static char *
+func_test (const char *funcname, unsigned int argc, char **argv)
+{
+ char *mem;
+
+ if (strcmp (funcname, "test-expand") == 0)
+ return test_expand (argv[0]);
+
+ if (strcmp (funcname, "test-eval") == 0)
+ return test_eval (argv[0]);
+
+ if (strcmp (funcname, "test-noexpand") == 0)
+ return test_noexpand (argv[0]);
+
+ mem = gmk_alloc (sizeof ("unknown"));
+ strcpy (mem, "unknown");
+ return mem;
+}
+
+int
+testapi_gmk_setup ()
+{
+ 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);
+ return 1;
+}
+EOF
+close($F) or die "close: testapi.c: $!\n";
+
+run_make_test('testapi.so: testapi.c ; @'.$sobuild, '', '');
+
+# TEST 1
+# Check the gmk_expand() function
+run_make_test(q!
+EXPAND = expansion
+all: ; @echo $(test-expand $$(EXPAND))
+load testapi.so
+!,
+ '', "expansion\n");
+
+# TEST 2
+# Check the eval operation. Prove that the argument is expanded only once
+run_make_test(q!
+load testapi.so
+TEST = bye
+ASSIGN = VAR = $(TEST) $(shell echo there)
+$(test-eval $(value ASSIGN))
+TEST = hi
+all:;@echo '$(VAR)'
+!,
+ '', "hi there\n");
+
+# TEST 2
+# Check the no-expand capability
+run_make_test(q!
+load testapi.so
+TEST = hi
+all:;@echo '$(test-noexpand $(TEST))'
+!,
+ '', "\$(TEST)\n");
+
+unlink(qw(testapi.c testapi.so)) unless $keep;
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/mult_rules b/tests/scripts/features/mult_rules
index 6f120f1..e706e17 100644
--- a/tests/scripts/features/mult_rules
+++ b/tests/scripts/features/mult_rules
@@ -47,7 +47,7 @@ else
$error_code);
# Create the answer to what should be produced by this Makefile
-$answer = "$make_name: *** No rule to make target `extra.h', needed by `foo.o'. Stop.\n";
+$answer = "$make_name: *** No rule to make target 'extra.h', needed by 'foo.o'. Stop.\n";
&compare_output($answer,&get_logfile(1));
diff --git a/tests/scripts/features/output-sync b/tests/scripts/features/output-sync
new file mode 100644
index 0000000..75d7e81
--- /dev/null
+++ b/tests/scripts/features/output-sync
@@ -0,0 +1,334 @@
+# -*-perl-*-
+
+$description = "Test --output-sync (-O) option.";
+
+$details = "Test the synchronization of output from parallel jobs.";
+
+# If we don't have output sync support, never mind.
+exists $FEATURES{'output-sync'} or return -1;
+
+# Output sync can't be tested without parallelization
+$parallel_jobs or return -1;
+
+
+if ($vos) {
+ $sleep_command = "sleep -seconds";
+}
+else {
+ $sleep_command = "sleep";
+}
+
+# The following subdirectories with Makefiles are used in several
+# of the following tests. The model is:
+# foo/Makefile - has a "foo" target that waits for the bar target
+# bar/Makefile - has a "bar" target that runs immediately
+# - has a "baz" target that waits for the foo target
+#
+# So, you start the two sub-makes in parallel and first the "bar" target is
+# built, followed by "foo", followed by "baz". The trick is that first each
+# target prints a "start" statement, then waits (if appropriate), then prints
+# an end statement. Thus we can tell if the -O flag is working, since
+# otherwise these statements would be mixed together.
+
+@syncfiles = ();
+
+sub output_sync_clean {
+ rmfiles('foo/Makefile', 'bar/Makefile', @syncfiles);
+ rmdir('foo');
+ rmdir('bar');
+}
+
+# We synchronize the different jobs by having them wait for a sentinel file to
+# be created, instead of relying on a certain amount of time passing.
+# Unfortunately in this test we have to sleep after we see the sync file,
+# since we also want to make the obtaining of the write synchronization lock
+# reliable. If things are too fast, then sometimes a different job will steal
+# the output sync lock and the output is mis-ordered from what we expect.
+sub output_sync_wait {
+ return "while [ ! -f ../mksync.$_[0] ]; do :; done; rm -f ../mksync.$_[0].wait; $sleep_command 1";
+}
+sub output_sync_set {
+ return "date > ../mksync.$_[0]";
+}
+
+@syncfiles = qw(mksync.foo mksync.foo_start mksync.bar mksync.bar_start);
+
+output_sync_clean();
+mkdir('foo', 0777);
+mkdir('bar', 0777);
+
+$set_foo = output_sync_set('foo');
+$set_bar = output_sync_set('bar');
+$set_foo_start = output_sync_set('foo_start');
+$set_bar_start = output_sync_set('bar_start');
+
+$wait_foo = output_sync_wait('foo');
+$wait_bar = output_sync_wait('bar');
+$wait_foo_start = output_sync_set('foo_start');
+$wait_bar_start = output_sync_set('bar_start');
+
+open(MAKEFILE,"> foo/Makefile");
+print MAKEFILE <<EOF;
+all: foo
+
+foo: foo-base ; \@$set_foo
+
+foo-base:
+\t\@echo foo: start
+\t\@$wait_bar
+\t\@echo foo: end
+
+foo-job: foo-job-base ; \@$set_foo
+
+foo-job-base:
+\t\@$wait_bar_start
+\t\@echo foo: start
+\t\@$set_foo_start
+\t\@$wait_bar
+\t\@echo foo: end
+
+foo-fail:
+\t\@echo foo-fail: start
+\t\@$wait_bar
+\t\@echo foo-fail: end
+\t\@exit 1
+EOF
+close(MAKEFILE);
+
+open(MAKEFILE,"> bar/Makefile");
+print MAKEFILE <<EOF;
+all: bar baz
+
+bar: bar-base ; \@$set_bar
+bar-base:
+\t\@echo bar: start
+\t\@echo bar: end
+
+bar-job: bar-job-base ; \@$set_bar
+
+bar-job-base:
+\t\@echo bar: start
+\t\@$set_bar_start
+\t\@$wait_foo_start
+\t\@echo bar: end
+
+baz: baz-base
+baz-base:
+\t\@echo baz: start
+\t\@$wait_foo
+\t\@echo baz: end
+EOF
+close(MAKEFILE);
+
+# Test per-make synchronization.
+unlink(@syncfiles);
+run_make_test(qq!
+all: make-foo make-bar
+
+make-foo: ; \$(MAKE) -C foo
+
+make-bar: ; \$(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
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: start
+bar: end
+baz: start
+baz: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'\n", 0, 6);
+
+# Test per-target 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!
+x=1
+\$xMAKEFLAGS += --no-print-directory
+
+all: make-foo make-bar
+
+make-foo: ; \$(MAKE) -C foo
+
+make-bar: ; $sleep_command 1 ; \$(MAKE) -C bar!,
+ '-j --output-sync=target',
+"#MAKEPATH# -C foo
+$sleep_command 1 ; #MAKEPATH# -C bar
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: start
+bar: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo: start
+foo: end
+#MAKE#[1]: Leaving directory '#PWD#/foo'
+#MAKE#[1]: Entering directory '#PWD#/bar'
+baz: start
+baz: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'\n", 0, 6);
+
+# Rerun but this time suppress the directory tracking
+unlink(@syncfiles);
+run_make_test(undef, '-j --output-sync=target x=',
+ "#MAKEPATH# -C foo
+$sleep_command 1 ; #MAKEPATH# -C bar
+bar: start
+bar: end
+foo: start
+foo: end
+baz: start
+baz: end\n", 0, 6);
+
+# Test that messages from make itself are enclosed with
+# "Entering/Leaving directory" messages.
+unlink(@syncfiles);
+run_make_test(qq!
+all: make-foo-fail make-bar-bar
+
+make-foo-fail: ; \$(MAKE) -C foo foo-fail
+
+make-bar-bar: ; $sleep_command 1 ; \$(MAKE) -C bar bar!,
+ '-j -O',
+"#MAKEPATH# -C foo foo-fail
+$sleep_command 1 ; #MAKEPATH# -C bar bar
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: start
+bar: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo-fail: start
+foo-fail: end
+Makefile:20: recipe for target 'foo-fail' failed
+#MAKE#[1]: *** [foo-fail] Error 1
+#MAKE#[1]: Leaving directory '#PWD#/foo'
+#MAKEFILE#:4: recipe for target 'make-foo-fail' failed
+#MAKE#: *** [make-foo-fail] Error 2\n",
+512);
+
+# Test the per-job synchronization.
+# For this we'll have bar-job:
+# print start, invoke bar-start, wait for foo-start, print end, print-bar-end
+# And foo-job:
+# wait for bar-start, print foo-start, wait for bar-end, print end
+
+unlink(@syncfiles);
+run_make_test(qq!
+all: make-foo make-bar
+
+make-foo: ; \$(MAKE) -C foo foo-job
+
+make-bar: ; $sleep_command 1 ; \$(MAKE) -C bar bar-job!,
+ '-j --output-sync=line',
+"#MAKEPATH# -C foo foo-job
+$sleep_command 1 ; #MAKEPATH# -C bar bar-job
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo: start
+#MAKE#[1]: Leaving directory '#PWD#/foo'
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: start
+#MAKE#[1]: Leaving directory '#PWD#/bar'
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo: end
+#MAKE#[1]: Leaving directory '#PWD#/foo'\n", 0, 6);
+
+
+# Remove temporary directories and contents.
+output_sync_clean();
+
+# Ensure recursion doesn't mis-order or double-print output
+run_make_test(qq!
+all:
+\t\@echo foo
+\t\@+echo bar
+!,
+ '-j -Oline', "foo\nbar\n");
+
+run_make_test(undef, '-j -Otarget', "foo\nbar\n");
+
+# Ensure when make writes out command it's not misordered
+run_make_test(qq!
+all:
+\t\@echo foobar
+\ttrue
+!,
+ '-j -Oline', "foobar\ntrue\n");
+
+run_make_test(undef, '-j -Otarget', "foobar\ntrue\n");
+
+# Ensure that shell functions inside recipes write stderr to the sync file
+run_make_test(q!
+all: ; @: $(shell echo foo 1>&2)
+!,
+ '-w -Oline', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n");
+
+# Ensure that output generated while parsing makefiles is synced
+# when appropriate.
+run_make_test(q!
+$(shell echo foo 1>&2)
+all: ; echo bar
+!,
+ '-s -w -Otarget', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n#MAKE#: Entering directory '#PWD#'\nbar\n#MAKE#: Leaving directory '#PWD#'\n");
+
+# Test recursion
+$m1 = get_tmpfile();
+$m2 = get_tmpfile();
+
+open(M1, "> $m1");
+print M1 <<'EOF';
+$(shell echo d1 stderr 1>&2)
+$(info d1 stdout)
+all:; @:
+EOF
+close(M1);
+
+open(M2, "> $m2");
+print M2 <<'EOF';
+$(shell echo d2 stderr 1>&2)
+$(info d2 stdout)
+all:; @:
+# Force an ordering on the output
+$(shell sleep 1)
+EOF
+close(M2);
+
+run_make_test(qq!
+all: t1 t2
+t1: ; \@\$(MAKE) -f $m1
+t2: ; \@\$(MAKE) -f $m2
+!,
+ "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#[1]: Entering directory '#PWD#'\nd2 stderr\nd2 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n");
+
+rmfiles($m1, $m2);
+
+# Ensure that output generated while parsing makefiles is synced
+# when appropriate.
+$m1 = get_tmpfile();
+
+open(M1, "> $m1");
+print M1 <<'EOF';
+$(shell echo d1 stderr 1>&2)
+$(info d1 stdout)
+$(error d1 failed)
+all:; @:
+EOF
+close(M1);
+
+run_make_test(qq!
+all: t1
+t1: ; -\@\$(MAKE) -f $m1
+!,
+ "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n$m1:3: *** d1 failed. Stop.\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKEFILE#:3: recipe for target 't1' failed\n#MAKE#: [t1] Error 2 (ignored)\n");
+
+rmfiles($m1);
+
+# 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 cc0f84f..c702c26 100644
--- a/tests/scripts/features/parallelism
+++ b/tests/scripts/features/parallelism
@@ -41,7 +41,7 @@ all: 1 2; \@echo success
1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@
2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@",
"-j4",
- "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n");
+ "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n", 0, 7);
rmfiles(qw(1.inc 2.inc));
@@ -60,7 +60,7 @@ endif
1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@
2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@",
"-j4",
- "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n");
+ "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n", 0, 7);
rmfiles(qw(1.inc 2.inc));
@@ -91,21 +91,24 @@ run_make_test("
all: fail.1 ok fail.2 fail.3
fail.1 fail.2 fail.3:
- \@sleep \$(patsubst fail.%,%,\$\@)
+ \@$sleep_command \$(patsubst fail.%,%,\$\@)
\@echo Fail
\@exit 1
ok:
- \@sleep 4
+ \@$sleep_command 4
\@echo Ok done",
- '-rR -j5', 'Fail
+ '-rR -j5', "Fail
+#MAKEFILE#:6: recipe for target 'fail.1' failed
#MAKE#: *** [fail.1] Error 1
#MAKE#: *** Waiting for unfinished jobs....
Fail
+#MAKEFILE#:6: recipe for target 'fail.2' failed
#MAKE#: *** [fail.2] Error 1
Fail
+#MAKEFILE#:6: recipe for target 'fail.3' failed
#MAKE#: *** [fail.3] Error 1
-Ok done',
+Ok done",
512);
@@ -140,81 +143,40 @@ intermed: | phony ; touch $@
phony: ; : phony', '-rR -j', ': phony');
rmfiles('target');
-# TEST #10: Don't put --jobserver-fds into a re-exec'd MAKEFLAGS.
-# We can't test this directly because there's no way a makefile can
-# show the value of MAKEFLAGS we were re-exec'd with. We can intuit it
-# by looking for "disabling jobserver mode" warnings; we should only
-# get one from the original invocation and none from the re-exec.
-# See Savannah bug #18124
+# TEST #11: Make sure -jN from MAKEFLAGS is processed even when we re-exec
+# See Savannah bug #33873
+
+$extraENV{MAKEFLAGS} = '-j4';
run_make_test(q!
+things = thing1 thing2
+all: $(things)
+thing1:; @sleep 1; echo '$@ start'; sleep 2; echo '$@ end'
+thing2:; @echo '$@ start'; sleep 2; echo '$@ end'
-include inc.mk
-recur:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @rm -f inc.mk
- @$(MAKE) -j2 -f #MAKEFILE# all
-all:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @echo $@
-inc.mk:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @echo 'FOO = bar' > $@
+inc.mk: ; @touch $@
!,
- '--no-print-directory -j2', "#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nall\n");
+ '', "thing2 start\nthing1 start\nthing2 end\nthing1 end\n");
+delete $extraENV{MAKEFLAGS};
rmfiles('inc.mk');
-if ($all_tests) {
- # Implicit files aren't properly recreated during parallel builds
- # Savannah bug #26864
+# Ensure intermediate/secondary files are not pruned incorrectly.
+# See Savannah bug #30653
- # The first run works fine
- run_make_test(q!
-%.bar: %.x foo.y ; cat $^ > $@
-%.x: ; touch $@
-foo.y: foo.y.in ; cp $< $@
-foo.y.in: ; touch $@
-!,
- '-j2 main.bar',
- "touch foo.y.in
-touch main.x
-cp foo.y.in foo.y
-cat main.x foo.y > main.bar
-rm main.x");
-
- # Now we touch the .in file and make sure it still works
- touch('foo.y.in');
-
- run_make_test(undef, '-j2 main.bar', "cp foo.y.in foo.y
-touch main.x
-cat main.x foo.y > main.bar
-rm main.x");
-
- # Clean up
- rmfiles(qw(foo.y foo.y.in main.bar));
-}
+utouch(-15, 'file2');
+utouch(-10, 'file4');
+utouch(-5, 'file1');
-if ($all_tests) {
- # Jobserver FD handling is messed up in some way.
- # Savannah bug #28189
- # It doesn't look like that bug anymore but this is the code it runs
-
- run_make_test(q!
-ifdef EXTRA
-vpath %.dst /
-xxx.dst: ; true
-yyy.dst: ; true
-endif
-
-M := $(MAKE)
-xx: ; $M --no-print-directory -j2 -f $(MAKEFILE_LIST) xxx.dst yyy.dst EXTRA=1
+run_make_test(q!
+.INTERMEDIATE: file3
+file4: file3 ; @mv -f $< $@
+file3: file2 ; touch $@
+file2: file1 ; @touch $@
!,
- '-j2',
- '#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.
-true
-true
-');
-}
+ '--no-print-directory -j2', "touch file3");
+
+rmfiles('file1', 'file2', 'file3', 'file4');
# Make sure that all jobserver FDs are closed if we need to re-exec the
# master copy.
diff --git a/tests/scripts/features/patspecific_vars b/tests/scripts/features/patspecific_vars
index 8ca228d..a530bba 100644
--- a/tests/scripts/features/patspecific_vars
+++ b/tests/scripts/features/patspecific_vars
@@ -81,7 +81,7 @@ all: bar baz
b%: pattern := good $$t
-global := orginal $$t
+global := original $$t
# normal target
@@ -103,14 +103,14 @@ else
%z: a := global: $(global) pattern: $(pattern) inherit: $(inherit)
endif
-%z: ; @echo \'pattrn: $a;\'
+%z: ; @echo \'pattern: $a;\'
global := new $$t
',
'',
-'normal: global: orginal $t pattern: inherit: ;
-pattrn: global: orginal $t pattern: inherit: ;');
+'normal: global: original $t pattern: inherit: ;
+pattern: global: original $t pattern: inherit: ;');
# TEST #7 -- test expansion of pattern-specific recursive variables
@@ -118,7 +118,7 @@ pattrn: global: orginal $t pattern: inherit: ;');
run_make_test(undef, # reuse previous makefile
'rec=1',
'normal: global: new $t pattern: good $t inherit: good $t;
-pattrn: global: new $t pattern: good $t inherit: good $t;');
+pattern: global: new $t pattern: good $t inherit: good $t;');
# TEST #8: override in pattern-specific variables
diff --git a/tests/scripts/features/patternrules b/tests/scripts/features/patternrules
index eebe7c0..0ff49a7 100644
--- a/tests/scripts/features/patternrules
+++ b/tests/scripts/features/patternrules
@@ -110,7 +110,8 @@ $(dir)/foo.bar:
',
"dir=$dir",
-"#MAKE#: *** [$dir/foo.bar] Error 1",
+"#MAKEFILE#:6: recipe for target '$dir/foo.bar' failed
+#MAKE#: *** [$dir/foo.bar] Error 1",
512);
unlink("$dir/foo.bar");
@@ -203,7 +204,7 @@ CWEAVE := :
%.tex : %.w %.ch
!,
'foo.tex',
- "#MAKE#: *** No rule to make target `foo.tex'. Stop.", 512);
+ "#MAKE#: *** No rule to make target 'foo.tex'. Stop.", 512);
unlink(@f);
diff --git a/tests/scripts/features/recursion b/tests/scripts/features/recursion
index a6b8f90..fd5e351 100644
--- a/tests/scripts/features/recursion
+++ b/tests/scripts/features/recursion
@@ -18,7 +18,7 @@ last:
',
('CFLAGS=-O -w' . ($parallel_jobs ? ' -j 2' : '')),
($vos
- ? "#MAKE#: Entering directory `#PWD#'
+ ? "#MAKE#: Entering directory '#PWD#'
make 'CFLAGS=-O' -f #MAKEFILE# foo
make CFLAGS=-O
MAKELEVEL = 0
@@ -26,20 +26,20 @@ make 'CFLAGS=-O' -f #MAKEFILE# last
make CFLAGS=-O
MAKELEVEL = 0
THE END
-#MAKE#: Leaving directory `#PWD#'"
- : "#MAKE#: Entering directory `#PWD#'
+#MAKE#: Leaving directory '#PWD#'"
+ : "#MAKE#: Entering directory '#PWD#'
#MAKEPATH# -f #MAKEFILE# foo
-#MAKE#[1]: Entering directory `#PWD#'
+#MAKE#[1]: Entering directory '#PWD#'
#MAKEPATH#
MAKELEVEL = 1
#MAKEPATH# -f #MAKEFILE# last
-#MAKE#[2]: Entering directory `#PWD#'
+#MAKE#[2]: Entering directory '#PWD#'
#MAKEPATH#
MAKELEVEL = 2
THE END
-#MAKE#[2]: Leaving directory `#PWD#'
-#MAKE#[1]: Leaving directory `#PWD#'
-#MAKE#: Leaving directory `#PWD#'"));
+#MAKE#[2]: Leaving directory '#PWD#'
+#MAKE#[1]: Leaving directory '#PWD#'
+#MAKE#: Leaving directory '#PWD#'"));
# Test command line overrides.
diff --git a/tests/scripts/features/reinvoke b/tests/scripts/features/reinvoke
index 9952ced..eb1a349 100644
--- a/tests/scripts/features/reinvoke
+++ b/tests/scripts/features/reinvoke
@@ -57,9 +57,24 @@ include $(F)',
# 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', "[ -f b ] || echo >> b\nhello\n")
&rmfiles('a','b','c');
+# Ensure command line variables are preserved properly across re-exec
+# Tests for Savannah bug #30723
+
+run_make_test('
+ifdef RECURSE
+-include foo30723
+endif
+recurse: ; @$(MAKE) -f $(MAKEFILE_LIST) RECURSE=1 test
+test: ; @echo F.O=$(F.O)
+foo30723: ; @touch $@
+',
+ '--no-print-directory F.O=bar', "F.O=bar\n");
+
+unlink('foo30723');
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/rule_glob b/tests/scripts/features/rule_glob
new file mode 100644
index 0000000..2d377e7
--- /dev/null
+++ b/tests/scripts/features/rule_glob
@@ -0,0 +1,37 @@
+# -*-perl-*-
+
+$description = "Test globbing in targets and prerequisites.";
+
+$details = "";
+
+touch(qw(a.one a.two a.three));
+
+# Test wildcards in regular targets and prerequisites
+run_make_test(q{
+.PHONY: all a.one a.two a.three
+all: a.one* a.t[a-z0-9]o a.th[!q]ee
+a.o[Nn][Ee] a.t*: ; @echo $@
+},
+ '', "a.one\na.two\na.three");
+
+# Test wildcards in pattern targets and prerequisites
+run_make_test(q{
+.PHONY: all
+all: a.four
+%.four : %.t* ; @echo $@: $(sort $^)
+},
+ '', "a.four: a.three a.two");
+
+# Test wildcards in second expansion targets and prerequisites
+run_make_test(q{
+.PHONY: all
+all: a.four
+.SECONDEXPANSION:
+%.four : $$(sort %.t*) ; @echo $@: $(sort $^)
+},
+ '', "a.four: a.three a.two");
+
+unlink(qw(a.one a.two a.three));
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/se_explicit b/tests/scripts/features/se_explicit
index 79e0a36..790017a 100644
--- a/tests/scripts/features/se_explicit
+++ b/tests/scripts/features/se_explicit
@@ -6,6 +6,9 @@ $details = "";
# TEST #0: Test handing of '$' in prerequisites with and without second
# expansion.
+# If we don't support archives then the prerequisite is different
+my $prereq = exists $FEATURES{'archives'} ? '$' : '$(PRE)';
+
run_make_test(q!
ifdef SE
.SECONDEXPANSION:
@@ -18,7 +21,7 @@ PRE = three four
.DEFAULT: ; @echo '$@'
!,
'',
- "\$\nbar\$biz\nfoo\$bar : bar\$baz bar\$biz");
+ "$prereq\nbar\$biz\nfoo\$bar : bar\$baz bar\$biz");
run_make_test(undef, 'SE=1', "three\nfour\nbariz\nfoo\$bar : baraz bariz");
@@ -115,7 +118,7 @@ run_make_test(q!
.SECONDEXPANSION:
all : $$(eval $$(info test))
!,
- '', "test\n#MAKE#: Nothing to be done for `all'.\n");
+ '', "test\n#MAKE#: Nothing to be done for 'all'.\n");
# TEST #5: (NEGATIVE) catch eval in a prereq list trying to create new
# target/prereq relationships.
@@ -152,5 +155,13 @@ a%l: q1x $$+ q2x ; @echo '$+'
'', "q1x bar bar q2x bar bar\n");
-# This tells the test driver that the perl test script executed properly.
+# Allow patsubst shorthand in second expansion context.
+# Requires the colon to be quoted. Savannah bug #16545
+run_make_test(q!
+.PHONY: foo.bar
+.SECONDEXPANSION:
+foo: $$(@\\:%=%.bar); @echo '$^'
+!,
+ '', "foo.bar\n");
+
1;
diff --git a/tests/scripts/features/se_implicit b/tests/scripts/features/se_implicit
index e9acb2f..ec09d8d 100644
--- a/tests/scripts/features/se_implicit
+++ b/tests/scripts/features/se_implicit
@@ -222,5 +222,39 @@ foo.o:
!,
'', "\n");
+# Test #10: Test second expansion with second expansion prerequisites
+# Ensures pattern_search() recurses with SE prereqs.
+touch('a');
+run_make_test(q!
+.SECONDEXPANSION:
+sim_base_rgg := just_a_name
+sim_base_src := a
+sim_base_f := a a a
+sim_%.f: $${sim_$$*_f}
+ echo $@
+sim_%.src: $${sim_$$*_src}
+ echo $@
+sim_%: \
+ $$(if $$(sim_$$*_src),sim_%.src) \
+ $$(if $$(sim_$$*_f),sim_%.f) \
+ $$(if $$(sim_$$*_rgg),$$(sim_$$*_rgg).s)
+ echo $@
+!,
+ '-s sim_base', "#MAKE#: *** No rule to make target 'sim_base'. Stop.", 512);
+
+unlink('a');
+
+# Ensure that order-only tokens embedded in second expansions are parsed
+run_make_test(q!
+.SECONDEXPANSION:
+PREREQS=p1|p2
+P2=p2
+all : foo bar
+f%o: $$(PREREQS) ; @echo '$@' from '$^' and '$|'
+b%r: p1|$$(P2) ; @echo '$@' from '$^' and '$|'
+p% : ; : $@
+!,
+ "", ": p1\n: p2\nfoo from p1 and p2\nbar from p1 and p2\n");
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/shell_assignment b/tests/scripts/features/shell_assignment
new file mode 100644
index 0000000..686e4bd
--- /dev/null
+++ b/tests/scripts/features/shell_assignment
@@ -0,0 +1,65 @@
+# -*-perl-*-
+
+$description = "Test BSD-style shell assignments (VAR != VAL) for variables.";
+
+$details = "";
+
+# TEST 0: Basic shell assignment (!=).
+
+run_make_test('
+.POSIX:
+
+demo1!=printf \' 1 2 3\n4\n\n5 \n \n 6\n\n\n\n\'
+demo2 != printf \'7 8\n \'
+demo3 != printf \'$$(demo2)\'
+demo4 != printf \' 2 3 \n\'
+demo5 != printf \' 2 3 \n\n\'
+all: ; @echo "<$(demo1)> <$(demo2)> <$(demo3)> <$(demo4)> <${demo5}>"
+',
+ '', "< 1 2 3 4 5 6 > <7 8 > <7 8 > < 2 3 > < 2 3 >\n");
+
+# TEST 1: Handle '#' the same way as BSD make
+
+run_make_test('
+foo1!=echo bar#baz
+hash != printf \'\043\'
+foo2!= echo "bar$(hash)baz"
+
+all: ; @echo "<$(foo1)> <$(hash)> <$(foo2)>"
+',
+ '', "<bar> <#> <bar#baz>\n");
+
+# TEST 2: shell assignment variables (from !=) should be recursive.
+# Note that variables are re-evaluated later, so the shell can output
+# a value like $(XYZZY) as part of !=. The $(XYZZY) will be EVALUATED
+# when the value containing it is evaluated. On the negative side, this
+# means if you don't want this, you need to escape dollar signs as $$.
+# On the positive side, it means that shell programs can output macros
+# that are then evaluated as they are traditionally evaluated.. and that
+# you can use traditional macro evaluation semantics to implement !=.
+
+run_make_test('
+XYZZY = fiddle-dee-dee
+dollar = $$
+VAR3 != printf \'%s\' \'$(dollar)(XYZZY)\'
+
+all: ; @echo "<$(VAR3)>"
+',
+ '', "<fiddle-dee-dee>\n");
+
+
+# TEST 3: Overrides invoke shell anyway; they just don't store the result
+# in a way that is visible.
+
+run_make_test('
+
+override != echo abc > ,abc ; cat ,abc
+
+all: ; @echo "<$(override)>" ; cat ,abc
+',
+ 'override=xyz', "<xyz>\nabc\n");
+
+unlink(',abc');
+
+
+1;
diff --git a/tests/scripts/features/targetvars b/tests/scripts/features/targetvars
index ddd6c1f..a9b8dbe 100644
--- a/tests/scripts/features/targetvars
+++ b/tests/scripts/features/targetvars
@@ -237,10 +237,20 @@ a: ; @echo "$(FOO)"
run_make_test(undef, 'FOO=C', "C f1\n");
+# TEST #19: Conditional variables with command-line settings
+
+run_make_test('
+a: FOO ?= f1
+a: ; @echo "$(FOO)"
+',
+ '', "f1\n");
+
+run_make_test(undef, 'FOO=C', "C\n");
+
# TEST #20: Check for continuation after semicolons
run_make_test(q!
-a: A = 'hello; \
+a: A = 'hello;\
world'
a: ; @echo $(A)
!,
diff --git a/tests/scripts/features/utf8 b/tests/scripts/features/utf8
new file mode 100644
index 0000000..54bc471
--- /dev/null
+++ b/tests/scripts/features/utf8
@@ -0,0 +1,11 @@
+# -*-perl-*-
+
+$description = "Test support for UTF-8.";
+
+$details = "";
+
+# Verify that the UTF-8 BOM is ignored.
+run_make_test("\xEF\xBB\xBFall: ; \@echo \$\@\n", '', "all");
+
+# 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 15d5071..d8f3ffb 100644
--- a/tests/scripts/features/varnesting
+++ b/tests/scripts/features/varnesting
@@ -1,29 +1,30 @@
-$description = "The following test creates a makefile to ...";
+# -*-perl-*-
+$description = "Test recursive variables";
$details = "";
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "x = variable1\n"
- ."variable2 := Hello\n"
- ."y = \$(subst 1,2,\$(x))\n"
- ."z = y\n"
- ."a := \$(\$(\$(z)))\n"
- ."all: \n"
- ."\t\@echo \$(a)\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 = "Hello\n";
-
-&compare_output($answer,&get_logfile(1));
+run_make_test('
+x = variable1
+variable2 := Hello
+y = $(subst 1,2,$(x))
+z = y
+a := $($($(z)))
+all:
+ @echo $(a)
+',
+ '', "Hello\n");
+
+# This tests resetting the value of a variable while expanding it.
+# You may only see problems with this if you're using valgrind or
+# some other memory checker that poisons freed memory.
+# See Savannah patch #7534
+
+run_make_test('
+VARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE)
+wololo:
+ @$(VARIABLE)
+',
+ '', "hi\n");
1;
diff --git a/tests/scripts/features/vpath b/tests/scripts/features/vpath
index a3aebd9..ec24165 100644
--- a/tests/scripts/features/vpath
+++ b/tests/scripts/features/vpath
@@ -74,7 +74,7 @@ vpath-d/a: fail.te
vpath-d/b : fail.te
vpath-d/fail.te:
!,
- '', "#MAKE#: Nothing to be done for `default'.\n");
+ '', "#MAKE#: Nothing to be done for 'default'.\n");
rmdir('vpath-d');
diff --git a/tests/scripts/features/vpath3 b/tests/scripts/features/vpath3
index 978c5ee..c6ede28 100644
--- a/tests/scripts/features/vpath3
+++ b/tests/scripts/features/vpath3
@@ -1,50 +1,35 @@
-# -*-perl-*-
+# -*-perl-*-
$description = "Test the interaction of the -lfoo feature and vpath";
$details = "";
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "vpath %.a a1\n";
-print MAKEFILE "vpath %.so b1\n";
-print MAKEFILE "vpath % a2 b2\n";
-print MAKEFILE "vpath % b3\n";
-print MAKEFILE "all: -l1 -l2 -l3; \@echo \$^\n";
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-mkdir("a1", 0777);
-mkdir("b1", 0777);
-mkdir("a2", 0777);
-mkdir("b2", 0777);
-mkdir("b3", 0777);
-
-@files_to_touch = ("a1${pathsep}lib1.a",
- "b1${pathsep}lib1.so",
- "a2${pathsep}lib2.a",
- "b2${pathsep}lib2.so",
- "lib3.a",
- "b3${pathsep}lib3.so");
+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);
-&run_make_with_options($makefile,"",&get_logfile);
-
-# Create the answer to what should be produced by this Makefile
-$answer = "a1${pathsep}lib1.a a2${pathsep}lib2.a lib3.a\n";
-
-if (&compare_output($answer,&get_logfile(1)))
-{
- unlink @files_to_touch;
- rmdir("a1");
- rmdir("b1");
- rmdir("a2");
- rmdir("b2");
- rmdir("b3");
+run_make_test('
+vpath %.h b3
+vpath %.a a1
+vpath %.so b1
+vpath % a2 b2
+vpath % b3
+all: -l1 -lc -l2 -l3; @echo $^
+',
+ '', "a1${pathsep}lib1.a a1${pathsep}libc.a a2${pathsep}lib2.a lib3.a\n");
+
+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 f7683f5..5e6217b 100644
--- a/tests/scripts/features/vpathgpath
+++ b/tests/scripts/features/vpathgpath
@@ -57,7 +57,7 @@ sub touchfiles {
push(@touchedfiles, "bar.c");
-$answer = "$make_name: Nothing to be done for `general'.\n";
+$answer = "$make_name: Nothing to be done for 'general'.\n";
&compare_output($answer,&get_logfile(1));
diff --git a/tests/scripts/features/vpathplus b/tests/scripts/features/vpathplus
index a37fbed..361788c 100644
--- a/tests/scripts/features/vpathplus
+++ b/tests/scripts/features/vpathplus
@@ -86,6 +86,7 @@ cat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1
$answer = "not creating notarget.c from notarget.d
cat notarget.c > notarget.b 2>/dev/null || exit 1
+$makefile:16: recipe for target 'notarget.b' failed
$make_name: *** [notarget.b] Error 1
";
diff --git a/tests/scripts/functions/call b/tests/scripts/functions/call
index f3c5470..9db9da7 100644
--- a/tests/scripts/functions/call
+++ b/tests/scripts/functions/call
@@ -13,7 +13,7 @@ print MAKEFILE <<'EOMAKE';
#
reverse = $2 $1
-# A complex `map' function, using recursive `call'.
+# A complex 'map' function, using recursive 'call'.
#
map = $(foreach a,$2,$(call $1,$a))
@@ -38,7 +38,7 @@ two = $(call one,$(1),foo,$(2))
DEP_foo = bar baz quux
DEP_baz = quux blarp
rest = $(wordlist 2,$(words ${1}),${1})
-tclose = $(if $1,$(firstword $1) \
+tclose = $(if $1,$(firstword $1)\
$(call tclose,$(sort ${DEP_$(firstword $1)} $(call rest,$1))))
all: ; @echo '$(call reverse,bar,foo)'; \
@@ -96,4 +96,15 @@ close(MAKEFILE);
$answer = "1 2 3 4 5 6 7 8 9\n1 2 3 4 5\n1 2 3\n1 2 3\n";
&compare_output($answer,&get_logfile(1));
+# Ensure that variables are defined in global scope even in a $(call ...)
+
+delete $ENV{X123};
+
+run_make_test('
+tst = $(eval export X123)
+$(call tst)
+all: ; @echo "$${X123-not set}"
+',
+ '', "\n");
+
1;
diff --git a/tests/scripts/functions/file b/tests/scripts/functions/file
new file mode 100644
index 0000000..9a4cd02
--- /dev/null
+++ b/tests/scripts/functions/file
@@ -0,0 +1,101 @@
+# -*-perl-*-
+
+$description = 'Test the $(file ...) function.';
+
+# Test > and >>
+run_make_test(q!
+define A
+a
+b
+endef
+B = c d
+$(file >file.out,$(A))
+$(foreach L,$(B),$(file >> file.out,$L))
+x:;@echo hi; cat file.out
+!,
+ '', "hi\na\nb\nc\nd");
+
+unlink('file.out');
+
+# Test >> to a non-existent file
+run_make_test(q!
+define A
+a
+b
+endef
+$(file >> file.out,$(A))
+x:;@cat file.out
+!,
+ '', "a\nb");
+
+unlink('file.out');
+
+# Test > to a read-only file
+touch('file.out');
+chmod(0444, 'file.out');
+
+# Find the error that will be printed
+# This seems complicated, but we need the message from the C locale
+my $loc = undef;
+if ($has_POSIX) {
+ $loc = POSIX::setlocale(POSIX::LC_MESSAGES);
+ POSIX::setlocale(POSIX::LC_MESSAGES, 'C');
+}
+my $e;
+open(my $F, '>', 'file.out') and die "Opened read-only file!\n";
+$e = "$!";
+$loc and POSIX::setlocale(POSIX::LC_MESSAGES, $loc);
+
+run_make_test(q!
+define A
+a
+b
+endef
+$(file > file.out,$(A))
+x:;@cat file.out
+!,
+ '', "#MAKEFILE#:6: *** open: file.out: $e. Stop.",
+ 512);
+
+unlink('file.out');
+
+# Use variables for operator and filename
+run_make_test(q!
+define A
+a
+b
+endef
+OP = >
+FN = file.out
+$(file $(OP) $(FN),$(A))
+x:;@cat file.out
+!,
+ '', "a\nb");
+
+unlink('file.out');
+
+# Don't add newlines if one already exists
+run_make_test(q!
+define A
+a
+b
+
+endef
+$(file >file.out,$(A))
+x:;@cat file.out
+!,
+ '', "a\nb");
+
+unlink('file.out');
+
+# Empty text
+run_make_test(q!
+$(file >file.out,)
+$(file >>file.out,)
+x:;@cat file.out
+!,
+ '', "\n\n");
+
+unlink('file.out');
+
+1;
diff --git a/tests/scripts/functions/filter-out b/tests/scripts/functions/filter-out
index 6c8b27a..1fe4819 100644
--- a/tests/scripts/functions/filter-out
+++ b/tests/scripts/functions/filter-out
@@ -1,6 +1,6 @@
# -*-perl-*-
-$description = "Test the filter-out function.";
+$description = "Test the filter and filter-out functions.";
$details = "The makefile created in this test has two variables. The
filter-out function is first used to discard names ending in
@@ -11,18 +11,32 @@ which is only used if there are multiple literals present in both
the pattern and text arguments. The result of both filter-out
functions is the same single .elc name.\n";
-open(MAKEFILE,"> $makefile");
+# Basic test -- filter
+run_make_test(q!
+files1 := $(filter %.o, foo.elc bar.o lose.o)
+files2 := $(filter %.o foo.i, foo.i bar.i lose.i foo.elc bar.o lose.o)
+all: ; @echo '$(files1) $(files2)'
+!,
+ '', "bar.o lose.o foo.i bar.o lose.o\n");
-print MAKEFILE <<'EOF';
+# Basic test -- filter-out
+run_make_test(q!
files1 := $(filter-out %.o, foo.elc bar.o lose.o)
files2 := $(filter-out foo.i bar.i lose.i %.o, foo.i bar.i lose.i foo.elc bar.o lose.o)
-all: ; @echo $(files1) $(files2)
-EOF
+all: ; @echo '$(files1) $(files2)'
+!,
+ '', "foo.elc foo.elc\n");
-close(MAKEFILE);
+# Escaped patterns
+run_make_test(q!all:;@echo '$(filter foo\%bar,foo%bar fooXbar)'!,
+ '', "foo%bar\n");
-&run_make_with_options($makefile, "", &get_logfile, 0);
-$answer = "foo.elc foo.elc\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(q!all:;@echo '$(filter foo\%\%\\\\\%\%bar,foo%%\\%%bar fooX\\Ybar)'!,
+ '', "foo%%\\%%bar\n");
+
+run_make_test(q!
+X = $(filter foo\\\\\%bar,foo\%bar foo\Xbar)
+all:;@echo '$(X)'!,
+ '', "foo\\%bar\n");
1;
diff --git a/tests/scripts/functions/foreach b/tests/scripts/functions/foreach
index 82e99d7..4d1a11d 100644
--- a/tests/scripts/functions/foreach
+++ b/tests/scripts/functions/foreach
@@ -1,5 +1,5 @@
# -*-perl-*-
-# $Id: foreach,v 1.5 2006/03/10 02:20:46 psmith Exp $
+# $Id$
$description = "Test the foreach function.";
@@ -62,7 +62,7 @@ y = $x
all: ; @echo $y',
'',
- "#MAKEFILE#:2: *** insufficient number of arguments (1) to function `foreach'. Stop.",
+ "#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'foreach'. Stop.",
512);
run_make_test('
@@ -71,7 +71,7 @@ y := $x
all: ; @echo $y',
'',
- "#MAKEFILE#:2: *** insufficient number of arguments (1) to function `foreach'. Stop.",
+ "#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'foreach'. Stop.",
512);
1;
diff --git a/tests/scripts/functions/guile b/tests/scripts/functions/guile
new file mode 100644
index 0000000..c63bec9
--- /dev/null
+++ b/tests/scripts/functions/guile
@@ -0,0 +1,99 @@
+# -*-perl-*-
+
+$description = 'Test the $(guile ...) function.';
+
+$details = 'This only works on systems that support it.';
+
+# If this instance of make doesn't support GNU Guile, skip it
+# This detects if guile is loaded using the "load" directive
+# $makefile = get_tmpfile();
+# open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n";
+# print MAKEFILE q!
+# -load guile
+# all: ; @echo $(filter guile,$(.LOADED))
+# !;
+# close(MAKEFILE) || die "Failed to write $makefile: $!\n";
+# $cmd = subst_make_string("#MAKEPATH# -f $makefile");
+# $log = get_logfile(0);
+# $code = run_command_with_output($log, $cmd);
+# read_file_into_string ($log) eq "guile\n" and $FEATURES{guile} = 1;
+
+# If we don't have Guile support, never mind.
+exists $FEATURES{guile} or return -1;
+
+# Verify simple data type conversions
+# Currently we don't support vectors:
+# echo '$(guile (vector 1 2 3))'; \
+run_make_test(q!
+x:;@echo '$(guile #f)'; \
+ echo '$(guile #t)'; \
+ echo '$(guile #\c)'; \
+ echo '$(guile 1234)'; \
+ echo '$(guile 'foo)'; \
+ echo '$(guile "bar")'; \
+ echo '$(guile (cons 'a 'b))'; \
+ echo '$(guile '(a b (c . d) 1 (2) 3))'
+!,
+ '', "\n#t\nc\n1234\nfoo\nbar\na b\na b c d 1 2 3");
+
+# Verify the gmk-expand function
+run_make_test(q!
+VAR = $(guile (gmk-expand "$(shell echo hi)"))
+x:;@echo '$(VAR)'
+!,
+ '', "hi");
+
+# Verify the gmk-eval function
+# Prove that the string is expanded only once (by eval)
+run_make_test(q!
+TEST = bye
+EVAL = VAR = $(TEST) $(shell echo there)
+$(guile (gmk-eval "$(value EVAL)"))
+TEST = hi
+x:;@echo '$(VAR)'
+!,
+ '', "hi there");
+
+# Verify the gmk-eval function with a list
+run_make_test(q!
+$(guile (gmk-eval '(VAR = 1 (2) () 3)))
+x:;@echo '$(VAR)'
+!,
+ '', "1 2 3");
+
+# Verify the gmk-var function
+run_make_test(q!
+VALUE = hi $(shell echo there)
+VAR = $(guile (gmk-var "VALUE"))
+x:;@echo '$(VAR)'
+!,
+ '', "hi there");
+
+# Verify the gmk-var function with a symbol
+run_make_test(q!
+VALUE = hi $(shell echo there)
+VAR = $(guile (gmk-var 'VALUE))
+x:;@echo '$(VAR)'
+!,
+ '', "hi there");
+
+# Write a Guile program using define and run it
+run_make_test(q!
+# Define the "fib" function in Guile
+define fib
+;; A procedure for counting the n:th Fibonacci number
+;; See SICP, p. 37
+(define (fib n)
+ (cond ((= n 0) 0)
+ ((= n 1) 1)
+ (else (+ (fib (- n 1))
+ (fib (- n 2))))))
+endef
+$(guile $(fib))
+
+# Now run it
+x:;@echo $(guile (fib $(FIB)))
+!,
+ 'FIB=10', "55");
+
+1;
diff --git a/tests/scripts/functions/sort b/tests/scripts/functions/sort
index d472102..b558910 100644
--- a/tests/scripts/functions/sort
+++ b/tests/scripts/functions/sort
@@ -1,55 +1,47 @@
-$description = "The following test creates a makefile to verify\n"
- ."the ability of make to sort lists of object. Sort\n"
- ."will also remove any duplicate entries. This will also\n"
- ."be tested.";
-
-$details = "The make file is built with a list of object in a random order\n"
- ."and includes some duplicates. Make should sort all of the elements\n"
- ."remove all duplicates\n";
-
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "foo := moon_light days \n"
- ."foo1:= jazz\n"
- ."bar := captured \n"
- ."bar2 = boy end, has rise A midnight \n"
- ."bar3:= \$(foo)\n"
- ."s1 := _by\n"
- ."s2 := _and_a\n"
- ."t1 := \$(addsuffix \$(s1), \$(bar) )\n"
- ."t2 := \$(addsuffix \$(s2), \$(foo1) )\n"
- ."t3 := \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \n"
- ."t4 := \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \n"
- ."t5 := \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \n"
- ."t6 := \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \n"
- ."t7 := \$(t6) \$(t6) \$(t6) \n"
- ."p1 := \$(addprefix \$(foo1), \$(s2) )\n"
- ."blank:= \n"
- ."all:\n"
- ."\t\@echo \$(sort \$(bar2) \$(foo) \$(addsuffix \$(s1), \$(bar) ) \$(t2) \$(bar2) \$(bar3))\n"
- ."\t\@echo \$(sort \$(blank) \$(foo) \$(bar2) \$(t1) \$(p1) )\n"
- ."\t\@echo \$(sort \$(foo) \$(bar2) \$(t1) \$(t4) \$(t5) \$(t7) \$(t6) )\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 = "A boy captured_by days end, has jazz_and_a midnight moon_light rise\n"
- ."A boy captured_by days end, has jazz_and_a midnight moon_light rise\n"
- ."A boy captured_by days end, has jazz_and_a midnight moon_light rise\n";
-
-&compare_output($answer,&get_logfile(1));
+# -*-perl-*-
+
+$description = "The following test creates a makefile to verify
+the ability of make to sort lists of object. Sort
+will also remove any duplicate entries. This will also
+be tested.";
+
+$details = "The make file is built with a list of object in a random order
+and includes some duplicates. Make should sort all of the elements
+remove all duplicates\n";
+
+run_make_test('
+foo := moon_light days
+foo1:= jazz
+bar := captured
+bar2 = boy end, has rise A midnight
+bar3:= $(foo)
+s1 := _by
+s2 := _and_a
+t1 := $(addsuffix $(s1), $(bar) )
+t2 := $(addsuffix $(s2), $(foo1) )
+t3 := $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2)
+t4 := $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3)
+t5 := $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4)
+t6 := $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5)
+t7 := $(t6) $(t6) $(t6)
+p1 := $(addprefix $(foo1), $(s2) )
+blank:=
+all:
+ @echo $(sort $(bar2) $(foo) $(addsuffix $(s1), $(bar) ) $(t2) $(bar2) $(bar3))
+ @echo $(sort $(blank) $(foo) $(bar2) $(t1) $(p1) )
+ @echo $(sort $(foo) $(bar2) $(t1) $(t4) $(t5) $(t7) $(t6) )
+',
+ '', 'A boy captured_by days end, has jazz_and_a midnight moon_light rise
+A boy captured_by days end, has jazz_and_a midnight moon_light rise
+A boy captured_by days end, has jazz_and_a midnight moon_light rise
+');
+
+
+# Test with non-space/tab whitespace. Note that you can't see the
+# original bug except using valgrind.
+
+run_make_test("FOO = a b\tc\rd\fe \f \f \f \f \ff
+all: ; \@echo \$(words \$(sort \$(FOO)))\n",
+ '', "5\n");
1;
-
-
-
-
-
-
diff --git a/tests/scripts/functions/wildcard b/tests/scripts/functions/wildcard
index 2841f5d..bcd84ad 100644
--- a/tests/scripts/functions/wildcard
+++ b/tests/scripts/functions/wildcard
@@ -88,4 +88,16 @@ all: ; @echo $(wildcard xz--y*.7)
!,
'', "\n");
+# TEST #5: wildcard used to verify file existence
+
+touch('xxx.yyy');
+
+run_make_test(q!exists: ; @echo file=$(wildcard xxx.yyy)!,
+ '', "file=xxx.yyy\n");
+
+unlink('xxx.yyy');
+
+run_make_test(q!exists: ; @echo file=$(wildcard xxx.yyy)!,
+ '', "file=\n");
+
1;
diff --git a/tests/scripts/functions/word b/tests/scripts/functions/word
index 34527ea..4dcc940 100644
--- a/tests/scripts/functions/word
+++ b/tests/scripts/functions/word
@@ -56,32 +56,32 @@ wordlist-e1: ; @echo $(wordlist ,,$(FOO))
wordlist-e2: ; @echo $(wordlist abc ,,$(FOO))
wordlist-e3: ; @echo $(wordlist 1, 12a ,$(FOO))',
'word-e1',
- "#MAKEFILE#:3: *** non-numeric first argument to `word' function: ''. Stop.",
+ "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: ''. Stop.",
512);
run_make_test(undef,
'word-e2',
- "#MAKEFILE#:4: *** non-numeric first argument to `word' function: 'abc '. Stop.",
+ "#MAKEFILE#:4: *** non-numeric first argument to 'word' function: 'abc '. Stop.",
512);
run_make_test(undef,
'word-e3',
- "#MAKEFILE#:5: *** non-numeric first argument to `word' function: '1a'. Stop.",
+ "#MAKEFILE#:5: *** non-numeric first argument to 'word' function: '1a'. Stop.",
512);
run_make_test(undef,
'wordlist-e1',
- "#MAKEFILE#:7: *** non-numeric first argument to `wordlist' function: ''. Stop.",
+ "#MAKEFILE#:7: *** non-numeric first argument to 'wordlist' function: ''. Stop.",
512);
run_make_test(undef,
'wordlist-e2',
- "#MAKEFILE#:8: *** non-numeric first argument to `wordlist' function: 'abc '. Stop.",
+ "#MAKEFILE#:8: *** non-numeric first argument to 'wordlist' function: 'abc '. Stop.",
512);
run_make_test(undef,
'wordlist-e3',
- "#MAKEFILE#:9: *** non-numeric second argument to `wordlist' function: ' 12a '. Stop.",
+ "#MAKEFILE#:9: *** non-numeric second argument to 'wordlist' function: ' 12a '. Stop.",
512);
# Test error conditions again, but this time in a variable reference
@@ -94,37 +94,37 @@ WL = $(wordlist $s,$e,$(FOO))
word-e: ; @echo $(W)
wordlist-e: ; @echo $(WL)',
'word-e x=',
- "#MAKEFILE#:3: *** non-numeric first argument to `word' function: ''. Stop.",
+ "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: ''. Stop.",
512);
run_make_test(undef,
'word-e x=abc',
- "#MAKEFILE#:3: *** non-numeric first argument to `word' function: 'abc'. Stop.",
+ "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: 'abc'. Stop.",
512);
run_make_test(undef,
'word-e x=0',
- "#MAKEFILE#:3: *** first argument to `word' function must be greater than 0. Stop.",
+ "#MAKEFILE#:3: *** first argument to 'word' function must be greater than 0. Stop.",
512);
run_make_test(undef,
'wordlist-e s= e=',
- "#MAKEFILE#:4: *** non-numeric first argument to `wordlist' function: ''. Stop.",
+ "#MAKEFILE#:4: *** non-numeric first argument to 'wordlist' function: ''. Stop.",
512);
run_make_test(undef,
'wordlist-e s=abc e=',
- "#MAKEFILE#:4: *** non-numeric first argument to `wordlist' function: 'abc'. Stop.",
+ "#MAKEFILE#:4: *** non-numeric first argument to 'wordlist' function: 'abc'. Stop.",
512);
run_make_test(undef,
'wordlist-e s=4 e=12a',
- "#MAKEFILE#:4: *** non-numeric second argument to `wordlist' function: '12a'. Stop.",
+ "#MAKEFILE#:4: *** non-numeric second argument to 'wordlist' function: '12a'. Stop.",
512);
run_make_test(undef,
'wordlist-e s=0 e=12',
- "#MAKEFILE#:4: *** invalid first argument to `wordlist' function: `0'. Stop.",
+ "#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: '0'. Stop.",
512);
diff --git a/tests/scripts/misc/bs-nl b/tests/scripts/misc/bs-nl
new file mode 100644
index 0000000..4fc3f63
--- /dev/null
+++ b/tests/scripts/misc/bs-nl
@@ -0,0 +1,129 @@
+# -*-perl-*-
+$description = "Test backslash-newline handling.";
+
+$details = "";
+
+# TEST #1
+# -------
+
+# Backslash-newlines in recipes
+
+# These are basic backslash-newlines with no tricks
+run_make_test("fast:;\@echo fa\\\nst\n",
+ '', 'fast');
+
+run_make_test("slow:;\@: no-op; echo sl\\\now\n",
+ '', 'slow');
+
+run_make_test("dquote:;\@echo \"dqu\\\note\"\n",
+ '', 'dquote');
+
+run_make_test("squote:;\@echo 'squ\\\note'\n",
+ '', "squ\\\note");
+
+# Ensure that a leading prefix character is omitted
+run_make_test("fast:;\@echo fa\\\n\tst\n",
+ '', 'fast');
+
+run_make_test("slow:;\@: no-op; echo sl\\\n\tow\n",
+ '', 'slow');
+
+run_make_test("dquote:;\@echo \"dqu\\\n\tote\"\n",
+ '', 'dquote');
+
+run_make_test("squote:;\@echo 'squ\\\n\tote'\n",
+ '', "squ\\\note");
+
+# Ensure that ONLY the leading prefix character is omitted
+run_make_test("fast:;\@echo fa\\\n\t st\n",
+ '', 'fa st');
+
+run_make_test("slow:;\@: no-op; echo sl\\\n\t\tow\n",
+ '', "sl ow");
+
+run_make_test("dquote:;\@echo \"dqu\\\n\t ote\"\n",
+ '', 'dqu ote');
+
+run_make_test("squote:;\@echo 'squ\\\n\t\t ote'\n",
+ '', "squ\\\n\t ote");
+
+# Backslash-newlines in variable values
+
+# Simple
+run_make_test(q!
+var = he\
+llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# Condense trailing space
+run_make_test(q!
+var = he \
+llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# Remove leading space
+run_make_test(q!
+var = he\
+ llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# Multiple bs/nl condensed
+run_make_test(q!
+var = he\
+\
+\
+ llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# POSIX: Preserve trailing space
+run_make_test(q!
+.POSIX:
+x = y
+var = he \
+llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# POSIX: One space per bs-nl
+run_make_test(q!
+.POSIX:
+x = y
+var = he\
+\
+\
+ llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# Savannah #39035: handle whitespace in call
+run_make_test(q!
+f = echo $(1)
+t:; @$(call f,"a \
+ b"); \
+ $(call f,"a \
+ b")
+!,
+ '', "a b\na b\n");
+
+# Savannah #38945: handle backslash CRLF
+# We need our own makefile so we can set binmode
+my $m1 = get_tmpfile();
+open(MAKEFILE, "> $m1");
+binmode(MAKEFILE);
+print MAKEFILE "FOO = foo \\\r\n";
+close(MAKEFILE);
+
+my $m2 = get_tmpfile();
+open(MAKEFILE, "> $m2");
+print MAKEFILE "include $m1\ndefine BAR\nall: ; \@echo \$(FOO) bar\nendef\n\$(eval \$(BAR))\n";
+close(MAKEFILE);
+
+run_make_with_options($m2, '', get_logfile());
+compare_output("foo bar\n", get_logfile(1));
+
+
+1;
diff --git a/tests/scripts/misc/fopen-fail b/tests/scripts/misc/fopen-fail
new file mode 100644
index 0000000..6580e51
--- /dev/null
+++ b/tests/scripts/misc/fopen-fail
@@ -0,0 +1,15 @@
+# -*-perl-*-
+
+$description = "Make sure make exits with an error if fopen fails.";
+
+# Recurse infinitely until we run out of open files, and ensure we
+# fail with a non-zero exit code. Don't bother to test the output
+# since it's hard to know what it will be, exactly.
+# See Savannah bug #27374.
+
+run_make_test(q!
+include $(lastword $(MAKEFILE_LIST))
+!,
+ '', undef, 512);
+
+1;
diff --git a/tests/scripts/misc/general3 b/tests/scripts/misc/general3
index b3142c2..8ad0f8e 100644
--- a/tests/scripts/misc/general3
+++ b/tests/scripts/misc/general3
@@ -26,7 +26,7 @@ TAB = \t \# A TAB and some spaces
\$(STR)
\$(STR) \$(TAB)",
- '', "#MAKE#: Nothing to be done for `all'.");
+ '', "#MAKE#: Nothing to be done for 'all'.");
# TEST 2
diff --git a/tests/scripts/options/dash-B b/tests/scripts/options/dash-B
index e36842e..9c708b7 100644
--- a/tests/scripts/options/dash-B
+++ b/tests/scripts/options/dash-B
@@ -22,13 +22,13 @@ foo: bar.x
',
'', 'cp bar.x foo');
-run_make_test(undef, '', "#MAKE#: Nothing to be done for `all'.");
+run_make_test(undef, '', "#MAKE#: Nothing to be done for 'all'.");
run_make_test(undef, '-B', 'cp bar.x foo');
# Put the timestamp for foo into the future; it should still be remade.
utouch(1000, 'foo');
-run_make_test(undef, '', "#MAKE#: Nothing to be done for `all'.");
+run_make_test(undef, '', "#MAKE#: Nothing to be done for 'all'.");
run_make_test(undef, '-B', 'cp bar.x foo');
# Clean up
diff --git a/tests/scripts/options/dash-C b/tests/scripts/options/dash-C
index 5864ffd..42d0a8b 100644
--- a/tests/scripts/options/dash-C
+++ b/tests/scripts/options/dash-C
@@ -34,9 +34,9 @@ if (-f $example) {
}
# Create the answer to what should be produced by this Makefile
-$answer = "$make_name: Entering directory `$wpath'\n"
+$answer = "$make_name: Entering directory '$wpath'\n"
. "$delete_command EXAMPLE\n"
- . "$make_name: Leaving directory `$wpath'\n";
+ . "$make_name: Leaving directory '$wpath'\n";
&compare_output($answer,&get_logfile(1));
@@ -62,9 +62,9 @@ if (-f $example) {
}
# Create the answer to what should be produced by this Makefile
-$answer = "$make_name: Entering directory `$wpath'\n"
+$answer = "$make_name: Entering directory '$wpath'\n"
. "$delete_command EXAMPLEslash\n"
- . "$make_name: Leaving directory `$wpath'\n";
+ . "$make_name: Leaving directory '$wpath'\n";
&compare_output($answer,&get_logfile(1));
diff --git a/tests/scripts/options/dash-I b/tests/scripts/options/dash-I
index 8dc5d9b..d47a8d8 100644
--- a/tests/scripts/options/dash-I
+++ b/tests/scripts/options/dash-I
@@ -51,9 +51,9 @@ $answer = "This is another included makefile\n";
$answer = "$mkpath ANOTHER -f $makefile
-${make_name}[1]: Entering directory `$pwd'
+${make_name}[1]: Entering directory '$pwd'
This is another included makefile
-${make_name}[1]: Leaving directory `$pwd'\n";
+${make_name}[1]: Leaving directory '$pwd'\n";
&run_make_with_options($makefile,"-I $workdir recurse",&get_logfile);
&compare_output($answer,&get_logfile(1));
diff --git a/tests/scripts/options/dash-W b/tests/scripts/options/dash-W
index d3fde87..20b9f74 100644
--- a/tests/scripts/options/dash-W
+++ b/tests/scripts/options/dash-W
@@ -12,7 +12,7 @@ a.x b.x: ; echo >> $@
# Run it again: nothing should happen
-run_make_test(undef, '', "#MAKE#: `a.x' is up to date.");
+run_make_test(undef, '', "#MAKE#: 'a.x' is up to date.");
# Now run it with -W b.x: should rebuild a.x
@@ -21,7 +21,7 @@ run_make_test(undef, '-W b.x', 'echo >> a.x');
# Put the timestamp for a.x into the future; it should still be remade.
utouch(1000, 'a.x');
-run_make_test(undef, '', "#MAKE#: `a.x' is up to date.");
+run_make_test(undef, '', "#MAKE#: 'a.x' is up to date.");
run_make_test(undef, '-W b.x', 'echo >> a.x');
# Clean up
diff --git a/tests/scripts/options/dash-k b/tests/scripts/options/dash-k
index d87a786..e784e0d 100644
--- a/tests/scripts/options/dash-k
+++ b/tests/scripts/options/dash-k
@@ -57,10 +57,10 @@ else {
# Create the answer to what should be produced by this Makefile
$answer = "cc -c main.c
-$make_name: *** No rule to make target `kbd.c', needed by `kbd.o'.
+$make_name: *** No rule to make target 'kbd.c', needed by 'kbd.o'.
cc -c commands.c
cc -c display.c
-$make_name: Target `edit' not remade because of errors.\n";
+$make_name: Target 'edit' not remade because of errors.\n";
# COMPARE RESULTS
@@ -92,8 +92,9 @@ close(MAKEFILE);
&run_make_with_options($makefile2, "-k", &get_logfile, $error_code);
$answer = "exit 1
+$makefile2:9: recipe for target 'foo.o' failed
$make_name: *** [foo.o] Error 1
-$make_name: Target `all' not remade because of errors.\n";
+$make_name: Target 'all' not remade because of errors.\n";
&compare_output($answer, &get_logfile(1));
@@ -106,8 +107,8 @@ ifile: no-such-file; @false
',
'-k',
"#MAKEFILE#:2: ifile: No such file or directory
-#MAKE#: *** No rule to make target `no-such-file', needed by `ifile'.
-#MAKE#: Failed to remake makefile `ifile'.
+#MAKE#: *** No rule to make target 'no-such-file', needed by 'ifile'.
+#MAKE#: Failed to remake makefile 'ifile'.
hi\n",
512);
diff --git a/tests/scripts/options/dash-n b/tests/scripts/options/dash-n
index de19f42..dfed419 100644
--- a/tests/scripts/options/dash-n
+++ b/tests/scripts/options/dash-n
@@ -3,37 +3,24 @@ $description = "Test the -n option.\n";
$details = "Try various uses of -n and ensure they all give the correct results.\n";
-open(MAKEFILE, "> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE <<'EOMAKE';
+touch('orig');
+run_make_test(q!
final: intermediate ; echo >> $@
intermediate: orig ; echo >> $@
-
-EOMAKE
-
-close(MAKEFILE);
-
-&touch('orig');
-
-# TEST 0
-
-&run_make_with_options($makefile, "", &get_logfile);
-$answer = "echo >> intermediate\necho >> final\n";
-&compare_output($answer, &get_logfile(1));
+!,
+ '', "echo >> intermediate\necho >> final\n");
# TEST 1
-&run_make_with_options($makefile, "-Worig -n", &get_logfile);
-$answer = "echo >> intermediate\necho >> final\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, '-Worig -n', "echo >> intermediate\necho >> final\n");
-unlink('orig', 'intermediate', 'final');
+rmfiles(qw(orig intermediate final));
# We consider the actual updated timestamp of targets with all
-# recursive commands, even with -n.
+# recursive commands, even with -n. Switching this to the new model
+# is non-trivial because we use a trick below to change the log content
+# before we compare it ...
$makefile2 = &get_tmpfile;
@@ -56,15 +43,58 @@ close(MAKEFILE);
# TEST 2
&run_make_with_options($makefile2, "", &get_logfile);
-$answer = "$make_name: `a' is up to date.\n";
+$answer = "$make_name: 'a' is up to date.\n";
&compare_output($answer, &get_logfile(1));
# TEST 3
&run_make_with_options($makefile2, "-n", &get_logfile);
-$answer = "$make_name: `a' is up to date.\n";
+$answer = "$make_name: 'a' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 4
+
+unlink(qw(a b));
+
+&run_make_with_options($makefile2, "-t -n", &get_logfile);
+
+open(DASH_N_LOG, ">>" . &get_logfile(1));
+print DASH_N_LOG "a exists but should not!\n" if -e 'a';
+print DASH_N_LOG "b exists but should not!\n" if -e 'b';
+close(DASH_N_LOG);
+
+&compare_output("touch b\ntouch a\n", &get_logfile(1));
+
+# CLEANUP
+
+unlink(qw(a b c));
+
+# Ensure -n continues to be included with recursive/re-execed make
+# See Savannah bug #38051
+
+$topmake = &get_tmpfile;
+$submake = &get_tmpfile;
+
+open(MAKEFILE, "> $topmake");
+print MAKEFILE <<"EOF";
+foo: ; \@\$(MAKE) -f "$submake" bar
+EOF
+close(MAKEFILE);
+
+
+# The bar target should print what would happen, but not actually run
+open(MAKEFILE, "> $submake");
+print MAKEFILE <<'EOF';
+inc: ; touch $@
+-include inc
+bar: ; @echo $(strip $(MAKEFLAGS))
+EOF
+close(MAKEFILE);
+
+&run_make_with_options($topmake, '-n --no-print-directory', &get_logfile);
+$answer = "$make_path -f \"$submake\" bar\ntouch inc\necho n --no-print-directory\n";
&compare_output($answer, &get_logfile(1));
-unlink('a', 'b', 'c');
+unlink('inc');
1;
diff --git a/tests/scripts/options/eval b/tests/scripts/options/eval
index 06a035c..0f82409 100644
--- a/tests/scripts/options/eval
+++ b/tests/scripts/options/eval
@@ -16,4 +16,14 @@ recurse: ; @$(MAKE) -f #MAKEFILE# && echo recurse!,
run_make_test(undef, '--no-print-directory --eval=\$\(info\ eval\) recurse',
"eval\neval\nall\nrecurse");
+# Make sure that --eval is handled correctly during restarting
+run_make_test(q!
+all: ; @echo $@
+-include gen.mk
+gen.mk: ; @echo > $@
+!,
+ '--eval=\$\(info\ eval\)', "eval\neval\nall");
+
+unlink('gen.mk');
+
1;
diff --git a/tests/scripts/options/print-directory b/tests/scripts/options/print-directory
new file mode 100644
index 0000000..a05bbee
--- /dev/null
+++ b/tests/scripts/options/print-directory
@@ -0,0 +1,33 @@
+# -*-perl-*-
+
+$description = "Test the -w option to GNU make.";
+
+# Simple test without -w
+run_make_test(q!
+all: ; @echo hi
+!,
+ "", "hi\n");
+
+# Simple test with -w
+run_make_test(undef, "-w",
+ "#MAKE#: Entering directory '#PWD#'\nhi\n#MAKE#: Leaving directory '#PWD#'\n");
+
+# Test makefile rebuild to ensure no enter/leave
+run_make_test(q!
+include foo
+all: ;@:
+foo: ; touch foo
+!,
+ "", "#MAKEFILE#:2: foo: No such file or directory\ntouch foo\n");
+unlink('foo');
+
+# Test makefile rebuild with -w
+run_make_test(q!
+include foo
+all: ;@:
+foo: ; touch foo
+!,
+ "-w", "#MAKE#: Entering directory '#PWD#'\n#MAKEFILE#:2: foo: No such file or directory\ntouch foo\n#MAKE#: Leaving directory '#PWD#'\n");
+unlink('foo');
+
+1;
diff --git a/tests/scripts/options/symlinks b/tests/scripts/options/symlinks
index 40d2564..a1bfce0 100644
--- a/tests/scripts/options/symlinks
+++ b/tests/scripts/options/symlinks
@@ -26,7 +26,7 @@ if ($port_type eq 'W32' || !( eval { symlink("",""); 1 })) {
# Without -L, nothing should happen
# With -L, it should update targ
run_make_test('targ: sym ; @echo make $@ from $<', '',
- "#MAKE#: `targ' is up to date.");
+ "#MAKE#: 'targ' is up to date.");
run_make_test(undef, '-L', "make targ from sym");
# Now update dep; in all cases targ should be out of date.
@@ -36,8 +36,8 @@ if ($port_type eq 'W32' || !( eval { symlink("",""); 1 })) {
# Now update targ; in all cases targ should be up to date.
&touch('targ');
- run_make_test(undef, '', "#MAKE#: `targ' is up to date.");
- run_make_test(undef, '-L', "#MAKE#: `targ' is up to date.");
+ run_make_test(undef, '', "#MAKE#: 'targ' is up to date.");
+ run_make_test(undef, '-L', "#MAKE#: 'targ' is up to date.");
# Add in a new link between sym and dep. Be sure it's newer than targ.
sleep(1);
@@ -46,7 +46,7 @@ if ($port_type eq 'W32' || !( eval { symlink("",""); 1 })) {
# Without -L, nothing should happen
# With -L, it should update targ
- run_make_test(undef, '', "#MAKE#: `targ' is up to date.");
+ run_make_test(undef, '', "#MAKE#: 'targ' is up to date.");
run_make_test(undef, '-L', "make targ from sym");
rmfiles('targ', 'dep', 'sym', 'dep1');
@@ -56,7 +56,7 @@ if ($port_type eq 'W32' || !( eval { symlink("",""); 1 })) {
symlink("../$dirname/dep", 'sym');
run_make_test('targ: sym ; @echo make $@ from $<', '',
- "#MAKE#: *** No rule to make target `sym', needed by `targ'. Stop.", 512);
+ "#MAKE#: *** No rule to make target 'sym', needed by 'targ'. Stop.", 512);
run_make_test('targ: sym ; @echo make $@ from $<', '-L',
'make targ from sym');
diff --git a/tests/scripts/options/warn-undefined-variables b/tests/scripts/options/warn-undefined-variables
index 34bfaea..ce15507 100644
--- a/tests/scripts/options/warn-undefined-variables
+++ b/tests/scripts/options/warn-undefined-variables
@@ -18,8 +18,8 @@ all: ; @echo ref $(EREF) $(UREF)',
# With --warn-undefined-variables, it should warn me
run_make_test(undef, '--warn-undefined-variables',
- "#MAKEFILE#:7: warning: undefined variable `UNDEFINED'
-#MAKEFILE#:9: warning: undefined variable `UNDEFINED'
+ "#MAKEFILE#:7: warning: undefined variable 'UNDEFINED'
+#MAKEFILE#:9: warning: undefined variable 'UNDEFINED'
ref");
1;
diff --git a/tests/scripts/targets/DEFAULT b/tests/scripts/targets/DEFAULT
index 0cabde9..f3d5148 100644
--- a/tests/scripts/targets/DEFAULT
+++ b/tests/scripts/targets/DEFAULT
@@ -35,9 +35,9 @@ close(MAKEFILE);
&run_make_with_options($makefile,'bar',&get_logfile);
# Create the answer to what should be produced by this Makefile
-$answer = "${make_name}[1]: Entering directory `$pwd'\n"
+$answer = "${make_name}[1]: Entering directory '$pwd'\n"
. "Executing rule BAR\n"
- . "${make_name}[1]: Leaving directory `$pwd'\n";
+ . "${make_name}[1]: Leaving directory '$pwd'\n";
# COMPARE RESULTS
diff --git a/tests/scripts/targets/INTERMEDIATE b/tests/scripts/targets/INTERMEDIATE
index 4fdd7a2..2b3021b 100644
--- a/tests/scripts/targets/INTERMEDIATE
+++ b/tests/scripts/targets/INTERMEDIATE
@@ -42,7 +42,7 @@ $answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n";
# TEST #1
&run_make_with_options($makefile,'foo.d',&get_logfile);
-$answer = "$make_name: `foo.d' is up to date.\n";
+$answer = "$make_name: 'foo.d' is up to date.\n";
&compare_output($answer, &get_logfile(1));
# TEST #2
@@ -63,7 +63,7 @@ $answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm bar.e foo
# TEST #4
&run_make_with_options($makefile,'foo.c',&get_logfile);
-$answer = "$make_name: `foo.c' is up to date.\n";
+$answer = "$make_name: 'foo.c' is up to date.\n";
&compare_output($answer, &get_logfile(1));
# TEST #5
diff --git a/tests/scripts/targets/ONESHELL b/tests/scripts/targets/ONESHELL
index 997423f..87713da 100644
--- a/tests/scripts/targets/ONESHELL
+++ b/tests/scripts/targets/ONESHELL
@@ -4,6 +4,10 @@ $description = "Test the behaviour of the .ONESHELL target.";
$details = "";
+# Some shells (*shakes fist at Solaris*) cannot handle multiple flags in
+# separate arguments.
+my $t = `/bin/sh -e -c true 2>/dev/null`;
+my $multi_ok = $? == 0;
# Simple
@@ -17,6 +21,21 @@ all:
[ 0"$a" -eq "$$" ] || echo fail
');
+# Simple but use multi-word SHELLFLAGS
+
+if ($multi_ok) {
+ run_make_test(q!
+.ONESHELL:
+.SHELLFLAGS = -e -c
+all:
+ a=$$$$
+ [ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+ '', 'a=$$
+[ 0"$a" -eq "$$" ] || echo fail
+');
+}
+
# Again, but this time with inner prefix chars
run_make_test(q!
diff --git a/tests/scripts/targets/POSIX b/tests/scripts/targets/POSIX
index 9c30e18..a24e3bc 100644
--- a/tests/scripts/targets/POSIX
+++ b/tests/scripts/targets/POSIX
@@ -1,6 +1,6 @@
# -*-perl-*-
-$description = "Test the behaviour of the .PHONY target.";
+$description = "Test the behaviour of the .POSIX target.";
$details = "";
@@ -17,7 +17,8 @@ run_make_test(qq!
.POSIX:
all: ; \@$script
!,
- '', "#MAKE#: *** [all] Error $err\n", 512);
+ '', "#MAKEFILE#:3: recipe for target 'all' failed
+#MAKE#: *** [all] Error $err\n", 512);
# User settings must override .POSIX
$flags = '-xc';
@@ -29,5 +30,28 @@ all: ; \@$script
!,
'', $out);
+# Test the default value of various POSIX-specific variables
+my %POSIX = (AR => 'ar', ARFLAGS => '-rv',
+ YACC => 'yacc', YFLAGS => '',
+ LEX => 'lex', LFLAGS => '',
+ LDFLAGS => '',
+ CC => 'c99', CFLAGS => '-O',
+ FC => 'fort77', FFLAGS => '-O 1',
+ GET => 'get', GFLAGS => '',
+ SCCSFLAGS => '', SCCSGETFLAGS => '-s');
+my $make = join('', map { "\t\@echo '$_=\$($_)'\n" } sort keys %POSIX);
+my $r = join('', map { "$_=$POSIX{$_}\n"} sort keys %POSIX);
+run_make_test(qq!
+.POSIX:
+all:
+$make
+!,
+ '', $r);
+
+# Make sure that local settings take precedence
+%extraENV = map { $_ => "xx-$_" } keys %POSIX;
+$r = join('', map { "$_=xx-$_\n"} sort keys %POSIX);
+run_make_test(undef, '', $r);
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/targets/SECONDARY b/tests/scripts/targets/SECONDARY
index c954ee9..447c275 100644
--- a/tests/scripts/targets/SECONDARY
+++ b/tests/scripts/targets/SECONDARY
@@ -44,7 +44,7 @@ $answer = "cp foo.f foo.e\ncp foo.e foo.d\n";
unlink('foo.e');
&run_make_with_options($makefile,'foo.d',&get_logfile);
-$answer = "$make_name: `foo.d' is up to date.\n";
+$answer = "$make_name: 'foo.d' is up to date.\n";
&compare_output($answer, &get_logfile(1));
# TEST #3
@@ -67,7 +67,7 @@ $answer = "cp foo.e foo.c\n";
unlink('foo.e');
&run_make_with_options($makefile,'foo.c',&get_logfile);
-$answer = "$make_name: `foo.c' is up to date.\n";
+$answer = "$make_name: 'foo.c' is up to date.\n";
&compare_output($answer, &get_logfile(1));
# TEST #6
@@ -103,7 +103,7 @@ close(MAKEFILE);
touch('final');
&run_make_with_options($makefile2, '', &get_logfile);
-$answer = "$make_name: `final' is up to date.\n";
+$answer = "$make_name: 'final' is up to date.\n";
&compare_output($answer, &get_logfile(1));
unlink('source', 'final', 'intermediate');
@@ -129,10 +129,11 @@ touch(qw(1.a 2.a));
run_make_test('
%.c : %.b ; cp $< $@
%.b : %.a ; cp $< $@
-all : 1.c 2.c', '-rR -j',
+all : 1.c 2.c
+2.a: 1.c', '-rR -j',
'cp 1.a 1.b
-cp 2.a 2.b
cp 1.b 1.c
+cp 2.a 2.b
cp 2.b 2.c
rm 1.b 2.b');
diff --git a/tests/scripts/variables/DEFAULT_GOAL b/tests/scripts/variables/DEFAULT_GOAL
index 1c06506..8188ce7 100644
--- a/tests/scripts/variables/DEFAULT_GOAL
+++ b/tests/scripts/variables/DEFAULT_GOAL
@@ -42,7 +42,7 @@ run_make_test('
.DEFAULT_GOAL = foo
',
'',
-'#MAKE#: *** No rule to make target `foo\'. Stop.',
+"#MAKE#: *** No rule to make target 'foo'. Stop.",
512);
diff --git a/tests/scripts/variables/GNUMAKEFLAGS b/tests/scripts/variables/GNUMAKEFLAGS
new file mode 100644
index 0000000..e9c0d55
--- /dev/null
+++ b/tests/scripts/variables/GNUMAKEFLAGS
@@ -0,0 +1,42 @@
+# -*-perl-*-
+
+$description = "Test proper behavior of GNUMAKEFLAGS";
+
+# Accept flags from GNUMAKEFLAGS as well as MAKEFLAGS
+# Results always go in MAKEFLAGS
+
+$extraENV{'GNUMAKEFLAGS'} = '-e -r -R';
+
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+ '', 'erR');
+
+# Long arguments mean everything is prefixed with "-"
+
+$extraENV{'GNUMAKEFLAGS'} = '--no-print-directory -e -r -R --trace';
+
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+ '', "#MAKEFILE#:2: target 'all' does not exist
+echo erR --trace --no-print-directory
+erR --trace --no-print-directory");
+
+# Verify that re-exec / recursion doesn't duplicate flags from GNUMAKEFLAGS
+
+unlink('x.mk');
+
+$extraENV{GNUMAKEFLAGS} = '-Itst/bad -Oline';
+
+run_make_test(q!
+recurse: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; #MAKEPATH# -f #MAKEFILE# all
+all: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS
+-include x.mk
+x.mk: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; echo > $@
+!,
+ "", "x.mk\nMAKEFLAGS = -Itst/bad -Oline\nGNUMAKEFLAGS =\nrecurse\nMAKEFLAGS = -Itst/bad -Oline\nGNUMAKEFLAGS =\n#MAKE#[1]: Entering directory '#PWD#'\nall\nMAKEFLAGS = w -Itst/bad -Oline\nGNUMAKEFLAGS =\n#MAKE#[1]: Leaving directory '#PWD#'\n");
+
+unlink('x.mk');
+
+1;
diff --git a/tests/scripts/variables/LIBPATTERNS b/tests/scripts/variables/LIBPATTERNS
index 826f2fa..9182954 100644
--- a/tests/scripts/variables/LIBPATTERNS
+++ b/tests/scripts/variables/LIBPATTERNS
@@ -20,7 +20,7 @@ run_make_test('
.LIBPATTERNS = mtest_foo.a mtest_%.a
all: -lfoo ; @echo "build $@ from $<"
',
- '', "#MAKE#: .LIBPATTERNS element `mtest_foo.a' is not a pattern
+ '', "#MAKE#: .LIBPATTERNS element 'mtest_foo.a' is not a pattern
build all from mtest_foo.a\n");
# TEST 2: target-specific override
diff --git a/tests/scripts/variables/MAKE b/tests/scripts/variables/MAKE
index d1081da..dc62160 100644
--- a/tests/scripts/variables/MAKE
+++ b/tests/scripts/variables/MAKE
@@ -16,8 +16,8 @@ foo:
!,
'',
"#MAKEPATH#\n#MAKEPATH# -f #MAKEFILE# foo\n"
- . "#MAKE#[1]: Entering directory `#PWD#'\n"
- . "#MAKEPATH#\n#MAKE#[1]: Leaving directory `#PWD#'\n");
+ . "#MAKE#[1]: Entering directory '#PWD#'\n"
+ . "#MAKEPATH#\n#MAKE#[1]: Leaving directory '#PWD#'\n");
rmfiles("foo");
diff --git a/tests/scripts/variables/MAKEFLAGS b/tests/scripts/variables/MAKEFLAGS
index 0b567e8..8a5d0f6 100644
--- a/tests/scripts/variables/MAKEFLAGS
+++ b/tests/scripts/variables/MAKEFLAGS
@@ -1,4 +1,4 @@
-# -*-perl-*-
+# -*-perl-*-
$description = "Test proper behavior of MAKEFLAGS";
@@ -8,36 +8,34 @@ $details = "DETAILS";
run_make_test(q!
all: ; @echo $(MAKEFLAGS)
!,
- '-e -r -R', 'Rre');
+ '-e -r -R', 'erR');
# Long arguments mean everything is prefixed with "-"
run_make_test(q!
all: ; @echo $(MAKEFLAGS)
!,
- '--no-print-directory -e -r -R', '--no-print-directory -Rre');
+ '--no-print-directory -e -r -R --trace', "#MAKEFILE#:2: target 'all' does not exist
+echo erR --trace --no-print-directory
+erR --trace --no-print-directory");
-if ($all_tests) {
- # Recursive invocations of make should accumulate MAKEFLAGS values.
- # Savannah bug #2216
- run_make_test(q!
+# Recursive invocations of make should accumulate MAKEFLAGS values.
+# Savannah bug #2216
+run_make_test(q!
MSG = Fails
all:
@echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
@MSG=Works $(MAKE) -e -f #MAKEFILE# jump
jump:
- @echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
+ @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'
@$(MAKE) -f #MAKEFILE# print
print:
- @echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
- @echo $(MSG)
+ @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'
.PHONY: all jump print
!,
'--no-print-directory',
'all: MAKEFLAGS= --no-print-directory
-jump: MAKEFLAGS= --no-print-directory -e
-print: MAKEFLAGS= --no-print-directory -e
-Works');
-}
+jump Works: MAKEFLAGS=e --no-print-directory
+print Works: MAKEFLAGS=e --no-print-directory');
1;
diff --git a/tests/scripts/variables/MAKE_RESTARTS b/tests/scripts/variables/MAKE_RESTARTS
index 53ab738..ef8e368 100644
--- a/tests/scripts/variables/MAKE_RESTARTS
+++ b/tests/scripts/variables/MAKE_RESTARTS
@@ -52,10 +52,10 @@ MAKE_RESTARTS=1
foo.x:1: bar.x: No such file or directory
MAKE_RESTARTS=2
recurse MAKE_RESTARTS=
+#MAKE#[1]: Entering directory '#PWD#'
MAKE_RESTARTS=
-#MAKE#[1]: Entering directory `#PWD#'
all MAKE_RESTARTS=
-#MAKE#[1]: Leaving directory `#PWD#'");
+#MAKE#[1]: Leaving directory '#PWD#'");
rmfiles('foo.x', 'bar.x');
diff --git a/tests/scripts/variables/SHELL b/tests/scripts/variables/SHELL
index 7b7e7fe..1d01ba3 100644
--- a/tests/scripts/variables/SHELL
+++ b/tests/scripts/variables/SHELL
@@ -70,6 +70,22 @@ all: ; \@$script
!,
'', $out);
+# Do it again but add spaces to SHELLFLAGS
+
+# Some shells (*shakes fist at Solaris*) cannot handle multiple flags in
+# separate arguments.
+my $t = `/bin/sh -e -c true 2>/dev/null`;
+my $multi_ok = $? == 0;
+
+if ($multi_ok) {
+ $flags = '-x -c';
+ run_make_test(qq!
+.SHELLFLAGS = $flags
+all: ; \@$script
+!,
+ '', $out);
+}
+
# We can't just use "false" because on different systems it provides a
# different exit code--once again Solaris: false exits with 255 not 1
$script = 'true; false; true';
@@ -81,6 +97,7 @@ run_make_test(qq!
.SHELLFLAGS = $flags
all: ; \@$script
!,
- '', "$out#MAKE#: *** [all] Error $err\n", 512);
+ '', "$out#MAKEFILE#:3: recipe for target 'all' failed
+#MAKE#: *** [all] Error $err\n", 512);
1;
diff --git a/tests/scripts/variables/define b/tests/scripts/variables/define
index f91519e..7324cbc 100644
--- a/tests/scripts/variables/define
+++ b/tests/scripts/variables/define
@@ -30,6 +30,10 @@ define simple :=
@echo $(FOO)
endef
+define posix ::=
+@echo $(FOO)
+endef
+
append = @echo a
define append +=
@@ -49,10 +53,54 @@ FOO = there
all: ; $(multi)
$(simple)
+ $(posix)
+ $(append)
+ $(cond)
+',
+ '', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n");
+
+# TEST 1a: Various new-style define/endef, with no spaces
+
+run_make_test('
+FOO = foo
+
+define multi=
+echo hi
+@echo $(FOO)
+endef # this is the end
+
+define simple:=
+@echo $(FOO)
+endef
+
+define posix::=
+@echo $(FOO)
+endef
+
+append = @echo a
+
+define append+=
+
+@echo b
+endef
+
+define cond?= # this is a conditional
+@echo first
+endef
+
+define cond?=
+@echo second
+endef
+
+FOO = there
+
+all: ; $(multi)
+ $(simple)
+ $(posix)
$(append)
$(cond)
',
- '', "echo hi\nhi\nthere\nfoo\na\nb\nfirst\n");
+ '', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n");
# TEST 2: define in true section of conditional (containing conditional)
@@ -112,7 +160,7 @@ ouch
endef
all: ; @echo ok
',
- '', "#MAKEFILE#:3: extraneous text after `define' directive\nok\n");
+ '', "#MAKEFILE#:3: extraneous text after 'define' directive\nok\n");
# TEST 7: NEGATIVE: extra text after endef
@@ -123,7 +171,7 @@ ouch
endef $(NAME)
all: ; @echo ok
',
- '', "#MAKEFILE#:5: extraneous text after `endef' directive\nok\n");
+ '', "#MAKEFILE#:5: extraneous text after 'endef' directive\nok\n");
# TEST 8: NEGATIVE: missing endef
@@ -134,7 +182,7 @@ define NAME =
ouch
endef$(NAME)
',
- '', "#MAKEFILE#:4: *** missing `endef', unterminated `define'. Stop.\n", 512);
+ '', "#MAKEFILE#:4: *** missing 'endef', unterminated 'define'. Stop.\n", 512);
# -------------------------
# Make sure that prefix characters apply properly to define/endef values.
diff --git a/tests/scripts/variables/flavors b/tests/scripts/variables/flavors
index 92feed6..ba133ea 100644
--- a/tests/scripts/variables/flavors
+++ b/tests/scripts/variables/flavors
@@ -73,4 +73,24 @@ all: ; @echo $(foo)
',
'', "Hello\n");
+# TEST 6: Simple using POSIX syntax
+run_make_test('
+bar = Goodbye
+foo ::= $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Goodbye\n");
+
+# TEST 7: POSIX syntax no spaces
+run_make_test('
+bar = Goodbye
+foo::=$(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Goodbye\n");
+
1;
diff --git a/tests/scripts/variables/private b/tests/scripts/variables/private
index b4baf5f..8967ffb 100644
--- a/tests/scripts/variables/private
+++ b/tests/scripts/variables/private
@@ -75,4 +75,48 @@ a b: ; @echo $@=$(private)
',
'', "b=a\na=a\n");
+# 9: make sure private suppresses inheritance
+run_make_test(q!
+DEFS = FOO
+all: bar1
+bar1: private DEFS += 1
+bar3: private DEFS += 3
+bar1: bar2
+bar2: bar3
+bar1 bar2 bar3: ; @echo '$@: $(DEFS)'
+!,
+ '', "bar3: FOO 3\nbar2: FOO\nbar1: FOO 1\n");
+
+# 10: Test append with pattern-specific variables and private
+
+run_make_test(q!
+IA = global
+PA = global
+PS = global
+S = global
+PS = global
+SV = global
+b%: IA += b%
+b%: private PA += b%
+b%: private PS = b%
+bar: all
+bar: IA += bar
+bar: private PA += bar
+bar: private PS = bar
+a%: IA += a%
+a%: private PA += a%
+a%: private PS = a%
+all: IA += all
+all: private PA += all
+all: private PS = all
+
+bar all: ; @echo '$@: IA=$(IA)'; echo '$@: PA=$(PA)'; echo '$@: PS=$(PS)'
+!,
+ '', "all: IA=global b% bar a% all
+all: PA=global a% all
+all: PS=all
+bar: IA=global b% bar
+bar: PA=global b% bar
+bar: PS=bar\n");
+
1;
diff --git a/tests/scripts/variables/special b/tests/scripts/variables/special
index a1e15c2..4637b2a 100644
--- a/tests/scripts/variables/special
+++ b/tests/scripts/variables/special
@@ -53,7 +53,7 @@ all:
# Test the .RECIPEPREFIX variable
&run_make_test('
define foo
-: foo-one \
+: foo-one\
foo-two
: foo-three
: foo-four