diff options
author | Kévin THIERRY <kevin.thierry@open.eurogiciel.org> | 2014-11-05 08:27:15 +0100 |
---|---|---|
committer | Kévin THIERRY <kevin.thierry@open.eurogiciel.org> | 2014-11-05 08:27:15 +0100 |
commit | e15597c3e85dedc015ff923a88febd46a1551f71 (patch) | |
tree | 467fdb092d1fa76bcb63d4db653e8176dae24e62 /tests/scripts | |
parent | 9789b4dba120180760ec948089fc98ebab6eb28b (diff) | |
download | make-e15597c3e85dedc015ff923a88febd46a1551f71.tar.gz make-e15597c3e85dedc015ff923a88febd46a1551f71.tar.bz2 make-e15597c3e85dedc015ff923a88febd46a1551f71.zip |
Imported Upstream version 4.0upstream/4.0sandbox/kevinthierry/upstream
Diffstat (limited to 'tests/scripts')
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 |