summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorTizenOpenSource <tizenopensrc@samsung.com>2023-01-09 12:00:19 +0900
committerTizenOpenSource <tizenopensrc@samsung.com>2023-01-09 12:00:19 +0900
commit575596137b326da0fb261d4c19abe44c172b0cb7 (patch)
treed979d5d65b28cf65628a9c59be4396612d7c587e /tests
parentb11e2699c7ec42e6d2fc0f4c940f14e7c89b3974 (diff)
downloadmake-upstream.tar.gz
make-upstream.tar.bz2
make-upstream.zip
Imported Upstream version 4.4upstream/4.4upstream
Diffstat (limited to 'tests')
-rw-r--r--tests/README56
-rwxr-xr-xtests/config_flags_pm.com4
-rwxr-xr-xtests/mkshadow4
-rw-r--r--tests/run_make_tests.bat4
-rw-r--r--tests/run_make_tests.pl181
-rw-r--r--tests/scripts/features/archives7
-rw-r--r--tests/scripts/features/default_names2
-rw-r--r--tests/scripts/features/dircache31
-rw-r--r--tests/scripts/features/double_colon150
-rw-r--r--tests/scripts/features/errors29
-rw-r--r--tests/scripts/features/exec29
-rw-r--r--tests/scripts/features/export42
-rw-r--r--tests/scripts/features/grouped_targets74
-rw-r--r--tests/scripts/features/implicit_search483
-rw-r--r--tests/scripts/features/include270
-rw-r--r--tests/scripts/features/jobserver97
-rw-r--r--tests/scripts/features/load54
-rw-r--r--tests/scripts/features/loadapi103
-rw-r--r--tests/scripts/features/mult_rules22
-rw-r--r--tests/scripts/features/output-sync33
-rw-r--r--tests/scripts/features/parallelism95
-rw-r--r--tests/scripts/features/patternrules550
-rw-r--r--tests/scripts/features/reinvoke118
-rw-r--r--tests/scripts/features/se_explicit305
-rw-r--r--tests/scripts/features/se_implicit240
-rw-r--r--tests/scripts/features/se_statpat133
-rw-r--r--tests/scripts/features/statipattrules208
-rw-r--r--tests/scripts/features/targetvars155
-rw-r--r--tests/scripts/features/temp_stdin118
-rw-r--r--tests/scripts/features/varnesting12
-rw-r--r--tests/scripts/features/vpath139
-rw-r--r--tests/scripts/features/vpath245
-rw-r--r--tests/scripts/features/vpath341
-rw-r--r--tests/scripts/features/vpathgpath4
-rw-r--r--tests/scripts/features/vpathplus97
-rw-r--r--tests/scripts/functions/eval2
-rw-r--r--tests/scripts/functions/file71
-rw-r--r--tests/scripts/functions/filter-out16
-rw-r--r--tests/scripts/functions/foreach4
-rw-r--r--tests/scripts/functions/intcmp72
-rw-r--r--tests/scripts/functions/let111
-rw-r--r--tests/scripts/functions/origin28
-rw-r--r--tests/scripts/functions/shell146
-rw-r--r--tests/scripts/functions/word102
-rw-r--r--tests/scripts/misc/bs-nl2
-rw-r--r--tests/scripts/misc/close_stdout2
-rw-r--r--tests/scripts/misc/fopen-fail4
-rw-r--r--tests/scripts/misc/general431
-rw-r--r--tests/scripts/options/dash-I123
-rw-r--r--tests/scripts/options/dash-d9
-rw-r--r--tests/scripts/options/dash-e17
-rw-r--r--tests/scripts/options/dash-f97
-rw-r--r--tests/scripts/options/dash-k5
-rw-r--r--tests/scripts/options/dash-l7
-rw-r--r--tests/scripts/options/dash-r44
-rw-r--r--tests/scripts/options/print-directory51
-rw-r--r--tests/scripts/options/shuffle128
-rw-r--r--tests/scripts/options/symlinks9
-rw-r--r--tests/scripts/targets/INTERMEDIATE84
-rw-r--r--tests/scripts/targets/NOTINTERMEDIATE119
-rw-r--r--tests/scripts/targets/ONESHELL51
-rw-r--r--tests/scripts/targets/POSIX4
-rw-r--r--tests/scripts/targets/WAIT193
-rw-r--r--tests/scripts/variables/GNUMAKEFLAGS22
-rw-r--r--tests/scripts/variables/INCLUDE_DIRS70
-rw-r--r--tests/scripts/variables/MAKEFLAGS143
-rw-r--r--tests/scripts/variables/MAKE_RESTARTS12
-rw-r--r--tests/scripts/variables/SHELL20
-rw-r--r--tests/scripts/variables/automatic26
-rw-r--r--tests/scripts/variables/define29
-rw-r--r--tests/scripts/variables/flavors44
-rw-r--r--tests/scripts/variables/negative14
-rw-r--r--tests/scripts/variables/undefine18
-rw-r--r--tests/test_driver.pl273
-rwxr-xr-xtests/thelp.pl9
75 files changed, 5143 insertions, 1004 deletions
diff --git a/tests/README b/tests/README
index aab3c35..6ffa19a 100644
--- a/tests/README
+++ b/tests/README
@@ -7,7 +7,7 @@ This entire test suite, including all test files, are copyright and
distributed under the following terms:
-----------------------------------------------------------------------------
- Copyright (C) 1992-2020 Free Software Foundation, Inc.
+ Copyright (C) 1992-2022 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@@ -23,10 +23,9 @@ distributed under the following terms:
this program. If not, see <http://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------
-The test suite requires Perl. These days, you should have at least Perl
-5.004 (available from ftp.gnu.org, and portable to many machines). It
-used to work with Perl 4.036 but official support for Perl 4.x was
-abandoned a long time ago, due to lack of testbeds, as well as interest.
+The test suite requires Perl. These days, you should have at least Perl 5.6.
+Newer versions may be required: I don't test regularly with older versions
+than what is installed by default on my development systems.
The test suite assumes that the first "diff" it finds on your PATH is
GNU diff, but that only matters if a test fails.
@@ -54,14 +53,6 @@ with your network or file server, not GNU make (I believe). This
shouldn't happen very often anymore: I've done a lot of work on the
tests to reduce the impacts of this situation.
-The options/dash-l test will not really test anything if the copy of
-make you are using can't obtain the system load. Some systems require
-make to be setgid sys or kmem for this; if you don't want to install
-make just to test it, make it setgid to kmem or whatever group /dev/kmem
-is (i.e., "chgrp kmem make;chmod g+s make" as root). In any case, the
-options/dash-l test should no longer *fail* because make can't read
-/dev/kmem.
-
A directory named "work" will be created when the tests are run which
will contain any makefiles and "diff" files of tests that fail so that
you may look at them afterward to see the output of make and the
@@ -74,28 +65,35 @@ other possible options for the test suite.
Open Issues
-----------
-The test suite has a number of problems which should be addressed. One
-VERY serious one is that there is no real documentation. You just have
-to see the existing tests. Use the newer tests: many of the tests
-haven't been updated to use the latest/greatest test methods. See the
-ChangeLog in the tests directory for pointers.
+The test suite has a number of problems which should be addressed. One VERY
+serious one is that there is no real documentation. You just have to see the
+existing tests. Use the newer tests: many of the tests haven't been updated
+to use the latest/greatest test methods. See the ChangeLogs for pointers.
+
+The second serious problem is that it's not relocatable: when you build out of
+the source tree it creates symlinks, which doesn't work on every system and is
+just bogus to boot.
+
+The third serious problem is that it's not parallelizable: it scribbles all
+over its installation directory and so can only test one make at a time.
+
+The fourth serious problem is that since the tests scribble all over the same
+directory (a) they can interfere with each other and (b) we cannot preserve
+the full environment for every test, if it involves creating temporary files
+etc. as they must be deleted before the next test.
-The second serious problem is that it's not parallelizable: it scribbles
-all over its installation directory and so can only test one make at a
-time. The third serious problem is that it's not relocatable: the only
-way it works when you build out of the source tree is to create
-symlinks, which doesn't work on every system and is bogus to boot. The
-fourth serious problem is that it doesn't create its own sandbox when
-running tests, so that if a test forgets to clean up after itself that
-can impact future tests.
+To solve these the suite should create a separate directory for EVERY test,
+local to the build directory, and all temporary files should exist in that
+directory. The directory can be preserved on error, or removed if the test
+succeeds (unless --keep is given).
Bugs
----
-Any complaints/suggestions/bugs/etc. for the test suite itself (as
-opposed to problems in make that the suite finds) should be handled the
-same way as normal GNU make bugs/problems (see the README for GNU make).
+Any complaints/suggestions/bugs/etc. for the test suite itself should be
+handled the same way as normal GNU make bugs/problems (see the README for GNU
+make).
Paul D. Smith
diff --git a/tests/config_flags_pm.com b/tests/config_flags_pm.com
index e7da8ca..d02ea66 100755
--- a/tests/config_flags_pm.com
+++ b/tests/config_flags_pm.com
@@ -3,7 +3,7 @@ $! config_flags_pm.com - Build config-flags.pm on VMS.
$!
$! Just good enough to run the self tests for now.
$!
-$! Copyright (C) 2014-2020 Free Software Foundation, Inc.
+$! Copyright (C) 2014-2022 Free Software Foundation, Inc.
$! This file is part of GNU Make.
$!
$! GNU Make is free software; you can redistribute it and/or modify it under
@@ -17,7 +17,7 @@ $! FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
$! details.
$!
$! You should have received a copy of the GNU General Public License along with
-$! this program. If not, see <http://www.gnu.org/licenses/>.
+$! this program. If not, see <https://www.gnu.org/licenses/>.
$!
$!
$ open/read cfpm_in config-flags.pm.in
diff --git a/tests/mkshadow b/tests/mkshadow
index e7533c8..4615aec 100755
--- a/tests/mkshadow
+++ b/tests/mkshadow
@@ -3,7 +3,7 @@
# Simple script to make a "shadow" test directory, using symbolic links.
# Typically you'd put the shadow in /tmp or another local disk
#
-# Copyright (C) 1992-2020 Free Software Foundation, Inc.
+# Copyright (C) 1992-2022 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@@ -17,7 +17,7 @@
# details.
#
# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>.
+# this program. If not, see <https://www.gnu.org/licenses/>.
case "$1" in
"") echo 'Usage: mkshadow <destdir>'; exit 1 ;;
diff --git a/tests/run_make_tests.bat b/tests/run_make_tests.bat
index 45ff930..b90b6e3 100644
--- a/tests/run_make_tests.bat
+++ b/tests/run_make_tests.bat
@@ -1,5 +1,5 @@
@echo off
-rem Copyright (C) 2017-2020 Free Software Foundation, Inc.
+rem Copyright (C) 2017-2022 Free Software Foundation, Inc.
rem This file is part of GNU Make.
rem
rem GNU Make is free software; you can redistribute it and/or modify it under
@@ -13,7 +13,7 @@ rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for.
rem more details.
rem
rem You should have received a copy of the GNU General Public License along
-rem with this program. If not, see <http://www.gnu.org/licenses/>.
+rem with this program. If not, see <https://www.gnu.org/licenses/>.
setlocal
cd "%~dp0"
diff --git a/tests/run_make_tests.pl b/tests/run_make_tests.pl
index d76e4f3..70dd182 100644
--- a/tests/run_make_tests.pl
+++ b/tests/run_make_tests.pl
@@ -11,7 +11,7 @@
# [-make <make prog>]
# (and others)
-# Copyright (C) 1992-2020 Free Software Foundation, Inc.
+# Copyright (C) 1992-2022 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@@ -25,7 +25,7 @@
# details.
#
# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>.
+# this program. If not, see <https://www.gnu.org/licenses/>.
# Add the working directory to @INC and load the test driver
use FindBin;
@@ -45,6 +45,10 @@ $cwdpath = cwd();
$has_POSIX = eval { require "POSIX.pm" };
%FEATURES = ();
+%DEFVARS = (
+ AR => undef,
+ CC => undef
+);
$valgrind = 0; # invoke make with valgrind
$valgrind_args = '';
@@ -104,61 +108,7 @@ $ERR_read_only_file = undef;
$ERR_unreadable_file = undef;
$ERR_nonexe_file = undef;
$ERR_exe_dir = undef;
-
-{
- use locale;
-
- my $loc = undef;
- if ($has_POSIX) {
- POSIX->import(qw(locale_h));
- # Windows has POSIX locale, but only LC_ALL not LC_MESSAGES
- $loc = POSIX::setlocale(&POSIX::LC_ALL);
- POSIX::setlocale(&POSIX::LC_ALL, 'C');
- }
-
- if (open(my $F, '<', 'file.none')) {
- print "Opened non-existent file! Skipping related tests.\n";
- } else {
- $ERR_no_such_file = "$!";
- }
-
- unlink('file.out');
- touch('file.out');
-
- chmod(0444, 'file.out');
- if (open(my $F, '>', 'file.out')) {
- print "Opened read-only file! Skipping related tests.\n";
- close($F);
- } else {
- $ERR_read_only_file = "$!";
- }
-
- $_ = `./file.out 2>/dev/null`;
- if ($? == 0) {
- print "Executed non-executable file! Skipping related tests.\n";
- } else {
- $ERR_nonexe_file = "$!";
- }
-
- $_ = `./. 2>/dev/null`;
- if ($? == 0) {
- print "Executed directory! Skipping related tests.\n";
- } else {
- $ERR_exe_dir = "$!";
- }
-
- chmod(0000, 'file.out');
- if (open(my $F, '<', 'file.out')) {
- print "Opened unreadable file! Skipping related tests.\n";
- close($F);
- } else {
- $ERR_unreadable_file = "$!";
- }
-
- unlink('file.out') or die "Failed to delete file.out: $!\n";
-
- $loc and POSIX::setlocale(&POSIX::LC_ALL, $loc);
-}
+$ERR_command_not_found = undef;
#$SIG{INT} = sub { print STDERR "Caught a signal!\n"; die @_; };
@@ -168,9 +118,9 @@ sub valid_option
if ($option =~ /^-make([-_]?path)?$/i) {
$make_path = shift @argv;
- if (!-f $make_path) {
+ if (! -f $make_path) {
print "$option $make_path: Not found.\n";
- exit 0;
+ exit 1;
}
return 1;
}
@@ -179,7 +129,7 @@ sub valid_option
$srcdir = shift @argv;
if (! -f File::Spec->catfile($srcdir, 'src', 'gnumake.h')) {
print "$option $srcdir: Not a valid GNU make source directory.\n";
- exit 0;
+ exit 1;
}
return 1;
}
@@ -234,6 +184,7 @@ sub subst_make_string
s/#MAKE#/$make_name/g;
s/#PERL#/$perl_name/g;
s/#PWD#/$cwdpath/g;
+ s/#WORK#/$workdir/g;
# If we're using a shell
s/#HELPER#/$perl_name $helptool/g;
return $_;
@@ -252,7 +203,7 @@ sub run_make_test
defined $old_makefile
or die "run_make_test(undef) invoked before run_make_test('...')\n";
$makefile = $old_makefile;
- } else {
+ } elsif ($makestring) {
if (! defined($makefile)) {
$makefile = &get_tmpfile();
}
@@ -306,7 +257,7 @@ sub create_command {
# Using a ref should be preferred as it's more portable but all the older
# invocations use strings.
sub run_make_with_options {
- my ($filename,$options,$logname,$expected_code,$timeout,@call) = @_;
+ my ($filename, $options, $logname, $expected_code, $timeout, @call) = @_;
@call = caller unless @call;
my $code;
my $command = create_command($options);
@@ -360,13 +311,8 @@ sub run_make_with_options {
$command = add_options($command, $options);
}
- my $cmdstr = ref($command) ? "'".join("' '", @$command)."'" : $command;
-
- if (@call) {
- $command_string = "#$call[1]:$call[2]\n$cmdstr\n";
- } else {
- $command_string = $cmdstr;
- }
+ my $cmdstr = cmd2str($command);
+ $command_string = "# $call[1]:$call[2]:\n$cmdstr\n";
if ($valgrind) {
print VALGRIND "\n\nExecuting: $cmdstr\n";
@@ -405,9 +351,9 @@ sub run_make_with_options {
}
if ($code != $expected_code) {
- print "Error running @make_command (expected $expected_code; got $code): $cmdstr\n";
+ print "Error running @make_command (expected $expected_code; got $code)\n$call[1]:$call[2]: $cmdstr\n";
$test_passed = 0;
- &create_file (&get_runfile, $command_string);
+ &create_file(get_runfile(), $command_string);
# If it's a SIGINT, stop here
if ($code & 127) {
print STDERR "\nCaught signal ".($code & 127)."!\n";
@@ -449,7 +395,7 @@ sub print_help
sub set_defaults
{
# $profile = 1;
- $testee = "GNU make";
+ $testee = "GNU Make";
$make_path = "make";
$tmpfilesuffix = "mk";
if ($port_type eq 'UNIX') {
@@ -459,6 +405,81 @@ sub set_defaults
} else {
$scriptsuffix = '.bat';
}
+
+ $ENV{LC_ALL} = $makeENV{LC_ALL};
+ $ENV{LANG} = $makeENV{LANG};
+ $ENV{LANGUAGE} = $makeENV{LANGUAGE};
+
+ use locale;
+
+ my $loc = undef;
+ if ($has_POSIX) {
+ POSIX->import(qw(locale_h));
+ # Windows has POSIX locale, but only LC_ALL not LC_MESSAGES
+ $loc = POSIX::setlocale(&POSIX::LC_ALL);
+ POSIX::setlocale(&POSIX::LC_ALL, 'C');
+ }
+
+ if (open(my $F, '<', 'file.none')) {
+ print "Opened non-existent file! Skipping related tests.\n";
+ } else {
+ $ERR_no_such_file = "$!";
+ }
+
+ unlink('file.out');
+ touch('file.out');
+
+ chmod(0444, 'file.out');
+ if (open(my $F, '>', 'file.out')) {
+ print "Opened read-only file! Skipping related tests.\n";
+ close($F);
+ } else {
+ $ERR_read_only_file = "$!";
+ }
+
+ $_ = `./file.out 2>&1`;
+ if ($? == 0) {
+ print "Executed non-executable file! Skipping related tests.\n";
+ } else {
+ $ERR_nonexe_file = "$!";
+ }
+
+ if ($^O =~ /cygwin/i) {
+ # For some reason the execute here gives a different answer than make's
+ print "Skipping directory execution on $^O\n";
+ } else {
+ $_ = `./. 2>&1`;
+ if ($? == 0) {
+ print "Executed directory! Skipping related tests.\n";
+ } else {
+ $ERR_exe_dir = "$!";
+ }
+ }
+
+ chmod(0000, 'file.out');
+ if (open(my $F, '<', 'file.out')) {
+ print "Opened unreadable file! Skipping related tests.\n";
+ close($F);
+ } else {
+ $ERR_unreadable_file = "$!";
+ }
+
+ unlink('file.out') or die "Failed to delete file.out: $!\n";
+
+ $_ = `/bin/sh -c 'bad-command 2>&1'`;
+ if ($? == 0) {
+ print "Invoked invalid file! Skipping related tests.\n";
+ } else {
+ chomp($_);
+ s/bad-command/#CMDNAME#/g;
+ $ERR_command_not_found = $_;
+ }
+
+ $loc and POSIX::setlocale(&POSIX::LC_ALL, $loc);
+
+ $ENV{LC_ALL} = $origENV{LC_ALL};
+ $ENV{LANG} = $origENV{LANG};
+ $ENV{LANGUAGE} = $origENV{LANGUAGE};
}
# This is no longer used: we import config-flags.pm instead
@@ -561,7 +582,7 @@ sub set_more_defaults
create_file('make.mk', 'all:;$(info $(MAKE))');
my $mk = `$make_path -sf make.mk`;
unlink('make.mk');
- chop $mk;
+ $mk =~ s/\r?\n$//;
$mk or die "FATAL ERROR: Cannot determine the value of \$(MAKE)\n";
$make_path = $mk;
}
@@ -571,7 +592,7 @@ sub set_more_defaults
create_file('shell.mk', 'all:;$(info $(SHELL))');
$sh_name = `$make_path -sf shell.mk`;
unlink('shell.mk');
- chop $sh_name;
+ $sh_name =~ s/\r?\n$//;
if (! $sh_name) {
print "Cannot determine shell\n";
$is_posix_sh = 0;
@@ -649,6 +670,18 @@ sub set_more_defaults
%FEATURES = map { $_ => 1 } split /\s+/, `$make_path -sf features.mk`;
unlink('features.mk');
+ # Find the default values for different built-in variables
+ my $s = "all:;\n";
+ foreach (keys %DEFVARS) {
+ $s .= "\$(info $_=\$($_))\n";
+ }
+ create_file('defvars.mk', $s);
+ foreach (split "\n", `$make_path -sf defvars.mk`) {
+ my @e = split /=/, $_, 2;
+ $DEFVARS{$e[0]} = $e[1];
+ }
+ unlink('defvars.mk');
+
# Set up for valgrind, if requested.
@make_command = ($make_path);
diff --git a/tests/scripts/features/archives b/tests/scripts/features/archives
index dcd38e5..809bf21 100644
--- a/tests/scripts/features/archives
+++ b/tests/scripts/features/archives
@@ -35,16 +35,17 @@ my $ar = get_config('AR') || 'ar';
my $redir = '2>&1';
$redir = '' if $osname eq 'VMS';
-my $arflags = 'rv';
+# This is the value from src/default.c
+my $arflags = $osname eq 'aix' ? '-Xany -rv' : '-rv';
my $arvar = "AR=$ar";
# Newer versions of binutils can be built with --enable-deterministic-archives
# which forces all timestamps (among other things) to always be 0, defeating
# GNU make's archive support. See if ar supports the U option to disable it.
unlink('libxx.a');
-$_ = `$ar U$arflags libxx.a a1.o $redir`;
+$_ = `$ar ${arflags}U libxx.a a1.o $redir`;
if ($? == 0) {
- $arflags = 'Urv';
+ $arflags = "${arflags}U";
$arvar = "$arvar ARFLAGS=$arflags";
}
diff --git a/tests/scripts/features/default_names b/tests/scripts/features/default_names
index 2e83880..3ecbaab 100644
--- a/tests/scripts/features/default_names
+++ b/tests/scripts/features/default_names
@@ -15,7 +15,7 @@ open(MAKEFILE,"> makefile");
print MAKEFILE "SECOND: ; \@echo It chose makefile\n";
close(MAKEFILE);
-# DOS/WIN32/MacOSX platforms are case-insensitive / case-preserving, so
+# DOS/W32/MacOSX platforms are case-insensitive / case-preserving, so
# Makefile is the same file as makefile. Just test what we can here.
my $case_sensitive = 0;
diff --git a/tests/scripts/features/dircache b/tests/scripts/features/dircache
new file mode 100644
index 0000000..e5e8469
--- /dev/null
+++ b/tests/scripts/features/dircache
@@ -0,0 +1,31 @@
+# -*-mode: perl-*-
+
+$description = "Test the directory cache behavior.";
+
+# The first wildcard should bring the entire directory into the cache Then we
+# create a new file "behind make's back" then see if the next wildcard detects
+# it.
+
+run_make_test(q!
+_orig := $(wildcard ./*)
+$(shell echo > anewfile)
+_new := $(wildcard ./*)
+$(info diff=$(filter-out $(_orig),$(_new)))
+all:;@:
+!,
+ '', "diff=./anewfile\n");
+
+rmfiles('anewfile');
+
+run_make_test(q!
+_orig := $(wildcard ./*)
+$(file >anewfile)
+_new := $(wildcard ./*)
+$(info diff=$(filter-out $(_orig),$(_new)))
+all:;@:
+!,
+ '', "diff=./anewfile\n");
+
+rmfiles('anewfile');
+
+1;
diff --git a/tests/scripts/features/double_colon b/tests/scripts/features/double_colon
index 58f126f..a039b0a 100644
--- a/tests/scripts/features/double_colon
+++ b/tests/scripts/features/double_colon
@@ -12,12 +12,9 @@ We test these features:
Then we do the same thing for parallel builds: double-colon
targets should always be built serially.";
-# The Contents of the MAKEFILE ...
-
-open(MAKEFILE,"> $makefile");
-
-print MAKEFILE <<'EOF';
+# TEST 0: A simple double-colon rule that isn't the goal target.
+run_make_test(q!
all: baz
foo:: f1.h ; @echo foo FIRST
@@ -38,37 +35,23 @@ f1.h f2.h: ; @echo $@
d :: ; @echo ok
d :: d ; @echo oops
-
-EOF
-
-close(MAKEFILE);
-
-# TEST 0: A simple double-colon rule that isn't the goal target.
-
-&run_make_with_options($makefile, "all", &get_logfile, 0);
-$answer = "aaa\nbbb\n";
-&compare_output($answer, &get_logfile(1));
+!,
+ "all", "aaa\nbbb\n");
# TEST 1: As above, in parallel
if ($parallel_jobs) {
- &run_make_with_options($makefile, "-j10 all", &get_logfile, 0);
- $answer = "aaa\nbbb\n";
- &compare_output($answer, &get_logfile(1));
+ run_make_test(undef, "-j10 all", "aaa\nbbb\n");
}
# TEST 2: A simple double-colon rule that is the goal target
-&run_make_with_options($makefile, "bar", &get_logfile, 0);
-$answer = "aaa\naaa done\nbbb\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "bar", "aaa\naaa done\nbbb\n");
# TEST 3: As above, in parallel
if ($parallel_jobs) {
- &run_make_with_options($makefile, "-j10 bar", &get_logfile, 0);
- $answer = "aaa\naaa done\nbbb\n";
- &compare_output($answer, &get_logfile(1));
+ run_make_test(undef, "-j10 bar", "aaa\naaa done\nbbb\n");
}
# TEST 4: Each double-colon rule is supposed to be run individually
@@ -76,16 +59,12 @@ if ($parallel_jobs) {
&utouch(-5, 'f2.h');
&touch('foo');
-&run_make_with_options($makefile, "foo", &get_logfile, 0);
-$answer = "f1.h\nfoo FIRST\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "foo", "f1.h\nfoo FIRST\n");
# TEST 5: Again, in parallel.
if ($parallel_jobs) {
- &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
- $answer = "f1.h\nfoo FIRST\n";
- &compare_output($answer, &get_logfile(1));
+ run_make_test(undef, "-j10 foo", "f1.h\nfoo FIRST\n");
}
# TEST 6: Each double-colon rule is supposed to be run individually
@@ -94,32 +73,24 @@ if ($parallel_jobs) {
unlink('f2.h');
&touch('foo');
-&run_make_with_options($makefile, "foo", &get_logfile, 0);
-$answer = "f2.h\nfoo SECOND\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "foo", "f2.h\nfoo SECOND\n");
# TEST 7: Again, in parallel.
if ($parallel_jobs) {
- &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
- $answer = "f2.h\nfoo SECOND\n";
- &compare_output($answer, &get_logfile(1));
+ run_make_test(undef, "-j10 foo", "f2.h\nfoo SECOND\n");
}
# TEST 8: Test circular dependency check; PR/1671
-&run_make_with_options($makefile, "d", &get_logfile, 0);
-$answer = "ok\n$make_name: Circular d <- d dependency dropped.\noops\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "d", "ok\n$make_name: Circular d <- d dependency dropped.\noops\n");
# TEST 8: I don't grok why this is different than the above, but it is...
#
# Hmm... further testing indicates this might be timing-dependent?
#
#if ($parallel_jobs) {
-# &run_make_with_options($makefile, "-j10 biz", &get_logfile, 0);
-# $answer = "aaa\ntwo\nbbb\n";
-# &compare_output($answer, &get_logfile(1));
+# run_make_test(undef, "-j10 biz", "aaa\ntwo\nbbb\n");
#}
unlink('foo','f1.h','f2.h');
@@ -133,16 +104,17 @@ unlink('foo','f1.h','f2.h');
&touch('two');
run_make_test('
+.RECIPEPREFIX = >
.PHONY: all
all: result
result:: one
- @echo $^ >>$@
- @echo $^
+> @echo $^ >>$@
+> @echo $^
result:: two
- @echo $^ >>$@
- @echo $^
+> @echo $^ >>$@
+> @echo $^
',
'',
@@ -161,23 +133,25 @@ a\ xb :: ; @echo two
# Test 11: SV 44742 : All double-colon rules should be run in parallel build.
-run_make_test('result :: 01
- @echo update
- @touch $@
+run_make_test('
+.RECIPEPREFIX = >
+result :: 01
+> @echo update
+> @touch $@
result :: 02
- @echo update
- @touch $@
+> @echo update
+> @touch $@
result :: 03
- @echo update
- @touch $@
+> @echo update
+> @touch $@
result :: 04
- @echo update
- @touch $@
+> @echo update
+> @touch $@
result :: 05
- @echo update
- @touch $@
+> @echo update
+> @touch $@
01 02 03 04 05:
- @touch 01 02 03 04 05
+> @touch 01 02 03 04 05
',
'-j10 result', "update\nupdate\nupdate\nupdate\nupdate\n");
@@ -186,14 +160,10 @@ unlink('result', '01', '02', '03', '04', '05');
# Test 12: SV 44742 : Double-colon rules with parallelism
run_make_test('
-root: all
- echo root
-all::
- echo all_one
-all:: 3
- echo all_two
-%:
- sleep $*
+root: all ; echo root
+all:: ; echo all_one
+all:: 3 ; echo all_two
+%: ; sleep $*
',
'-rs -j2 1 2 root', "all_one\nall_two\nroot\n");
@@ -212,9 +182,49 @@ FORCE:
unlink('joe-is-forced');
+# sv 60188.
+# Even though test.x is explicitly mentioned, terminal pattern rules still
+# apply only if the prerequisite exists.
+touch('hello.z');
+
+# subtest 1. test.x is explicitly mentioned.
+run_make_test(q!
+all: hello.z
+%.z:: test.x ; touch $@
+%.x: ;
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.z');
+
+# subtest 2. hello.x is derived from the stem.
+touch('hello.z');
+
+run_make_test(q!
+all: hello.z
+%.z:: %.x; touch $@
+%.x: ; touch $@
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.z');
+
+# subtest 3
+# hello.x is explicitly mentioned on an unrelated rule and thus is not an
+# intermediate file.
+# Terminal pattern rules do not apply anyway and there is no rule to built
+# 'hello.x'.
+touch('hello.z');
+run_make_test(q!
+all: hello.z
+%.z:: %.x; touch $@
+%.x: ;
+unrelated: hello.x
+!,
+ '', "#MAKE#: *** No rule to make target 'hello.x', needed by 'hello.z'. Stop.\n", 512);
+
+unlink('hello.z');
+
+
# This tells the test driver that the perl test script executed properly.
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/features/errors b/tests/scripts/features/errors
index f236d51..2cdaf31 100644
--- a/tests/scripts/features/errors
+++ b/tests/scripts/features/errors
@@ -31,6 +31,18 @@ all:
!,
'', "hi\nthere\n#MAKE#: *** [#MAKEFILE#:5: all] Error 1", 512);
+# Windows error look completely different :-/
+
+sub errors_getinfo
+{
+ my ($cmd, $args) = @_;
+ if ($port_type eq 'W32') {
+ return (2, "process_begin: CreateProcess(NULL, $cmd $args, ...) failed.\nmake (e=2): The system cannot find the file specified.");
+ }
+
+ return (127, "#MAKE#: $cmd: $ERR_no_such_file");
+}
+
# TEST #3
# -------
@@ -38,35 +50,36 @@ all:
my $unk = './foobarbazbozblat';
unlink($unk);
-my $err = $ERR_no_such_file;
-
+my ($ernum, $erstr) = errors_getinfo($unk, "xx yy");
run_make_test(qq!
one: ; -$unk xx yy
-!,
- 'one', "$unk xx yy\n#MAKE#: $unk: $err\n#MAKE#: [#MAKEFILE#:2: one] Error 127 (ignored)\n");
+!, 'one',
+ "$unk xx yy\n$erstr\n#MAKE#: [#MAKEFILE#:2: one] Error $ernum (ignored)\n");
# TEST #4
# -------
+($ernum, $erstr) = errors_getinfo($unk, "aa bb");
run_make_test(qq!
two: ; $unk aa bb
!, 'two -i',
- "$unk aa bb\n#MAKE#: $unk: $err\n#MAKE#: [#MAKEFILE#:2: two] Error 127 (ignored)\n");
+ "$unk aa bb\n$erstr\n#MAKE#: [#MAKEFILE#:2: two] Error $ernum (ignored)\n");
# TEST #5
# -------
run_make_test(undef, 'two',
- "$unk aa bb\n#MAKE#: $unk: $err\n#MAKE#: *** [#MAKEFILE#:2: two] Error 127\n", 512);
+ "$unk aa bb\n$erstr\n#MAKE#: *** [#MAKEFILE#:2: two] Error $ernum\n", 512);
# SV #56918 : Test the unknown command as the second recipe line
+($ernum, $erstr) = errors_getinfo($unk, "qq rr");
run_make_test(qq!
three:
\t\@echo one
\t$unk qq rr
!, 'three',
- "one\n$unk qq rr\n#MAKE#: $unk: $err\n#MAKE#: *** [#MAKEFILE#:4: three] Error 127\n", 512);
+ "one\n$unk qq rr\n$erstr\n#MAKE#: *** [#MAKEFILE#:4: three] Error $ernum\n", 512);
# Try failing due to non-executable file
@@ -86,7 +99,7 @@ if ($ERR_nonexe_file) {
# Try failing by "running" a directory
if ($ERR_exe_dir) {
- mkdir('sd', 0775);
+ mkdir('sd', 0775) or print "mkdir: sd: $!\n";
run_make_test(q!
PATH := .
diff --git a/tests/scripts/features/exec b/tests/scripts/features/exec
index 91181f4..f139cf8 100644
--- a/tests/scripts/features/exec
+++ b/tests/scripts/features/exec
@@ -3,40 +3,49 @@
use warnings;
my $description = "Test that make can execute binaries as well as scripts with"
- ." various shabangs and without a shebang";
+ ." various shabangs and without a shbang";
my $details = "The various shells that this test uses are the default"
." /bin/sh, \$SHELL and the perl interpreter that is"
." executing this test program. The shells are used for the value"
- ." of SHELL inside the test makefile and also as a shebang in the"
+ ." of SHELL inside the test makefile and also as a shbang in the"
." executed script. There is also a test which executes a script"
- ." that has no shebang.";
+ ." that has no shbang.";
# Only bother with this on UNIX systems
$port_type eq 'UNIX' or return -1;
+$^O =~ /cygwin/ and return -1;
+my @shbangs = ('', '#!/bin/sh', "#!$perl_name");
+my @shells = ('', 'SHELL=/bin/sh');
+
+# Try whatever shell the user has, as long as it's not a C shell.
+# The C shell is not usable with make, due to not correctly handling
+# file descriptors and possibly other issues.
my $usersh = $origENV{SHELL};
-my $answer = 'hello, world';
+if ($usersh !~ /csh/) {
+ push @shbangs, ("#!$usersh");
+ push @shells, ("SHELL=$usersh");
+}
-my @shebangs = ('', '#!/bin/sh', "#!$usersh", "#!$perl_name");
-my @shells = ('', 'SHELL=/bin/sh', "SHELL=$usersh");
+my $answer = 'hello, world';
# tests [0-11]
# Have a makefile with various SHELL= exec a shell program with varios
-# shebangs or without a shebang at all.
+# shbangs or without a shbang at all.
my $stem = './exec.cmd';
my $k = 0;
-for my $shebang (@shebangs) {
+for my $shbang (@shbangs) {
for my $shell (@shells) {
my $cmd = $k ? "$stem.$k" : $stem;
++$k;
unlink $cmd;
open(CMD,"> $cmd");
- print CMD "$shebang\n";
+ print CMD "$shbang\n";
print CMD "printf \"$answer\\n\";\n";
close(CMD);
chmod 0700, $cmd;
- run_make_test(q!
+ run_make_test("# shbang=$shbang\n# shell=$shell" . q!
all:; @$(CMD)
!, "$shell CMD=$cmd", "$answer\n");
diff --git a/tests/scripts/features/export b/tests/scripts/features/export
index 81bff0c..ad58177 100644
--- a/tests/scripts/features/export
+++ b/tests/scripts/features/export
@@ -32,16 +32,17 @@ ifdef EXPORT_ALL_PSEUDO
.EXPORT_ALL_VARIABLES:
endif
+.RECIPEPREFIX := >
all:
- @echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)"
- @echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ"
+> @echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)"
+> @echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ"
',
'', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
# TEST 1: make sure vars inherited from the parent are exported
-$extraENV{FOO} = 1;
+$ENV{FOO} = 1;
&run_make_test(undef, '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
@@ -85,9 +86,10 @@ B = b
export $(FOO)
export $(B)ar
+.RECIPEPREFIX := >
all:
- @echo foo=$(foo) bar=$(bar)
- @echo foo=$$foo bar=$$bar
+> @echo foo=$(foo) bar=$(bar)
+> @echo foo=$$foo bar=$$bar
',
"", "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n");
@@ -108,9 +110,10 @@ export foo bar
unexport $(FOO)
unexport $(B)ar
+.RECIPEPREFIX := >
all:
- @echo foo=$(foo) bar=$(bar)
- @echo foo=$$foo bar=$$bar
+> @echo foo=$(foo) bar=$(bar)
+> @echo foo=$$foo bar=$$bar
',
'', "foo=f-ok bar=b-ok\nfoo= bar=\n");
@@ -140,7 +143,8 @@ all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J
# TEST 8: Test unexporting multiple variables on the same line
-@extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
+@args{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
+%ENV = (%ENV, %args);
&run_make_test('
A = a
@@ -174,7 +178,7 @@ a: ; @echo "\$$(export)=$(export) / \$$export=$$export"
',
'', "\$(export)=456 / \$export=456\n");
-# TEST 9: Check "export" as a target
+# TEST 10: Check "export" as a target
&run_make_test('
a: export
@@ -182,5 +186,25 @@ export: ; @echo "$@"
',
'', "export\n");
+# Check export and assignment of a variable on the same line
+
+$ENV{hello} = 'moon';
+
+run_make_test(q!
+all: ; @echo hello=$(hello) hello=$$hello
+export hello=sun
+!,
+ '', "hello=sun hello=sun\n");
+
+# Check unexport and assignment of a variable on the same line
+
+$ENV{hello} = 'moon';
+
+run_make_test(q!
+all: ; @echo hello=$(hello) hello=$$hello
+unexport hello=sun
+!,
+ '', "hello=sun hello=\n");
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/grouped_targets b/tests/scripts/features/grouped_targets
index 615e962..6b3c561 100644
--- a/tests/scripts/features/grouped_targets
+++ b/tests/scripts/features/grouped_targets
@@ -129,5 +129,79 @@ f g h&:: ; @echo Z
'',
"Z");
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate.
+
+touch('hello.z');
+touch('hello.q');
+
+# subtest 1
+# hello.x is not explicitly mentioned and thus is an intermediate file.
+run_make_test(q!
+all: hello.z
+%.z %.q: %.x ; touch $*.z $*.q
+%.x: ;
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 2
+# test.x is explicitly mentioned and thus is not an intermediate file.
+run_make_test(q!
+all: hello.z
+%.z %.q: %.x test.x ; @echo $*.z $*.q
+%.x: ;
+!, '', "hello.z hello.q\n");
+
+# subtest 3
+# hello.x is explicitly mentioned on an unrelated rule and thus is not an
+# intermediate file.
+run_make_test(q!
+all: hello.z
+%.z %.q: %.x; @echo $*.z $*.q
+%.x: ;
+unrelated: hello.x
+!, '', "hello.z hello.q\n");
+
+unlink('hello.z');
+unlink('hello.q');
+
+# SV 62809: Missing grouped target peer causes remake regardless of which
+# target caused the rule to run.
+touch(qw(gta)); # but not gtb
+run_make_test(q!
+gta gtb &: ; touch gta gtb
+!,
+ 'gta', "touch gta gtb\n");
+unlink(qw(gta gtb));
+
+# Ensure both goal targets are built if they depend on a grouped prereq
+touch(qw(gta)); # but not gtb
+run_make_test(q!
+x1 x2: ; touch $@
+
+x1: gta
+x2: gtb
+
+gta gtb &: ; touch gta gtb
+!,
+ 'x1 x2', "touch gta gtb\ntouch x1\ntouch x2\n");
+
+# Now everything should be up to date
+run_make_test(undef, 'x1 x2',
+ "#MAKE#: 'x1' is up to date.\n#MAKE#: 'x2' is up to date.");
+
+unlink(qw(x1 x2 gta gtb));
+
+# If an also-make file is older than a prerequisite build both
+
+utouch(-20, 'gtb');
+utouch(-10, 'pre');
+touch(qw(gta));
+run_make_test(q!
+gta gtb &: pre ; touch gta gtb
+!,
+ 'gta', "touch gta gtb\n");
+unlink(qw(pre gta gtb));
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/implicit_search b/tests/scripts/features/implicit_search
new file mode 100644
index 0000000..564dc5b
--- /dev/null
+++ b/tests/scripts/features/implicit_search
@@ -0,0 +1,483 @@
+# -*-perl-*-
+
+$description = "Test implicit rule search.";
+
+$details = "";
+
+# sv 48643
+# Each test has a %.c rule ahead of %.f rule.
+# hello.f exists and hello.c is missing.
+
+unlink('hello.c', 'hello.tsk', 'hello.o', 'hello.x');
+
+# Run every test with and without a suffix.
+my @suffixes = ('', '.o');
+# Run every test with single and double colon rules.
+my @rules = ('', ':');
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+touch('hello.f');
+
+# Test that make finds the intended implicit rule based on existence of a
+# prerequisite in the filesystem.
+#
+# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+# Test that make finds the intended implicit rule based on the explicit
+# prerequisite of the top goal and despite the existence of a
+# prerequisite in the filesystem.
+#
+# hello.c is an explicit prerequisite of the top target (hello.o or hello).
+# hello.c ought to exist.
+# hello.c prerequisite causes '%.o: %.c' rule to be chosen.
+run_make_test("
+hello$s: hello.c
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello$s'. Stop.\n",
+512);
+
+# Test that make finds the intended implicit rule when the implicit
+# prerequisite matches a target of an unrelated rule and despite the existence
+# of a prerequisite of the other rule candidate in the filesystem.
+#
+# hello.c matches 'hello.c:' rule. This makes hello.c a target and thus ought
+# to exist.
+# hello.c prerequisite causes '%.o: %.c' rule to be chosen.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+hello.c:; @#HELPER# fail 1
+", '-r', "fail 1\n#MAKE#: *** [#MAKEFILE#:5: hello.c] Error 1\n", 512);
+
+# Test that make finds the intended implicit rule based on existence of a
+# prerequisite in the filesystem, even when the prerequisite of another
+# candidate rule is mentioned explicitly on an unrelated rule.
+#
+# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen, even though hello.c
+# is mentioned explicitly on 'unrelated: hello.c'.
+# ought-to-exist does not apply to hello.c.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+unrelated: hello.c
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+# Test that make finds the intended implicit rule based on existence of a
+# prerequisite in the filesystem.
+#
+# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.
+# Despite '%.o: %.c hello.c' rule having explicit prerequisite hello.c.
+# ought-to-exist does not apply to hello.c.
+run_make_test("
+all: hello$s
+%$s:$r %.c hello.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.
+# '%.o: %.f hello.f' rule has explicit prerequisite hello.f.
+# ought-to-exist does not apply to hello.c.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f hello.f; \$(info hello.f)
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+# Rule '%: %.f' is chosen, because '%: %.f' requires no intermediates.
+# '%: %.c', on the other hand, requires intemediate hello.c to be built by the
+# default rule.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info \$<)
+%$s:$r %.f; \$(info \$<)
+.DEFAULT:; \$(info \$\@) true
+unrelated: hello.c
+", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'.");
+
+
+# hello.f is missing.
+# This time both hello.c and hello.f are missing and both '%: %.c' and '%: %.f'
+# require an intermediate.
+# The default rule builds intemerdiate hello.c.
+# '%: %.c' rule is chosen to build hello.
+unlink('hello.f');
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info \$<)
+%$s:$r %.f; \$(info \$<)
+.DEFAULT:; \@\$(info \$\@) #HELPER# fail 1
+unrelated: hello.c
+", '-r', "hello.c\nfail 1\n#MAKE#: *** [#MAKEFILE#:5: hello.c] Error 1\n", 512);
+
+# hello.f is missing.
+# No rule is found, because hello.c is not mentioned explicitly.
+run_make_test("
+all: hello$s
+%$s:$r %.c; \$(info \$<)
+%$s:$r %.f; \$(info \$<)
+.DEFAULT:; \@\$(info \$\@) #HELPER# fail 1
+", '-r', "hello$s\nfail 1\n#MAKE#: *** [#MAKEFILE#:5: hello$s] Error 1\n", 512);
+
+}
+}
+
+# Almost the same tests as above, but this time an intermediate is built.
+
+touch('hello.f');
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n";
+my $rcode = 512;
+if ($s or $r) {
+ $result = "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.";
+ $rcode = 0;
+}
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', "$result", $rcode);
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s hello$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', $result, $rcode);
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c hello$s; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r', $result, $rcode);
+
+}
+}
+
+for my $r (@rules) {
+
+# Circular dependency hello.o <- hello.tsk is dropped.
+run_make_test("
+all: hello.tsk
+%.tsk: %.o; \$(info hello.tsk)
+%.o:$r %.c; \$(info hello.c)
+%.o:$r %.f %.tsk; \$(info hello.f)
+", '-r',
+"#MAKE#: Circular hello.o <- hello.tsk dependency dropped.\nhello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.");
+
+}
+
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+run_make_test("
+all: hello.tsk
+hello$s: hello.c
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+", '-r',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello$s'. Stop.\n",
+512);
+}
+}
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n";
+if ($s or $r) {
+ $result = "fail 1\n#MAKE#: *** [#MAKEFILE#:6: hello.c] Error 1\n";
+}
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+hello.c:; @#HELPER# fail 1
+", '-r', $result, 512);
+}
+}
+
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+unrelated: hello$s
+", '-r', "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.");
+}
+}
+
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n";
+my $rcode = 512;
+if ($s or $r) {
+ $result = "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.";
+ $rcode = 0;
+}
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c; \$(info hello.c)
+%$s:$r %.f hello.f; \$(info hello.f)
+", '-r', $result, $rcode);
+}
+}
+
+# One of the implicit rules has two prerequisites, hello.c and hello.x
+# hello.c does not qualify as ought to exit.
+# hello.x can be made from hello.z.
+# This test exersizes the break, which prevents making hello.x as an
+# intermediate from hello.z during compatibility search.
+unlink('hello.f');
+touch('hello.z');
+for my $s (@suffixes) {
+for my $r (@rules) {
+
+run_make_test("
+all: hello.tsk
+%.tsk: %$s; \$(info hello.tsk)
+%$s:$r %.c %.x; \$(info hello.c)
+%$s:$r %.f; \$(info hello.f)
+unrelated: hello$s
+%.x:$r %.z; \$(info hello.z)
+", '-r',
+"#MAKE#: *** No rule to make target 'hello$s', needed by 'hello.tsk'. Stop.\n",
+512);
+}
+}
+
+# Test that prerequisite 'hello.x' mentioned explicitly on an unrelated rule is
+# not considered intermediate.
+touch('hello.tsk');
+unlink('hello.x');
+run_make_test("
+all: hello.tsk
+%.tsk: %.x; touch hello.tsk
+%.x: ;
+unrelated: hello.x
+", '-r', "touch hello.tsk\n");
+unlink('hello.tsk');
+
+touch ('hello.f');
+# Test implicit search of builtin rules.
+
+# %: %.c (and other builtin rules) are skipped.
+# %: %.f is chosen.
+run_make_test(q!
+all: hello
+!, 'FC="@echo f77" OUTPUT_OPTION=', "f77 hello.f -o hello\n");
+
+# %.o: %.c (and other builtin rules) are skipped.
+# %.o: %.f is chosen.
+run_make_test(q!
+all: hello.o
+!, 'FC="@echo f77" OUTPUT_OPTION=', "f77 -c hello.f\n");
+
+
+# %: %.c is chosen.
+# hello.c is an explicit prerequisite of the top target hello.
+# hello.c ought to exist.
+# hello.c prerequisite causes '%: %.c' rule to be chosen.
+run_make_test(q!
+hello: hello.c
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello'. Stop.\n",
+512);
+
+# %.o: %.c is chosen.
+# hello.c is an explicit prerequisite of the top target hello.o.
+# hello.c ought to exist.
+# hello.c prerequisite causes '%.o: %.c' rule to be chosen.
+run_make_test(q!
+hello.o: hello.c
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello.o'. Stop.\n",
+512);
+
+# %: %.c (and other builtin rules) are skipped.
+# %: %.f is chosen.
+# ought-to-exist does not apply to hello.c.
+run_make_test(q!
+all: hello
+unrelated: hello.c
+!, 'FC="@echo f77" OUTPUT_OPTION=', "f77 hello.f -o hello\n");
+
+# %.o: %.c (and other builtin rules) are skipped.
+# %.o: %.f is chosen.
+# ought-to-exist does not apply to hello.c.
+run_make_test(q!
+all: hello.o
+unrelated: hello.c
+!, 'FC="@echo f77" OUTPUT_OPTION=', "f77 -c hello.f\n");
+
+# builtin rule %.o: %.f is removed.
+# %.o: %.c (and other builtin rules) are skipped, because hello.c is missing.
+# ought-to-exist does not apply to hello.c.
+# %.o: %.c is chosen as a compatibility rule, because of hello.c.
+run_make_test(q!
+all: hello.o
+unrelated: hello.c
+%.o: %.f
+!, '',
+"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello.o'. Stop.\n",
+512);
+
+
+# sv 17752.
+# In this test the builtin match-anything rule '%: %.f' is used to build
+# intermediate hello from hello.f, because hello is mentioned explicitly in
+# the makefile.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %; $(info $@ from $<)
+unrelated: hello
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"f77 hello.f -o hello\nhello.tsk from hello\n");
+
+# In this test the builtin match-anything rule %: %.f cannot be used to build
+# intermediate hello from hello.f, because hello is not mentioned explicitly in
+# the makefile.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %; $(info $@ from $<)
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n",
+512);
+
+# This is just like the one above, but compatibility rule '%.tsk: % %.x' has 2
+# prerequisites, '%' and '%.x'.
+# '%' expands to 'hello' and matches the explicit 'hello' on the unrelated rule.
+# '%.x' is an intermediate built from 'hello.xx' by rule '%.x: %.xx' during the
+# second pass (intermed_ok == 1) of compatibility search.
+# This test validates that compatibility search performs both intermed_ok == 0
+# and intermed_ok == 1 passes.
+unlink('hello.x');
+touch('hello.xx');
+run_make_test(q!
+all: hello.tsk
+%.tsk: % %.x; $(info $@ from $^)
+unrelated: hello
+%.x: %.xx; $(info $@ from $<)
+!, 'FC="@echo f77" OUTPUT_OPTION=',
+"f77 hello.f -o hello\nhello.x from hello.xx\nhello.tsk from hello hello.x\n");
+
+unlink('bye.o', 'bye.tsk', 'bye.x');
+# sv 21670.
+# Default recipe is used to build bye.o.
+run_make_test(q!
+all: bye.tsk
+%.tsk: %.o; $(info $@ from $<)
+.DEFAULT:; $(info bye.o)
+unrelated: bye.o
+!, '-r', "bye.o\nbye.tsk from bye.o\n#MAKE#: Nothing to be done for 'all'.");
+
+touch('bye.xx');
+# This is just like the one above, but compatibility rule '%.tsk: %.o %.x' has 2
+# prerequisites, '%.o' and '%.x'.
+# '%.o' expands to 'bye.o' and matches the explicit 'bye.o' on the unrelated rule.
+# '%.x' is an intermediate built from 'bye.xx' by rule '%.x: %.xx' during the
+# second pass (intermed_ok == 1) of compatibility search.
+# This test validates that compatibility search performs both intermed_ok == 0
+# and intermed_ok == 1 passes.
+run_make_test(q!
+all: bye.tsk
+%.tsk: %.o %.x; $(info $@ from $^)
+.DEFAULT:; $(info bye.o)
+unrelated: bye.o
+%.x: %.xx; $(info $@ from $<)
+!, '-r',
+"bye.o\nbye.x from bye.xx\nbye.tsk from bye.o bye.x\n#MAKE#: Nothing to be done for 'all'.");
+
+unlink('hello.f', 'hello.z', 'hello.xx', 'bye.xx');
+
+
+# A target specific variable causes the file to be entered to the database as a
+# prerequisite. Implicit search then treats this file as explicitly mentioned.
+# Test that implicit search keeps target specific variables of this file intact.
+# In this series of tests prerequisite 'hello.x' has a target specific variable
+# and is built as an intermediate. Implicit search treats 'hello.x' as
+# explicitly mentioned, but 'hello.x' does not qualify as ought-to-exist.
+unlink('hello.x', 'hello.tsk');
+
+# 'hello.x' is mentioned explicitly on the same implicit rule.
+run_make_test(q!
+all: hello.tsk
+%.tsk: hello.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags:=true
+!, '-r', "true\nhello.tsk\n");
+
+# Similar to the one above, but this time 'hello.x' is derived from the stem.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags:=true
+!, '-r', "true\nhello.tsk\n");
+
+# Similar to the one above, this time 'hello.x' is also mentioned explicitly on
+# an unrelated rule.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags:=true
+unrelated: hello.x
+!, '-r', "true\nhello.tsk\n");
+
+# 'hello.x' has a pattern specific variable.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+%.x: flags:=true
+!, '-r', "true\nhello.tsk\n");
+
+# 'hello.x' has a target specific variable and a pattern specific variable.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags+=good
+%.x: flags:=true
+!, '-r', "true good\nhello.tsk\n");
+
+# Intermediate prerequisite 'hello.x' has a target specific variable, a pattern
+# specfic variable, matches on both rules '%.tsk: %.x' and 'big_%.tsk: %.x'.
+run_make_test(q!
+all: hello.tsk big_hello.tsk
+%.tsk: %.x; $(info $@)
+big_%.tsk: %.x; $(info $@)
+%.x:; $(flags)
+hello.x: flags+=good
+%.x: flags:=true
+!, '-r', "true good\nhello.tsk\nbig_hello.tsk\n");
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/include b/tests/scripts/features/include
index 0c63c06..69d6718 100644
--- a/tests/scripts/features/include
+++ b/tests/scripts/features/include
@@ -8,16 +8,11 @@ Test extra whitespace at the end of the include, multiple -includes and
sincludes (should not give an error) and make sure that errors are reported
for targets that were also -included.";
-$makefile2 = &get_tmpfile;
+create_file('incl.mk', "ANOTHER: ; \@echo This is another included makefile\n");
-open(MAKEFILE,"> $makefile");
-
-# The contents of the Makefile ...
-
-print MAKEFILE <<EOF;
-\#Extra space at the end of the following file name
-include $makefile2
-all: ; \@echo There should be no errors for this makefile.
+run_make_test(qq!#Extra space at the end of the following file name
+include incl.mk ! . q!
+all: ; @echo There should be no errors for this makefile.
-include nonexistent.mk
-include nonexistent.mk
@@ -27,27 +22,12 @@ sinclude nonexistent-2.mk
sinclude makeit.mk
error: makeit.mk
-EOF
-
-close(MAKEFILE);
-
-
-open(MAKEFILE,"> $makefile2");
-
-print MAKEFILE "ANOTHER: ; \@echo This is another included makefile\n";
-
-close(MAKEFILE);
-
-# Create the answer to what should be produced by this Makefile
-&run_make_with_options($makefile, "all", &get_logfile);
-$answer = "There should be no errors for this makefile.\n";
-&compare_output($answer, &get_logfile(1));
+!,
+ "all", "There should be no errors for this makefile.\n");
-&run_make_with_options($makefile, "ANOTHER", &get_logfile);
-$answer = "This is another included makefile\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, "ANOTHER", "This is another included makefile\n");
-$makefile = undef;
+unlink('incl.mk');
# Try to build the "error" target; this will fail since we don't know
# how to create makeit.mk, but we should also get a message (even though
@@ -64,6 +44,22 @@ error: foo.mk ; @echo $@
512
);
+# The same as above with an additional include directory.
+
+mkdir('hellod', 0777);
+
+run_make_test
+ ('
+-include foo.mk
+error: foo.mk ; @echo $@
+',
+ '-Ihellod',
+ "#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'. Stop.\n",
+ 512
+ );
+
+rmdir('hellod');
+
# Make sure that target-specific variables don't impact things. This could
# happen because a file record is created when a target-specific variable is
# set.
@@ -157,12 +153,50 @@ include inc1
include inc2
inc2:; echo > $@
!,
- '', "echo > inc2\necho > inc1\nDONE\n");
+ '', "echo > inc1\necho > inc2\nDONE\n");
rmfiles('inc1', 'inc2');
+# Test include of make-able file doesn't show an error.
+# Specify an additional include directory.
+
+mkdir('hellod', 0777);
+
+run_make_test(q!
+.PHONY: default
+default:; @echo DONE
+
+inc1:; echo > $@
+include inc1
+include inc2
+inc2:; echo > $@
+!,
+ '-Ihellod', "echo > inc1\necho > inc2\nDONE\n");
+
+rmfiles('inc1', 'inc2');
+
+# Test include of make-able file doesn't show an error.
+# inc1 and inc2 are present in the specified include directory.
+touch('hellod/inc1');
+touch('hellod/inc2');
+
+run_make_test(q!
+.PHONY: default
+default:; @echo DONE
+
+inc1:; echo > $@
+include inc1
+include inc2
+inc2:; echo > $@
+!,
+ '-Ihellod', "DONE\n");
+
+rmfiles('inc1', 'inc2', 'hellod/inc1', 'hellod/inc2');
+
+rmdir('hellod');
+
# No target gets correct error
-run_make_test('', '', '#MAKE#: *** No targets. Stop.', 512);
+run_make_test("\n", '', '#MAKE#: *** No targets. Stop.', 512);
# No target in included file either, still gets correct error.
touch('inc1.mk');
@@ -209,7 +243,7 @@ inc1:; echo > $@
include inc1
include inc2
!,
- '', "#MAKEFILE#:7: inc2: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'inc2'. Stop.\n", 512);
+ '', "echo > inc1\n#MAKEFILE#:7: inc2: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'inc2'. Stop.\n", 512);
rmfiles('inc1');
@@ -235,10 +269,34 @@ inc1: foo; echo > $@
'', "#MAKEFILE#:3: inc1: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'foo', needed by 'inc1'. Stop.\n", 512);
rmfiles('inc1');
+
+ # Check that included double-colon targets with no prerequisites aren't
+ # built. This should fail as hello.mk doesn't exist
+
+ run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+include hello.mk
+hello.mk:: ; echo 'FOO=bar' > $@
+!,
+ '', "#MAKEFILE#:4: hello.mk: $ERR_no_such_file", 512);
+
+ # Check that included phony targets aren't built.
+ # This should fail as hello.mk doesn't exist
+
+ run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+include hello.mk
+hello.mk: ; echo 'FOO=bar' > $@
+.PHONY: hello.mk
+!,
+ '', "#MAKEFILE#:4: hello.mk: $ERR_no_such_file", 512);
}
-# Including files that can't be read should show an error
if (defined $ERR_unreadable_file) {
+ # Including files that can't be read should show an error
+ unlink('inc1');
create_file('inc1', 'FOO := foo');
chmod 0000, 'inc1';
@@ -248,7 +306,18 @@ all:;@echo $(FOO)
!,
'', "#MAKEFILE#:2: inc1: $ERR_unreadable_file\n#MAKE#: *** No rule to make target 'inc1'. Stop.", 512);
-# Unreadable files that we know how to successfully recreate should work
+ # Including files that can't be read should show an error, even when there
+ # is a readable file in a subsequent include directory.
+ mkdir('hellod', 0777);
+ touch("hellod/inc1");
+
+ run_make_test(q!
+include inc1
+all:;@echo $(FOO)
+!,
+ '-Ihellod', "#MAKEFILE#:2: inc1: $ERR_unreadable_file\n#MAKE#: *** No rule to make target 'inc1'. Stop.", 512);
+
+ # Unreadable files that we know how to successfully recreate should work
run_make_test(sprintf(q!
all:;@echo $(FOO)
@@ -257,7 +326,140 @@ inc1:; @%s $@ && echo FOO := bar > $@
!, $CMD_rmfile),
'', "bar");
- rmfiles('inc1');
+ # Unreadable files that we know how to successfully recreate should work.
+ # Even when there is a readable file in an additional include directory.
+
+ unlink('inc1');
+ create_file('inc1', 'FOO := foo');
+ chmod 0000, 'inc1';
+
+ run_make_test(sprintf(q!
+all:;@echo $(FOO)
+include inc1
+inc1:; @%s $@ && echo FOO := bar > $@
+!, $CMD_rmfile),
+ '-Ihellod', "bar");
+
+ rmfiles('inc1', 'hellod/inc1');
+ rmdir('hellod');
+}
+
+# Check that the order of remaking include files is correct: should remake
+# them in the same order they were encountered in the makefile. SV 58735
+
+run_make_test(q!
+-include i1 i2
+-include i3
+-include i4
+%:;@echo $@
+all:;
+!,
+ '', "i1\ni2\ni3\ni4\n#MAKE#: 'all' is up to date.\n");
+
+# Check that included files work if created after the first include failed
+# https://savannah.gnu.org/bugs/?57676
+
+run_make_test(q!
+default:; @echo $(hello)
+-include hello.mk
+$(shell echo hello=world >hello.mk)
+include hello.mk
+!,
+ '', "world\n");
+
+unlink('hello.mk');
+
+# Check that included double-colon targets with no prerequisites aren't built.
+# This should succeed since hello.mk already exists
+
+touch('hello.mk');
+
+run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+include hello.mk
+hello.mk:: ; echo 'FOO=bar' > $@
+!,
+ '', 'FOO=');
+
+unlink('hello.mk');
+
+# Check that included double-colon targets with no prerequisites aren't built.
+# This should succeed due to -include
+
+run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+-include hello.mk
+hello.mk:: ; echo 'FOO=bar' > $@
+!,
+ '', 'FOO=');
+
+# Check that phony targets aren't built.
+# This should succeed since hello.mk already exists
+
+touch('hello.mk');
+
+run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+include hello.mk
+hello.mk: ; echo 'FOO=bar' > $@
+.PHONY: hello.mk
+!,
+ '', 'FOO=');
+
+unlink('hello.mk');
+
+# Check that included double-colon targets with no prerequisites aren't built.
+# This should succeed due to -include
+
+run_make_test(q!
+.PHONY: default
+default:;@echo 'FOO=$(FOO)'
+-include hello.mk
+hello.mk: ; echo 'FOO=bar' > $@
+.PHONY: hello.mk
+!,
+ '', 'FOO=');
+
+# SV 56301 Verify pattern rules creating optional includes.
+# -k shouldn't matter when creating include files.
+
+run_make_test(q!
+all:; @echo hello
+-include inc_a.mk
+include inc_b.mk
+%_a.mk %_b.mk:; exit 1
+!,
+ '', "exit 1\n#MAKEFILE#:4: Failed to remake makefile 'inc_b.mk'.\n", 512);
+
+run_make_test(undef, '-k', "exit 1\n#MAKEFILE#:4: Failed to remake makefile 'inc_b.mk'.\n", 512);
+
+# It seems wrong to me that this gives a different error message, but at
+# least it doesn't keep going.
+run_make_test(q!
+all:; @echo hello
+include inc_a.mk
+-include inc_b.mk
+%_a.mk %_b.mk:; exit 1
+!,
+ '', "exit 1\n#MAKEFILE#:3: inc_a.mk: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:5: inc_a.mk] Error 1\n", 512);
+
+run_make_test(undef, '-k', "exit 1\n#MAKEFILE#:3: inc_a.mk: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:5: inc_a.mk] Error 1\n#MAKEFILE#:3: Failed to remake makefile 'inc_a.mk'.\n", 512);
+
+# Check the default makefiles... this requires us to invoke make with no
+# arguments. Also check MAKEFILES
+
+if ($port_type eq 'W32') {
+ $defaults = "GNUmakefile\nmakefile\nMakefile\nmakefile.mak";
+} else {
+ $defaults = "GNUmakefile\nmakefile\nMakefile";
}
+$ENV{MAKEFILES} = 'foobar barfoo';
+run_make_with_options(undef, ['-E', '%:;@echo $@', '-E', 'all:;', '-E', '-include bizbaz', '-E', '-include bazbiz'], get_logfile(0));
+$answer = "bizbaz\nbazbiz\nfoobar\nbarfoo\n$defaults\n#MAKE#: 'all' is up to date.\n";
+&compare_output(subst_make_string($answer), &get_logfile(1));
+
1;
diff --git a/tests/scripts/features/jobserver b/tests/scripts/features/jobserver
index 73d10d9..8ecbe34 100644
--- a/tests/scripts/features/jobserver
+++ b/tests/scripts/features/jobserver
@@ -25,17 +25,16 @@ all:;@echo $@: "/$(SHOW)/"
# Setting parallelism with the environment
# Command line should take precedence over the environment
-$extraENV{MAKEFLAGS} = "-j2 $np";
+$ENV{MAKEFLAGS} = "-j2 $np";
run_make_test(q!
SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))
recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all
all:;@echo $@: "/$(SHOW)/"
!,
'', "recurse: /-j2 --jobserver-auth=<auth> $np/\nall: /-j2 --jobserver-auth=<auth> $np/\n");
-delete $extraENV{MAKEFLAGS};
# Test override of -jN
-$extraENV{MAKEFLAGS} = "-j9 $np";
+$ENV{MAKEFLAGS} = "-j9 $np";
run_make_test(q!
SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))
recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -j3 -f #MAKEFILE# recurse2
@@ -43,7 +42,6 @@ recurse2: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all
all:;@echo $@: "/$(SHOW)/"
!,
"-j2 $np", "recurse: /-j2 --jobserver-auth=<auth> $np/\n#MAKE#[1]: warning: -j3 forced in submake: resetting jobserver mode.\nrecurse2: /-j3 --jobserver-auth=<auth> $np/\nall: /-j3 --jobserver-auth=<auth> $np/\n");
-delete $extraENV{MAKEFLAGS};
# Test override of -jN with -j
run_make_test(q!
@@ -64,17 +62,18 @@ all:;@echo $@: "/$(SHOW)/"
unlink('inc.mk');
run_make_test(q!
+.RECIPEPREFIX = >
-include inc.mk
recur:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @rm -f inc.mk
- @$(MAKE) -j2 -f #MAKEFILE# all
+#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+> @rm -f inc.mk
+> @$(MAKE) -j2 -f #MAKEFILE# all
all:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @echo $@
+#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+> @echo $@
inc.mk:
-# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
- @echo 'FOO = bar' > $@
+#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+> @echo 'FOO = bar' > $@
!,
"$np -j2", "#MAKE#[1]: warning: -j2 forced in submake: resetting jobserver mode.\nall\n");
@@ -83,27 +82,79 @@ unlink('inc.mk');
# Test recursion which is hidden from make.
# See Savannah bug #39934
# Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474
-# Windows doesn't use a pipe, and doesn't close access, so this won't happen.
+# Environments that don't use a pipe won't close access, so this won't happen.
if ($port_type ne 'W32') {
- open(MAKEFILE,"> Makefile2");
- print MAKEFILE '
- vpath %.c ../
- foo:
- ';
- close(MAKEFILE);
+ create_file('Makefile2', "vpath %.c ../\n", "foo:\n");
run_make_test(q!
default: ; @ #MAKEPATH# -f Makefile2
!,
- "-j2 $np",
+ "--jobserver-style=pipe -j2 $np",
"#MAKE#[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.
#MAKE#[1]: Nothing to be done for 'foo'.");
rmfiles('Makefile2');
}
-1;
+# For Windows and named pipes, we don't need to worry about recursion
+if ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) {
+ create_file('Makefile2', "vpath %.c ../\n", "foo:\n");
+
+ run_make_test(q!
+default: ; @ #MAKEPATH# -f Makefile2
+!,
+ "-j2 $np",
+"#MAKE#[1]: Nothing to be done for 'foo'.");
+
+ rmfiles('Makefile2');
+}
+
+# Ensure enter/leave directory messages appear before jobserver warnings
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
+run_make_test(q!
+all: ; @$(MAKE) -C . -f #MAKEFILE# recurse -j1
+recurse: ; @echo hi
+!,
+ '-w -j2', "#MAKE#: Entering directory '#PWD#'
+#MAKE#[1]: Entering directory '#PWD#'
+#MAKE#[1]: warning: -j1 forced in submake: resetting jobserver mode.
+hi
+#MAKE#[1]: Leaving directory '#PWD#'
+#MAKE#: Leaving directory '#PWD#'\n");
+
+# Check for invalid jobserver-style options
+
+run_make_test(q!
+all: a
+all a: ; @echo $@
+!,
+ '--jobserver-style=foo -j8',
+ "#MAKE#: *** Unknown jobserver auth style 'foo'. Stop.", 512);
+
+# sv 62908.
+# Test that when mkfifo fails, make switches to pipe and succeeds.
+# Force mkfifo to fail by attempting to create a fifo in a non existent
+# directory.
+# run_make_test does not allow matching a multiline pattern, therefore run the
+# test twice.
+# First time look for /$ERR_no_such_file/ to ensure mkfifo failed.
+# Second time look for /Nothing to be done/ to ensure make succeeded.
+if (exists $FEATURES{'jobserver-fifo'}) {
+ $ENV{TMPDIR} = "nosuchdir";
+ run_make_test("all:\n", '-j2', "/$ERR_no_such_file/");
+
+ $ENV{TMPDIR} = "nosuchdir";
+ run_make_test(undef, '-j2', "/Nothing to be done/");
+
+ # Verify that MAKE_TMPDIR is preferred if provided
+ $ENV{MAKE_TMPDIR} = '.';
+ $ENV{TMPDIR} = 'nosuchdir';
+
+ run_make_test(q!
+recurse: ; @$(MAKE) -f #MAKEFILE# all
+all:;@echo "$$MAKEFLAGS"
+!,
+ "-j2 --no-print-directory", "/--jobserver-auth=fifo:\\./");
+}
+
+1;
diff --git a/tests/scripts/features/load b/tests/scripts/features/load
index fa4b86f..b462ed9 100644
--- a/tests/scripts/features/load
+++ b/tests/scripts/features/load
@@ -4,7 +4,7 @@ $description = "Test the load operator.";
$details = "Test dynamic loading of modules.";
# Don't do anything if this system doesn't support "load"
-exists $FEATURES{load} or return -1;
+exists $FEATURES{'load'} or return -1;
my $cc = get_config('CC');
if (! $cc) {
@@ -19,18 +19,22 @@ unlink(qw(testload.c testload.so));
open(my $F, '> testload.c') or die "open: testload.c: $!\n";
print $F <<'EOF' ;
-#include <string.h>
-#include <stdio.h>
-
#include "gnumake.h"
+char* getenv (const char*);
+
int plugin_is_GPL_compatible;
+int testload_gmk_setup (gmk_floc *);
+int explicit_setup (gmk_floc *);
+
int
testload_gmk_setup (gmk_floc *pos)
{
(void)pos;
gmk_eval ("TESTLOAD = implicit", 0);
+ if (getenv("TESTAPI_KEEP"))
+ return -1;
return 1;
}
@@ -39,6 +43,8 @@ explicit_setup (gmk_floc *pos)
{
(void)pos;
gmk_eval ("TESTLOAD = explicit", 0);
+ if (getenv("TESTAPI_KEEP"))
+ return -1;
return 1;
}
EOF
@@ -46,14 +52,14 @@ close($F) or die "close: testload.c: $!\n";
# Make sure we can compile
-my $cflags = get_config('CFLAGS');
-my $cppflags = get_config('CPPFLAGS');
-my $ldflags = get_config('LDFLAGS');
-my $sobuild = "$cc ".($srcdir? "-I$srcdir/src":'')." $cppflags $cflags -shared -fPIC $ldflags -o testload.so testload.c";
+my $cppflags = get_config('CPPFLAGS') . ($srcdir ? " -I$srcdir/src" : '');
+my $cflags = get_config('CFLAGS') . ' -fPIC';
+my $ldflags = get_config('LDFLAGS') . ' -shared';
+my $sobuild = "$cc $cppflags $cflags $ldflags -o testload.so testload.c";
my $clog = `$sobuild 2>&1`;
if ($? != 0) {
- $verbose and print "Failed to build testload.so:\n$sobuild\n$_";
+ $verbose and print "Failed to build testload.so:\n$sobuild\n$clog";
return -1;
}
@@ -76,7 +82,7 @@ all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
!,
'', "pre= post=testload.so explicit\n");
-# TEST 4
+# TEST 3
# Check multiple loads
run_make_test(q!
PRE := $(.LOADED)
@@ -87,7 +93,7 @@ all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
!,
'', "pre= post=testload.so implicit\n");
-# TEST 5
+# TEST 4
# Check auto-rebuild of loaded file that's out of date
utouch(-10, 'testload.so');
touch('testload.c');
@@ -112,6 +118,32 @@ all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
%.so: %.c ; @echo "rebuilding $@"; !.$sobuild,
'', "rebuilding testload.so\npre= post=testload.so explicit\n");
+# sv 63044.
+# Test that the loaded shared object is present in .LOADED when the setup
+# routine returns -1.
+$ENV{TESTAPI_KEEP} = 1;
+run_make_test(q!
+PRE := $(.LOADED)
+load testload.so
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+!,
+ '--warn-undefined-variables', "pre= post=testload.so implicit\n");
+
+# Check that we don't auto-rebuild of loaded file that's out of date
+# if we return -1 from the setup
+utouch(-10, 'testload.so');
+touch('testload.c');
+
+$ENV{TESTAPI_KEEP} = 1;
+run_make_test(q!
+PRE := $(.LOADED)
+load ./testload.so
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+testload.so: testload.c ; @echo "rebuilding $@"; !.$sobuild,
+ '', "pre= post=testload.so implicit\n");
+
unlink(qw(testload.c testload.so)) unless $keep;
# This tells the test driver that the perl test script executed properly.
diff --git a/tests/scripts/features/loadapi b/tests/scripts/features/loadapi
index ba14928..a72f1f1 100644
--- a/tests/scripts/features/loadapi
+++ b/tests/scripts/features/loadapi
@@ -24,8 +24,12 @@ print $F <<'EOF' ;
#include "gnumake.h"
+char *getenv (const char*);
+
int plugin_is_GPL_compatible;
+int testapi_gmk_setup ();
+
static char *
test_eval (const char *buf)
{
@@ -67,12 +71,26 @@ func_test (const char *funcname, unsigned int argc, char **argv)
}
int
-testapi_gmk_setup ()
+testapi_gmk_setup (const gmk_floc *floc)
{
+ const char *verbose = getenv ("TESTAPI_VERBOSE");
+
gmk_add_function ("test-expand", func_test, 1, 1, GMK_FUNC_DEFAULT);
gmk_add_function ("test-noexpand", func_test, 1, 1, GMK_FUNC_NOEXPAND);
gmk_add_function ("test-eval", func_test, 1, 1, GMK_FUNC_DEFAULT);
gmk_add_function ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.", func_test, 0, 0, 0);
+
+ if (verbose)
+ {
+ printf ("testapi_gmk_setup\n");
+
+ if (verbose[0] == '2')
+ printf ("%s:%lu\n", floc->filenm, floc->lineno);
+ }
+
+ if (getenv ("TESTAPI_KEEP"))
+ return -1;
+
return 1;
}
EOF
@@ -121,6 +139,89 @@ all:;@echo '$(test-noexpand $(TEST))'
!,
'', "\$(TEST)\n");
+
+# During all subsequent tests testapi.so exists.
+#
+my @loads = ('', q!
+load testapi.so
+load testapi.so
+-load testapi.so
+-load testapi.so
+$(eval load testapi.so)
+$(eval -load testapi.so)
+!);
+
+for my $extra_loads (@loads) {
+my $n = 5;
+if ($extra_loads) {
+ $n = 12;
+}
+# sv 63045.
+# Test that having unloaded a shared object make loads it again, even if the
+# shared object is not updated.
+$ENV{TESTAPI_VERBOSE} = 1;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; \$(info \$@)
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\ntestapi.so\ntestapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n");
+
+# sv 63045.
+# Same as above, but testapi_gmk_setup returned -1.
+$ENV{TESTAPI_KEEP} = 1;
+$ENV{TESTAPI_VERBOSE} = 1;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; \$(info \$@)
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n");
+
+# sv 63045.
+# Test that make exits, unless make can successfully update an unloaded shared
+# object.
+$ENV{TESTAPI_VERBOSE} = 1;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; @#HELPER# fail 1
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\nfail 1\n#MAKE#: *** [#MAKEFILE#:$n: testapi.so] Error 1\n", 512);
+
+# sv 63045.
+# Same as above, but testapi_gmk_setup returned -1.
+$ENV{TESTAPI_KEEP} = 1;
+$ENV{TESTAPI_VERBOSE} = 1;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; @#HELPER# fail 1
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n");
+
+# sv 63100.
+# Test that make supplies the correct floc when the shared object is loaded
+# again.
+$ENV{TESTAPI_VERBOSE} = 2;
+run_make_test("
+load testapi.so
+$extra_loads
+all:; \$(info \$(test-expand hello))
+testapi.so: force; \$(info \$@)
+force:;
+.PHONY: force
+", '', "testapi_gmk_setup\n#MAKEFILE#:2\ntestapi.so\ntestapi_gmk_setup\n#MAKEFILE#:2\nhello\n#MAKE#: 'all' is up to date.\n");
+}
+
unlink(qw(testapi.c testapi.so)) unless $keep;
# This tells the test driver that the perl test script executed properly.
diff --git a/tests/scripts/features/mult_rules b/tests/scripts/features/mult_rules
index e706e17..bddd501 100644
--- a/tests/scripts/features/mult_rules
+++ b/tests/scripts/features/mult_rules
@@ -69,10 +69,20 @@ $answer = "EXTRA EXTRA\n";
unlink("defs.h","test.h","config.h","extra.h");
-1;
-
-
-
-
-
+# sv 62650.
+# Test the message that make prints when a file found by directory search
+# is preferred over the local one.
+run_make_test(q!
+vpath hello.c src
+all: hello.c; $(info $@ from $^)
+hello.c: ; $(info 1 $@)
+src/hello.c: ; $(info 2 $@)
+!, '',
+ "#MAKEFILE#:4: Recipe was specified for file 'hello.c' at #MAKEFILE#:4,
+#MAKEFILE#:4: but 'hello.c' is now considered the same file as 'src/hello.c'.
+#MAKEFILE#:4: Recipe for 'hello.c' will be ignored in favor of the one for 'src/hello.c'.
+2 src/hello.c
+all from src/hello.c
+#MAKE#: 'all' is up to date.\n");
+1;
diff --git a/tests/scripts/features/output-sync b/tests/scripts/features/output-sync
index 1d09174..13a54ca 100644
--- a/tests/scripts/features/output-sync
+++ b/tests/scripts/features/output-sync
@@ -116,20 +116,24 @@ EOF
close(MAKEFILE);
# Test per-make synchronization.
+# Note we have to sleep again here after starting the foo makefile before
+# starting the bar makefile, otherwise the "entering/leaving" messages for the
+# submakes might be ordered differently than we expect.
+
unlink(@syncfiles);
run_make_test(qq!
all: make-foo make-bar
make-foo: ; \$(MAKE) -C foo
-make-bar: ; \$(MAKE) -C bar!,
+make-bar: ; #HELPER# -q sleep 1 ; \$(MAKE) -C bar!,
'-j -Orecurse',
"#MAKEPATH# -C foo
#MAKE#[1]: Entering directory '#PWD#/foo'
foo: start
foo: end
#MAKE#[1]: Leaving directory '#PWD#/foo'
-#MAKEPATH# -C bar
+#HELPER# -q sleep 1 ; #MAKEPATH# -C bar
#MAKE#[1]: Entering directory '#PWD#/bar'
bar: start
bar: end
@@ -338,5 +342,30 @@ all:: ; @./foo bar baz
'-O', "#MAKE#: ./foo: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:2: all] Error 127\n", 512);
}
+if ($port_type eq 'UNIX') {
+# POSIX doesn't require sh to set PPID so test this
+my $cmd = create_command();
+add_options($cmd, '-f', '/dev/null', '-E', q!all:;@echo $$PPID!);
+my $fout = 'ppidtest.out';
+run_command_with_output($fout, @$cmd);
+$_ = read_file_into_string($fout);
+chomp($_);
+if (/^[0-9]+$/) {
+use POSIX ();
+# SV 63157.
+# Test that make removes temporary files, even when a signal is received.
+# The general test_driver postprocessing will ensure the temporary file used
+# to synchronize output and the jobserver fifo are both removed.
+# sleep is needed to let make write its "... Terminated" message to the log
+# file.
+run_make_test(q!
+pid:=$(shell echo $$PPID)
+all:; @kill -TERM $(pid) && sleep 16
+!, '-O -j2', '/#MAKE#: \*\*\* \[#MAKEFILE#:3: all] Terminated/', POSIX::SIGTERM);
+}
+
+unlink($fout);
+}
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/parallelism b/tests/scripts/features/parallelism
index 08f94a6..98ee8a3 100644
--- a/tests/scripts/features/parallelism
+++ b/tests/scripts/features/parallelism
@@ -7,46 +7,47 @@ if (!$parallel_jobs) {
return -1;
}
-run_make_test("
+run_make_test(q!
all : def_1 def_2 def_3
-def_1 : ; \@#HELPER# file ONE wait THREE out TWO
-def_2 : ; \@#HELPER# wait FOUR file THREE
-def_3 : ; \@#HELPER# wait ONE file FOUR",
+def_1 : ; @#HELPER# file ONE wait THREE out TWO
+def_2 : ; @#HELPER# wait FOUR file THREE
+def_3 : ; @#HELPER# wait ONE file FOUR!,
'-j4', "file ONE\nwait ONE\nfile FOUR\nwait FOUR\nfile THREE\nwait THREE\nTWO");
rmfiles(qw(ONE TWO THREE FOUR));
# Verify -j added to MAKEFLAGS in the makefile
-run_make_test("
+run_make_test(q!
MAKEFLAGS += -j4
all : def_1 def_2 def_3
-def_1 : ; \@#HELPER# file ONE wait THREE out TWO
-def_2 : ; \@#HELPER# wait FOUR file THREE
-def_3 : ; \@#HELPER# wait ONE file FOUR",
+def_1 : ; @#HELPER# file ONE wait THREE out TWO
+def_2 : ; @#HELPER# wait FOUR file THREE
+def_3 : ; @#HELPER# wait ONE file FOUR!,
'', "file ONE\nwait ONE\nfile FOUR\nwait FOUR\nfile THREE\nwait THREE\nTWO");
rmfiles(qw(ONE TWO THREE FOUR));
# Command line should take precedence
-run_make_test("
+run_make_test(q!
MAKEFLAGS += -j2
all : def_1 def_2 def_3
-def_1 : ; \@#HELPER# file ONE wait THREE out TWO
-def_2 : ; \@#HELPER# wait FOUR file THREE
-def_3 : ; \@#HELPER# wait ONE file FOUR",
+def_1 : ; @#HELPER# file ONE wait THREE out TWO
+def_2 : ; @#HELPER# wait FOUR file THREE
+def_3 : ; @#HELPER# wait ONE file FOUR!,
'-j4', "file ONE\nwait ONE\nfile FOUR\nwait FOUR\nfile THREE\nwait THREE\nTWO");
rmfiles(qw(ONE TWO THREE FOUR));
# Test parallelism with included files. Here we sleep/echo while
# building the included files, to test that they are being built in
# parallel.
-run_make_test("
-all: 1 2; \@#HELPER# out success
+run_make_test(q!
+all: 1 2; @#HELPER# out success
-include 1.inc 2.inc
+.RECIPEPREFIX := >
1.inc:
-\t\@#HELPER# file ONE.inc wait THREE.inc file TWO.inc
-\t\@echo '1: ; \@#HELPER# file ONE wait THREE file TWO' > \$\@
+> @#HELPER# file ONE.inc wait THREE.inc file TWO.inc
+> @echo '1: ; @#HELPER# file ONE wait THREE file TWO' > $@
2.inc:
-\t\@#HELPER# wait ONE.inc file THREE.inc
-\t\@echo '2: ; \@#HELPER# wait ONE file THREE' > \$\@",
+> @#HELPER# wait ONE.inc file THREE.inc
+> @echo '2: ; @#HELPER# wait ONE file THREE' > $@!,
"-j4",
"file ONE.inc\nwait ONE.inc\nfile THREE.inc\nwait THREE.inc\nfile TWO.inc\nfile ONE\nwait ONE\nfile THREE\nwait THREE\nfile TWO\nsuccess\n", 0, 7);
rmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));
@@ -54,17 +55,17 @@ rmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));
# Test parallelism with included files--this time recurse first and make
# sure the jobserver works.
-run_make_test("
-recurse: ; \@\$(MAKE) --no-print-directory -f #MAKEFILE# INC=yes all
-all: 1 2; \@#HELPER# out success
+run_make_test(q!
+recurse: ; @$(MAKE) --no-print-directory -f #MAKEFILE# INC=yes all
+all: 1 2; @#HELPER# out success
INC = no
-ifeq (\$(INC),yes)
+ifeq ($(INC),yes)
-include 1.inc 2.inc
endif
-1.inc: ; \@#HELPER# file ONE.inc wait THREE.inc file TWO.inc; echo '1: ; \@#HELPER# file ONE wait THREE file TWO' > \$\@
-2.inc: ; \@#HELPER# wait ONE.inc file THREE.inc; echo '2: ; \@#HELPER# wait ONE file THREE' > \$\@",
+1.inc: ; @#HELPER# file ONE.inc wait THREE.inc file TWO.inc; echo '1: ; @#HELPER# file ONE wait THREE file TWO' > $@
+2.inc: ; @#HELPER# wait ONE.inc file THREE.inc; echo '2: ; @#HELPER# wait ONE file THREE' > $@!,
"-j4",
"file ONE.inc\nwait ONE.inc\nfile THREE.inc\nwait THREE.inc\nfile TWO.inc\nfile ONE\nwait ONE\nfile THREE\nwait THREE\nfile TWO\nsuccess\n", 0, 7);
rmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));
@@ -74,47 +75,42 @@ rmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));
# function in an exported recursive variable. I added some code to check
# for this situation and print a message if it occurred. This test used
# to trigger this code when I added it but no longer does after the fix.
-# We have to increase the timeout from the default (5s) on this test.
-run_make_test("
-export HI = \$(shell \$(\$\@.CMD))
+run_make_test(q!
+export HI = $(shell $($@.CMD))
first.CMD = #HELPER# out hi
second.CMD = #HELPER# sleep 4
.PHONY: all first second
all: first second
-first second: ; \@#HELPER# out \$\@ sleep 1 out \$\@",
- '-j2', "first\nsleep 1\nfirst\nsecond\nsleep 1\nsecond", 0, 7);
+first second: ; @#HELPER# out $@ sleep 1 out $@!,
+ '-j2', "first\nsleep 1\nfirst\nsecond\nsleep 1\nsecond", 0);
# Michael Matz <matz@suse.de> reported a bug where if make is running in
# parallel without -k and two jobs die in a row, but not too close to each
# other, then make will quit without waiting for the rest of the jobs to die.
-run_make_test("
+run_make_test(q!
.PHONY: all fail.1 fail.2 fail.3 ok
all: fail.1 ok fail.2 fail.3
-.RECIPEPREFIX := >
-
-fail.1 fail.2 fail.3:
-> \@#HELPER# sleep \$(patsubst fail.%,%,\$\@)
-> \@#HELPER# out Fail
-> \@#HELPER# fail 1
+fail.1: ; @#HELPER# -q sleep 1 out $@ file fail.1 fail 1
+fail.2: ; @#HELPER# -q sleep 2 out $@ wait fail.1 file fail.2 fail 1
+fail.3: ; @#HELPER# -q sleep 3 out $@ wait fail.2 file fail.3 fail 1
-ok:
-> \@#HELPER# sleep 4
-> \@#HELPER# out OK",
- '-rR -j5', "sleep 1\nFail\nfail 1
-#MAKE#: *** [#MAKEFILE#:10: fail.1] Error 1
+ok: ; @#HELPER# -q sleep 4 wait fail.3 out OK!,
+ '-rR -j5', "fail.1\nfail 1
+#MAKE#: *** [#MAKEFILE#:5: fail.1] Error 1
#MAKE#: *** Waiting for unfinished jobs....
-sleep 2\nFail\nfail 1
-#MAKE#: *** [#MAKEFILE#:10: fail.2] Error 1
-sleep 3\nFail\nfail 1
-#MAKE#: *** [#MAKEFILE#:10: fail.3] Error 1
-sleep 4\nOK",
+fail.2\nfail 1
+#MAKE#: *** [#MAKEFILE#:6: fail.2] Error 1
+fail.3\nfail 1
+#MAKE#: *** [#MAKEFILE#:7: fail.3] Error 1
+OK",
512);
+rmfiles(qw(fail.1 fail.2 fail.3));
# Test for Savannah bug #15641.
#
@@ -148,7 +144,7 @@ rmfiles('target');
# TEST #11: Make sure -jN from MAKEFLAGS is processed even when we re-exec
# See Savannah bug #33873
-$extraENV{MAKEFLAGS} = '-j4';
+$ENV{MAKEFLAGS} = '-j4';
run_make_test(q!
things = thing1 thing2
@@ -160,7 +156,6 @@ inc.mk: ; @touch $@
!,
'', "file thing2start\nwait thing2start\nfile thing1start\nwait thing1start\nfile thing2end\nwait thing2end\nthing1end\n");
-delete $extraENV{MAKEFLAGS};
rmfiles(qw(inc.mk thing1start thing1end thing2start thing2end));
# Ensure intermediate/secondary files are not pruned incorrectly.
@@ -191,7 +186,7 @@ fff1.mk: ; touch $@
!,
'-j2', "touch fff1.mk\nfile TWO\nwait TWO\nfile ONE\n");
-unlink('fff1.mk', 'ONE', 'TWO');
+rmfiles('fff1.mk', 'ONE', 'TWO');
# Test if a sub-make needs to re-exec and the makefile is built via
# sub-make. Reported by Masahiro Yamada <yamada.masahiro@socionext.com>
@@ -212,7 +207,7 @@ endif
!,
'--no-print-directory -j2', "touch fff1.mk\nfile TWO\nwait TWO\nfile ONE\nrecurse\n");
-unlink('fff1.mk', 'ONE', 'TWO');
+rmfiles('fff1.mk', 'ONE', 'TWO');
# Make sure that all jobserver FDs are closed if we need to re-exec the
diff --git a/tests/scripts/features/patternrules b/tests/scripts/features/patternrules
index 6510c38..0b35408 100644
--- a/tests/scripts/features/patternrules
+++ b/tests/scripts/features/patternrules
@@ -18,32 +18,32 @@ $dir =~ s,.*/([^/]+)$,../$1,;
run_make_test(q!
.PHONY: all
-all: case.1 case.2 case.3
+all: case.1 case.2 case.3 case.4
# We can't have this, due to "Implicit Rule Search Algorithm" step 5c
#xxx: void
# 1 - existing file
-%.1: void
- @exit 1
-%.1: #MAKEFILE#
- @exit 0
+%.1: void ; @exit 1
+%.1: #MAKEFILE# ; @exit 0
# 2 - phony
-%.2: void
- @exit 1
-%.2: 2.phony
- @exit 0
+%.2: void ; @exit 1
+%.2: 2.phony ; @exit 0
.PHONY: 2.phony
# 3 - implicit-phony
-%.3: void
- @exit 1
-%.3: 3.implicit-phony
- @exit 0
+%.3: void ; @exit 1
+%.3: 3.implicit-phony ; @exit 0
3.implicit-phony:
-!, '', '');
+
+# 4 - explicitly mentioned file made by an implicit rule
+%.4: void ; @exit 1
+%.4: test.x ; @exit 0
+%.x: ;
+!,
+ '', '');
# TEST #1: make sure files that are built via implicit rules are marked
# as targets (Savannah bug #12202).
@@ -55,18 +55,14 @@ TARGETS := foo foo.out
all: $(TARGETS)
-%: %.in
- @echo $@
+%: %.in ; @echo $@
-%.out: %
- @echo $@
+%.out: % ; @echo $@
foo.in: ; @:
',
-'',
-'foo
-foo.out');
+ '', "foo\nfoo.out");
# TEST #2: make sure intermediate files that also happened to be
@@ -75,23 +71,17 @@ foo.out');
run_make_test('
$(dir)/foo.o:
-$(dir)/foo.y:
- @echo $@
+$(dir)/foo.y: ; @echo $@
-%.c: %.y
- touch $@
+%.c: %.y ; touch $@
-%.o: %.c
- @echo $@
+%.o: %.c ; @echo $@
.PHONY: install
install: $(dir)/foo.c
',
-"dir=$dir",
-"$dir/foo.y
-touch $dir/foo.c
-$dir/foo.o");
+ "dir=$dir", "$dir/foo.y\ntouch $dir/foo.c\n$dir/foo.o");
unlink("$dir/foo.c");
@@ -109,9 +99,8 @@ run_make_test('
$(dir)/foo.bar:
',
-"dir=$dir",
-"#MAKE#: *** [#MAKEFILE#:6: $dir/foo.bar] Error 1",
-512);
+ "dir=$dir",
+ "#MAKE#: *** [#MAKEFILE#:6: $dir/foo.bar] Error 1", 512);
unlink("$dir/foo.bar");
@@ -123,25 +112,16 @@ run_make_test('
.PHONY: all
all: foo.c foo.o
-%.h %.c: %.in
- touch $*.h
- touch $*.c
+%.h %.c: %.in ; touch $*.h ; touch $*.c
-%.o: %.c %.h
- echo $+ >$@
+%.o: %.c %.h ; echo $+ >$@
-%.o: %.c
- @echo wrong rule
+%.o: %.c ; @echo wrong rule
-foo.in:
- touch $@
+foo.in: ; touch $@
',
-'',
-'touch foo.in
-touch foo.h
-touch foo.c
-echo foo.c foo.h >foo.o');
+ '', "touch foo.in\ntouch foo.h ; touch foo.c\necho foo.c foo.h >foo.o\nrm foo.h");
unlink('foo.in', 'foo.h', 'foo.c', 'foo.o');
@@ -151,10 +131,8 @@ unlink('foo.in', 'foo.h', 'foo.c', 'foo.o');
run_make_test('
all: foo.s1 foo.s2 p1.foo p2.foo
-p1.% p2.%: %.orig
- @echo $@
-%.s1 %.s2: %.orig
- @echo $@
+p1.% p2.%: %.orig ; @echo $@
+%.s1 %.s2: %.orig ; @echo $@
.PHONY: foo.orig
',
@@ -215,16 +193,14 @@ run_make_test('
all: foo.x foo-mt.x
',
-'',
-"one\ntwo");
-
-1;
+ '', "one\ntwo");
# Test pattern rules building the same targets
-# See SV 54233. Rely on our standard test timeout to break the loop
+# See SV 54233.
touch('a.c');
+# a.lnk isn't listed as removed, because it's not actually created
run_make_test(q!
all: a.elf a.dbg
@@ -234,19 +210,467 @@ all: a.elf a.dbg
!,
'-j2', ": a.elf a.lnk\n: a.elf a.dbg\n");
-unlink('a.c');
+# SV 60435 : a.lnk is removed, because it is intermediate.
+run_make_test(q!
+all: a.elf a.dbg
+
+%.elf %.lnk: %.c ; touch $*.elf $*.lnk
+
+%.elf %.dbg: %.lnk ; touch $*.elf $*.dbg
+!,
+ '-j2', "touch a.elf a.lnk\ntouch a.elf a.dbg\nrm a.lnk\n");
+
+unlink('a.elf', 'a.dbg');
+
+# SV 60435 : a.lnk is not intermediate, because it is explicitly mentioned.
+run_make_test(q!
+all: a.elf a.dbg
+
+%.elf %.lnk: %.c ; touch $*.elf $*.lnk
+
+%.elf %.dbg: %.lnk ; touch $*.elf $*.dbg
+
+install: a.lnk
+.PHONY: install
+!,
+ '-j2', "touch a.elf a.lnk\ntouch a.elf a.dbg\n");
+
+unlink('a.c', 'a.elf', 'a.dbg', 'a.lnk');
# SV 56655: Test patterns matching files containing whitespace
touch('some file.yy');
run_make_test(q!
%.xx : %.yy ; @echo matched
-!, '"some file.xx"', "matched\n");
+!,
+ '"some file.xx"', "matched\n");
unlink('some file.xx', 'some file.yy');
+
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate.
+
+touch('hello.z');
+unlink('hello.x', 'test.x');
+
+# subtest 1
+# hello.x is not explicitly mentioned and thus is an intermediate file.
+run_make_test(q!
+all: hello.z
+%.z: %.x ; touch $@
+%.x: ;
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 2
+# test.x is explicitly mentioned and thus is not an intermediate file.
+run_make_test(q!
+all: hello.z
+%.z: %.x test.x ; touch $@
+%.x: ;
+!,
+ '', "touch hello.z");
+
+# subtest 3
+# hello.x is explicitly mentioned on an unrelated rule and thus is not an
+# intermediate file.
+touch('hello.z');
+run_make_test(q!
+all: hello.z
+%.z: %.x; touch $@
+%.x: ;
+unrelated: hello.x
+!,
+ '', "touch hello.z");
+
+unlink('hello.z');
+
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate, even when the builtin rules are used.
+
+touch('hello.x');
+touch('test.x');
+touch('hello.tsk');
+
+# subtest 1
+# hello.o is not explicitly mentioned and thus is an intermediate file.
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.z ; @echo $@
+%.z : %.x ; @echo $@
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 2
+# test.z is explicitly mentioned and thus is not an intermediate file.
+# test.z is built first because until it's built we don't know if we
+# need to rebuild the intermediate hello.z
+run_make_test(q!
+all: hello.tsk
+%.tsk: %.z test.z ; @echo $@
+%.z : %.x ; @echo $@
+!,
+ '', "test.z\nhello.z\nhello.tsk\n");
+
+# subtest 3
+# hello.o is not explicitly mentioned and thus is an intermediate file.
+run_make_test(q!
+all: hello.tsk
+dep:=%.o
+%.tsk: $(dep) ; @echo $@
+!,
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 4
+# Even when test.z is constructed from 2 variables it is still explicitly
+# mentioned and thus is not an intermediate file.
+# test.z is built first because until it's built we don't know if we
+# need to rebuild the intermediate hello.z
+run_make_test(q!
+all: hello.tsk
+name:=test
+suf:=.z
+%.tsk: %.z $(name)$(suf) ; @echo $@
+%.z: %.x ; @echo $@
+!,
+ '', "test.z\nhello.z\nhello.tsk\n");
+
+unlink('hello.x', 'test.x', 'hello.tsk');
+
+# Test that chained pattern rules with multiple targets remove all intermediate
+# files.
+# sv 60435.
+
+# subtest 1.
+# a.1 and a.2 are intermediate and should be removed.
+
+run_make_test(q!
+a.4:
+%.4: %.1 %.15 ; cat $^ >$@
+%.1 %.15: ; touch $*.1 $*.15
+!,
+ '', "touch a.1 a.15\ncat a.1 a.15 >a.4\nrm a.15 a.1");
+
+unlink('a.4');
+
+# subtest 2.
+# a.1 and a.2 are intermediate and should be removed.
+# a.3 is explicit and should not be removed.
+run_make_test(q!
+a.4:
+%.4: %.1 %.15 a.3 ; cat $^ >$@
+%.1 %.15: ; touch $*.1 $*.15
+%.3: ; touch $@
+!,
+ '', "touch a.3\ntouch a.1 a.15\ncat a.1 a.15 a.3 >a.4\nrm a.15 a.1");
+
+unlink('a.3', 'a.4');
+
+# subtest 3.
+# a.1 and a.2 are intermediate and should be removed.
+# a.3 is explicit and should not be removed.
+run_make_test(q!
+a.4:
+%.4: %.1 %.15 a.3 ; cat $^ >$@
+%.1 %.15 %.3: ; touch $*.1 $*.15 $*.3
+!,
+ '', "touch a.1 a.15 a.3\ncat a.1 a.15 a.3 >a.4\nrm a.15 a.1");
+
+unlink('a.3', 'a.4');
+
+# subtest 4.
+# a.1 and a.2 are intermediate and should be removed.
+# a.3 is explicit and should not be removed.
+run_make_test(q!
+a.4:
+%.4: %.1 %.15 a.3 ; cat $^ >$@
+%.3 %.1 %.15: ; touch $*.1 $*.15 $*.3
+!,
+ '', "touch a.1 a.15 a.3\ncat a.1 a.15 a.3 >a.4\nrm a.15 a.1");
+
+unlink('a.3', 'a.4');
+
+# subtest 5.
+# a.1 and a.2 are intermediate and should be removed.
+# a.3 is explicit and should not be removed.
+run_make_test(q!
+a.4:
+%.4: a.3 %.1 %.15 ; cat $^ >$@
+%.1 %.15 %.3: ; touch $*.1 $*.15 $*.3
+!,
+ '', "touch a.1 a.15 a.3\ncat a.3 a.1 a.15 >a.4\nrm a.15 a.1");
+
+unlink('a.3', 'a.4');
+
+# subtest 6.
+# a.2 is intermediate and should be removed.
+# a.1 is mentioned explicitly on an unrelated rule and should not be removed.
+run_make_test(q!
+a.3:
+%.3: %.1 %.2 ; cat $^ >$@
+%.1 %.2: ; touch $*.1 $*.2
+install: a.1
+.PHONY: install
+!,
+ '', "touch a.1 a.2\ncat a.1 a.2 >a.3\nrm a.2");
+
+unlink('a.1', 'a.3');
+
+# Test removal of intermediate files.
+
+# subtest 1.
+# hello.x is removed, because it is intermediate.
+run_make_test(q!
+hello.tsk:
+%.tsk: %.x; touch $@
+%.x: ; touch $@
+!,
+ '', "touch hello.x\ntouch hello.tsk\nrm hello.x");
+
+unlink('hello.tsk');
+
+# subtest 2.
+# Even though hello.x is intermediate, it is not removed, because it is not
+# created.
+touch('hello.x');
+
+run_make_test(q!
+hello.tsk:
+%.tsk: %.x; touch $@
+%.x: ; touch $@
+!,
+ '', "touch hello.tsk");
+
+unlink('hello.x', 'hello.tsk');
+
+# subtest 2.
+# Even though hello.x is intermediate, it is not removed, because it is not
+# created.
+run_make_test(q!
+hello.tsk:
+%.tsk: %.x; touch $@
+%.x: ; : $@
+!,
+ '', ": hello.x\ntouch hello.tsk");
+
+unlink('hello.tsk');
+
+# A target explicitly listed as a prerequisite of a pattern rule, is still
+# considered mentioned and "ought to exist".
+
+run_make_test(q!
+1.all: 1.q ; touch $@
+%.q: 1.r ; touch $@
+%.r: ; touch $@
+!,
+ '', "touch 1.r\ntouch 1.q\ntouch 1.all\n");
+
+unlink('1.all', '1.q', '1.r');
+
+# SV 63098: Verify that missing also_made in pattern rules gives a warning but
+# doesn't fail.
+
+run_make_test(q!
+%a %b : ; touch $*a
+!,
+ 'gta', "touch gta\n#MAKEFILE#:2: warning: pattern recipe did not update peer target 'gtb'.\n");
+unlink(qw(gta));
+
+# We don't warn if we didn't update the file
+utouch(-10, qw(gta));
+run_make_test(q!
+%a %b : xyzzy ; $(OP)
+xyzzy: ;
+ifdef RUN
+OP = @echo no
+endif
+!,
+ '-rR gta', "#MAKE#: 'gta' is up to date.\n");
+
+run_make_test(undef, '-rR gta RUN=1', "no\n");
+unlink(qw(gta));
+
+run_make_test(q!
+all:;
+include gta
+%a %b : ; touch $*a
+!,
+ '', "touch gta\n#MAKEFILE#:4: warning: pattern recipe did not update peer target 'gtb'.\n#MAKE#: 'all' is up to date.");
+unlink(qw(gta));
+
+run_make_test(q!
+%.c %.h : %.y; touch $*.c
+%.o: %.c; touch $@
+foo.y: ; touch $@
+!,
+ 'foo.o', "touch foo.y\ntouch foo.c\n#MAKEFILE#:2: warning: pattern recipe did not update peer target 'foo.h'.\ntouch foo.o\nrm foo.c");
+unlink(qw(foo.y foo.c foo.o));
+
+if (0) {
+# SV 12078: Missing grouped pattern peer causes remake regardless of which
+# target caused the rule to run.
+touch(qw(gta)); # but not gtb
+run_make_test(q!
+%a %b : ; touch $*a $*b
+!,
+ 'gta', "touch gta gtb\n");
+unlink(qw(gta gtb));
+
+# Ensure both goal targets are built if they depend on a grouped pattern
+touch(qw(gta)); # but not gtb
+run_make_test(q!
+x y: ; touch $@
+
+x: gta
+y: gtb
+
+%a %b : ; touch $*a $*b
+!,
+ 'x y', "touch gta gtb\ntouch x\ntouch y\n");
+
+# Now everything should be up to date
+run_make_test(undef, 'x y',
+ "#MAKE#: 'x' is up to date.\n#MAKE#: 'y' is up to date.");
+
+unlink(qw(x y gta gtb));
+
+# sv 12078 : make sure we notice when all targets need to be rebuilt
+# a.1st exists but b.1st doesn't: make sure a.2nd is out of date as well
+
+utouch(-20, 'a.1st');
+utouch(-10, 'a.2nd', 'b.2nd');
+
+run_make_test(q!
+1st := a.1st b.1st
+2nd := ${1st:.1st=.2nd}
+.PHONY: all
+all: ${2nd}
+a.% b.% : ; touch a.$* b.$*
+${2nd}: %.2nd: %.1st ; cp $< $@
+!
+ , '', "touch a.1st b.1st\ncp a.1st a.2nd\ncp b.1st b.2nd\n");
+
+unlink(qw(a.1st b.1st a.2nd b.2nd));
+
+# Variation: b.1st exists but is newer
+
+utouch(-20, 'a.1st');
+utouch(-10, 'a.2nd', 'b.2nd');
+touch(qw(b.1st));
+
+run_make_test(undef, '', "cp b.1st b.2nd\n");
+
+unlink(qw(a.1st b.1st a.2nd b.2nd));
+}
+
+# sv 62206.
+
+# The following combinations are generated with and without second expansion.
+# 1.
+# all: bye.x
+# %.x: ...
+#
+# 2.
+# all: lib/bye.x
+# %.x: ...
+#
+# 3.
+# all: lib/bye.x
+# lib/%.x: ...
+#
+# The following combination is not generated, because there is no rule to
+# build bye.x, no stem substitution takes place, not of interest of this test.
+# 4.
+# all: bye.x
+# lib/%.x: ...
+
+my @dir = ('', 'lib/'); # With and without last slash.
+my @secondexpansion = ('', '.SECONDEXPANSION:');
+
+for my $se (@secondexpansion) {
+for my $d (@dir) { # The directory of the prerequisite of 'all'.
+for my $r (@dir) { # The directory of the target in the rule definition.
+(!$d && $r) && next; # Combination 4.
+my $dollar = $se ? '$' : '';
+
+# The prerequisite should only have directory if the prerequisite of 'all' has
+# it and if the prequisite pattern in the rule definition does not have it.
+# That is combination 2.
+my $pdir = $d && !$r ? $d : '';
+
+my $prereqs = "${pdir}bye.1";
+
+# One func, one %.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(firstword %.1); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+$prereqs = "${pdir}bye.1 ${pdir}bye.2";
+
+# Multiple funcs, each has one %.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(firstword %.1) $dollar\$(firstword %.2); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+$prereqs = "${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4";
+
+# Multiple funcs, each has multiple %.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(wordlist 1, 99, %.1 %.2) $dollar\$(wordlist 1, 99, %.3 %.4); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+$prereqs = "${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4";
+
+# Nested functions.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(wordlist 1, 99, $dollar\$(wordlist 1, 99, %.1 %.2)) $dollar\$(wordlist 1, 99, $dollar\$(wordlist 1,99, %.3 %.4)); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+$prereqs = "${pdir}bye1%2% ${pdir}bye ${pdir}3bye4%5 ${pdir}6bye ${pdir}bye7%8 ${pdir}bye9 ${pdir}bye10% ${pdir}11bye12 13";
+
+# Multiple funcs, each has multiple words, each word has multiple %, sole %,
+# various corner cases.
+# Make should substitute the first % and only the first % in each word with the
+# stem.
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(wordlist 1, 99, %1%2% % 3%4%5 6%) %7%8 %9 $dollar\$(wordlist 1, 99, %10% 11%12) 13; \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+if ($port_type eq 'UNIX') {
+# Test that make does not use some hardcoded array of a finite size on stack.
+# Long prerequisite name. This prerequisite name is over 66K long.
+my $prefix = 'abcdefgh' x 128 x 33; # 33K long.
+my $suffix = 'stuvwxyz' x 128 x 33; # 33K long.
+$prereqs = "${pdir}${prefix}bye${suffix}.1 ${pdir}${prefix}bye${suffix}.2";
+
+run_make_test("
+$se
+all: ${d}bye.x
+$r%.x: $dollar\$(wordlist 1, 99, ${prefix}%${suffix}.1 ${prefix}%${suffix}.2); \$(info \$@ from \$^)
+.PHONY: $prereqs
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+}
+
+}
+}
+}
+
# This tells the test driver that the perl test script executed properly.
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/features/reinvoke b/tests/scripts/features/reinvoke
index d2a1f50..07cbbfb 100644
--- a/tests/scripts/features/reinvoke
+++ b/tests/scripts/features/reinvoke
@@ -17,9 +17,7 @@ $omkfile = $makefile;
run_make_test('
all: ; @echo running rules.
-#MAKEFILE# incl.mk: incl-1.mk
- @echo rebuilding $@
- @echo >> $@
+#MAKEFILE# incl.mk: incl-1.mk ; @echo rebuilding $@; echo >> $@
include incl.mk',
'', "rebuilding incl.mk\nrunning rules.\n");
@@ -45,17 +43,17 @@ all: ; @echo hello
a : b ; echo >> $@
-b : c ; [ -f $@ ] || echo >> $@
+b : c ; test -f $@ || echo >> $@
c: ; echo >> $@
include $(F)',
- 'F=a', "[ -f b ] || echo >> b\nhello\n");
+ 'F=a', "test -f b || echo >> b\nhello\n");
# Now try with the file we're not updating being the actual file we're
# including: this and the previous one test different parts of the code.
-run_make_test(undef, 'F=b', "[ -f b ] || echo >> b\nhello\n");
+run_make_test(undef, 'F=b', "test -f b || echo >> b\nhello\n");
&rmfiles('a','b','c');
@@ -74,9 +72,109 @@ foo30723: ; @touch $@
unlink('foo30723');
+# If ANY makefile is rebuilt then we should re-exec
+
+run_make_test('
+all: ; @echo RESTARTS=$(MAKE_RESTARTS)
+
+m1.d: ; @echo $@; touch $@
+
+m2.d: m1.d ; @test -f $< || { echo $@; touch $@; }
+
+include m1.d
+-include m2.d
+',
+ '', "m1.d\nRESTARTS=1\n");
+
+unlink('m1.d', 'm2.d');
+
+# Same as before but be sure we get error messages for un-created makefiles
+run_make_test('
+all: ; @echo RESTARTS=$(MAKE_RESTARTS)
+
+m1.d: ; @echo $@; touch $@
+
+m2.d: m1.d ; @test -f $< || { echo $@; touch $@; }
+
+include m1.d m2.d
+', '',
+ # This runs afoul of https://savannah.gnu.org/bugs/?61226
+ 0 ? "m1.d\n#MAKEFILE#:8: m2.d: $ERR_no_such_file"
+ : "m1.d\nRESTARTS=1",
+ 0 ? 512 : 0);
+
+unlink('m1.d', 'm2.d');
+
+# sv 61226.
+# This set of four cases tests two aspects of make.
+#
+# 1. If a rule has no prerequisites or recipe, and the target of the rule is a
+# nonexistent file, then make imagines this target to have been updated
+# whenever its rule is run.
+#
+# 2. Make does not re-execute itself in this case of imagined target.
+#
+# Test case 1.
+# Make imagines hello.d was updated by a rule without recipe and without
+# prereqs.
+# This should succeed.
+# Make should not re-execute itself.
+run_make_test('
+hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
+hello.d:
+include hello.d
+', '', "RESTARTS=\n#MAKE#: 'hello.o' is up to date.");
+
+# Test case 2.
+# Make imagines hello.d was updated by a rule with a recipe and without
+# prereqs.
+# This should succeed.
+# Make should not re-execute itself.
+run_make_test('
+hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
+hello.d:; $(info $@)
+include hello.d
+', '', "hello.d\nRESTARTS=\n#MAKE#: 'hello.o' is up to date.");
+
+&touch('hello.td');
+# Test case 3.
+# Make imagines hello.d was updated by a rule without a recipe and with
+# prereqs.
+# This should succeed.
+# Make should not re-execute itself.
+run_make_test('
+hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
+hello.d: hello.td
+include hello.d
+', '', "RESTARTS=\n#MAKE#: 'hello.o' is up to date.");
+
+# Test case 4.
+# Same test as three tests above, but the rule has both recipe and prereqs.
+# Make should report this error.
+run_make_test('
+hello.o: hello.d; $(info $@)
+hello.d: hello.td; $(info $@)
+include hello.d
+', '',
+ # This runs afoul of https://savannah.gnu.org/bugs/?61226
+ 0 ? "hello.d\n#MAKEFILE#:4: hello.d: $ERR_no_such_file"
+ : "hello.d\nhello.o\n#MAKE#: 'hello.o' is up to date.",
+ 0 ? 512 : 0);
+
+unlink('hello.td');
+
+# Test DV 62088 : make sure we don't re-invoke for stdin makefiles.
+# The test framework doesn't seem to have a good way to do this.
+
+create_file('input.mk', "all:;\$(info all)\n");
+
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "input.mk: $!\n";
+
+run_make_test('', '-sf -', "all\n");
+
+close(STDIN);
+unlink('input.mk');
+
# This tells the test driver that the perl test script executed properly.
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/features/se_explicit b/tests/scripts/features/se_explicit
index c28641c..d1247d4 100644
--- a/tests/scripts/features/se_explicit
+++ b/tests/scripts/features/se_explicit
@@ -185,9 +185,9 @@ foo: $$@.o ;
# Not creating libcat.a here prevents segfault,
libcat.a: ; @touch $@
!,
- '', q!#MAKEFILE#:16: Recipe was specified for file '-lcat' at #MAKEFILE#:19,
+ '', q!#MAKEFILE#:16: Recipe was specified for file '-lcat' at #MAKEFILE#:16,
#MAKEFILE#:16: but '-lcat' is now considered the same file as 'libcat.a'.
-#MAKEFILE#:16: Recipe for 'libcat.a' will be ignored in favor of the one for '-lcat'.!);
+#MAKEFILE#:16: Recipe for '-lcat' will be ignored in favor of the one for 'libcat.a'.!);
unlink('libcat.a');
# SV 28456 : Don't reset $$< for default recipes
@@ -200,4 +200,305 @@ biz: $$(info $$<)
!,
'', "baz\n#MAKE#: Nothing to be done for 'biz'.\n");
+
+# sv 60659. Second expansion of automatic variables inside a function in the
+# prerequisite list.
+# $$@ expands to the target in the 1st and following rules.
+# $$<,$$^,$$+,$$|,$$?,$$*,$$% expand to the empty string in the prerequisite
+# list of the 1st rule.
+# $$<,$$^,$$+,$$|,$$?,$$*,$$% in the prerequisite list of the 2nd (and
+# following) rule expand to the values from the 1st rule.
+
+
+# subtest 1. Explicit rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+2.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 2. Explicit rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x 1.x
+15.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.x: 1.z 2.z 2.z | 3.z 4.z
+15.x 1.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=,%=
+@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 3. Grouped targets in explicit rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x
+15.x 1.x&: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=15.x,<=,^=,+=,|=,?=,*=,%=
+@=1.x,<=,^=,+=,|=,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 4. Grouped targets in explicit rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x 1.x
+15.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.x: 1.z 2.z 2.z | 3.z 4.z
+15.x 1.x&: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=,%=
+@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Double colon rules.
+# Because each double colon rule is independent of the other double colon rules
+# for the same target, each automatic variable in the prerequisite list, other
+# than $$@, second expands to the empty string in any rule, 1st, 2nd or later.
+
+# subtest 5. 1st double colon rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+2.x:: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 6. 2nd double colon rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x 1.x
+15.x:: 5.z 6.z 5.z | 7.z 7.z 8.z ;
+1.x:: 1.z 2.z 2.z | 3.z 4.z ;
+15.x 1.x:: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;
+%.z: ;
+!, '',
+"@=15.x,<=,^=,+=,|=,?=,*=,%=
+@=1.x,<=,^=,+=,|=,?=,*=,%=
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# sv 62324.
+# Integrity self check.
+run_make_test(q!
+.SECONDEXPANSION:
+all: bye.x
+bye.x: $$(firstword bye.1;
+!, '', "#MAKEFILE#:4: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+
+unlink('hello.tsk', 'test.o', 'bye.tsk', 'hello.o', 'hello.h', 'hello.q', 'bye.c', 'bye.o');
+
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the targets which
+# are not built.
+# Here, hello.tsk is built and its prerequisites are second expanded.
+# bye.tsk is not built and its prerequisites are not second expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Multipe rules per target.
+run_make_test(q!
+.SECONDEXPANSION:
+
+all: hello.tsk
+dep1:=hello.o
+dep2:=hello.h
+hello.tsk: $$(dep1)
+hello.tsk: $$(dep2); $(info $@ from $^)
+hello.o:; $(info $@)
+hello.h:; $(info $@)
+!, 'hello.tsk',
+"hello.h
+hello.o
+hello.tsk from hello.h hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Multiple targets per rule.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk bye.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Grouped targets.
+run_make_test(q!
+.SECONDEXPANSION:
+world.tsk: world.o $$(info 1 second expansion of $$@ prereqs)
+hello.tsk world.tsk &: hello.o $$(info 2 second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+world.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"2 second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+2 second expansion of world.tsk prereqs
+1 second expansion of world.tsk prereqs
+second expansion of world.o prereqs
+world.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Order only.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:| hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+bye.tsk:| bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+hello.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 1 rule per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk:: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 2 rules per targets.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: hello.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+hello.tsk:: hello.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+bye.tsk:: bye.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+bye.tsk:: bye.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+hello.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+hello.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+bye.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+bye.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+!, 'hello.tsk',
+"1 second expansion of hello.tsk prereqs
+1 second expansion of hello.o prereqs
+1 hello.o
+2 second expansion of hello.o prereqs
+2 hello.o
+1 hello.tsk from hello.o
+2 second expansion of hello.tsk prereqs
+2 hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Test that the prerequisites of 'hello.tsk' are second expanded once.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk hello.q
+hello.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+hello.q: hello.tsk $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+!, '',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+second expansion of hello.q prereqs
+hello.q from hello.tsk
+#MAKE#: Nothing to be done for 'all'.\n");
+
+# sv 62706.
+# Merge vpath file and local file.
+# Test that both sets of prerequisites from 'hello.c' rule and from
+# 'src/hello.c' rule are second expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+vpath hello.c src
+all: hello.c; $(info $@ from $^)
+hello.c: $$(info second expansion of hello.c prereqs); $(info 1 $@)
+src/hello.c: $$(info second expansion of src/hello.c prereqs); $(info 2 $@)
+!, '',
+"#MAKEFILE#:5: Recipe was specified for file 'hello.c' at #MAKEFILE#:5,
+#MAKEFILE#:5: but 'hello.c' is now considered the same file as 'src/hello.c'.
+#MAKEFILE#:5: Recipe for 'hello.c' will be ignored in favor of the one for 'src/hello.c'.
+second expansion of src/hello.c prereqs
+second expansion of hello.c prereqs
+2 src/hello.c
+all from src/hello.c
+#MAKE#: 'all' is up to date.\n");
+
+# sv 62706.
+# .DEFAULT.
+run_make_test(q!
+.SECONDEXPANSION:
+bye:=bye.c
+all: hello.o
+.DEFAULT: $$(info second expansion of prereqs of default recipe @ = $$@) ; $(info default recipe $@)
+!, '',
+"default recipe hello.o
+#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.1');
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:; exit 1
+unrelated: $$(shell touch hello.1);
+!, '',
+"exit 1
+#MAKE#: *** [#MAKEFILE#:3: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is explicit.
+# .SECONDARY marks hello.x as intermediate.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+.SECONDARY: hello.x
+all: hello.x
+hello.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
1;
diff --git a/tests/scripts/features/se_implicit b/tests/scripts/features/se_implicit
index 866d1fb..c9d7ca9 100644
--- a/tests/scripts/features/se_implicit
+++ b/tests/scripts/features/se_implicit
@@ -262,5 +262,245 @@ run_make_test(q!
!,
'q/ux', "q/u\nq/u\n");
+
+
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate.
+
+touch('hello.z');
+
+# subtest 1.
+# hello.x is derived from the stem and thus is an intermediate file.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=.x
+all: hello.z
+%.z: %$$(dep) ; @echo $@
+%.x: ;
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 2.
+# test.x is explicitly mentioned and thus is not an intermediate file.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=test.x
+all: hello.z
+%.z: %.x $$(dep) ; @echo $@
+%.x: ;
+!, '', "hello.z\n");
+
+# subtest 3.
+# make is building hello.z and does not second expand the prerequisites of rule
+# 'unrelated: $$(dep)'. '$$(dep)' stays not expanded and 'hello.x' is never
+# entered to the database. Make considers 'hello.x' intermediate while building
+# 'hello.z'. Because 'hello.z' is present and 'hello.x' is missing and
+# 'hello.x' is intermediate, there is no need to rebuild 'hello.z'.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=hello.x
+all: hello.z
+%.z: %.x; @echo $@
+%.x: ;
+unrelated: $$(dep)
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 4.
+# Just like subtest 3. $$(dep) is not second expanded. 'hello.x' is
+# intermediate.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=hello.x
+all: hello.z
+%.z: %.x; @echo $@
+%.x: ;
+%.q: $$(dep)
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.z');
+
+
+# sv 60188.
+# Test that a file explicitly mentioned by the user and made by an implicit
+# rule is not considered intermediate, even when the builtin rules are used.
+
+touch('hello.x');
+touch('hello.tsk');
+
+# subtest 1.
+# hello.z is explicitly mentioned and thus is not an intermediate file.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=hello.z
+all: hello.tsk
+%.tsk: $$(dep) ; @echo $@
+%.z : %.x ; @echo $@
+!, '', "hello.z\nhello.tsk");
+
+# subtest 2.
+# hello.z is derived from the stem and thus is an intermediate file.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=.z
+all: hello.tsk
+%.tsk: %$$(dep) ; @echo $@
+%.z : %.x ; @echo $@
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.x');
+unlink('hello.tsk');
+
+
+# sv 60659. Second expansion of automatic variables inside a function in the
+# prerequisite list.
+# $$@ expands to the target in the 1st and following rules.
+# $$* expands to the stem in the 1st and following rules.
+# $$<,$$^,$$+,$$|,$$?,$$% expand to the empty string in the prerequisite list
+# of the 1st rule.
+# $$<,$$^,$$+,$$|,$$?,$$% in the prerequisite list of the 2nd (and following)
+# rule expand to the values from the 1st rule.
+# $$% cannot be used in prerequisites, because in pattern rules % is
+# substituted for stem.
+
+
+# subtest 1. Pattern rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+%.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=2
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 2. Pattern rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x 1.x
+2.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.x: 1.z 2.z 2.z | 3.z 4.z
+%.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=2
+@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 3. Static pattern rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+2.x: %.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=2
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 4. Static pattern rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 15.x 1.x
+15.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.x: 1.z 2.z 2.z | 3.z 4.z
+15.x 1.x: %.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=15
+@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 5. Grouped targets in implicit rules. 1st rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+%.x %.xx&: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=2
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 6. Grouped targets in implicit rules. 2nd rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x 1.xx
+2.x: 5.z 6.z 5.z | 7.z 7.z 8.z
+1.xx: 1.z 2.z 2.z | 3.z 4.z
+%.x %.xx&: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+%.z: ;
+!, '',
+"@=2.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=2
+@=1.xx,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1
+#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# subtest 7. Double colon rule.
+run_make_test(q!
+.SECONDEXPANSION:
+all: 2.x
+%.x:: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;
+5.z 6.z: ;
+!, '',
+"@=2.x,<=,^=,+=,|=,?=,*=2
+#MAKE#: Nothing to be done for 'all'.\n");
+
+# sv 62324.
+# Integrity self check.
+run_make_test(q!
+.SECONDEXPANSION:
+all: bye.x
+%.x: $$(firstword %.1;
+!, '', "#MAKE#: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the rules which are
+# not tried during implicit search.
+# Here, make tries rules '%.tsk: %.o' and '%.o' and their prerequisites are
+# second expanded.
+# Rules '%.bin: %.x' and '%.x:' are not used in implicit search for 'hello.tsk'
+# and 'hello.o' and their prerequisites are not expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+%.bin: %.x $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+%.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+%.x: $$(info second expansion of $$@ prereqs); $(info $@)
+%.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, '-R hello.tsk',
+"second expansion of hello.o prereqs
+second expansion of hello.tsk prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk
+%.tsk: %.o; exit 1
+hello.o:;
+%.q: $$(shell touch hello.1);
+!, '',
+"exit 1
+#MAKE#: *** [#MAKEFILE#:4: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is implicit.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.\n");
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/se_statpat b/tests/scripts/features/se_statpat
index b1e59e1..935ff3f 100644
--- a/tests/scripts/features/se_statpat
+++ b/tests/scripts/features/se_statpat
@@ -91,17 +91,142 @@ baz.a.2
#
run_make_test(q!
.SECONDEXPANSION:
-foo$$bar: f%r: % $$*.1
- @echo '$*'
+foo$$bar: f%r: % $$*.1 ; @echo '$*'
-oo$$ba oo$$ba.1:
- @echo '$@'
+oo$$ba oo$$ba.1: ; @echo '$@'
!,
'', 'oo$ba
oo$ba.1
oo$ba
');
+# sv 62324.
+# Integrity self check.
+run_make_test(q!
+.SECONDEXPANSION:
+all: bye.x
+bye.x: %.x: $$(firstword %.1;
+!, '', "#MAKEFILE#:4: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+
+#unlink('hello.tsk', 'bye.tsk', 'hello.o', 'hello.q', 'bye.o');
+
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the targets which
+# are not built.
+# Here, hello.tsk is built and its prerequisites are second expanded.
+# bye.tsk is not built and its prerequisites are not second expanded.
+
+# Static pattern rules.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Order only prereqs.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: %.tsk:| %.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+bye.tsk: %.tsk:| %.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+hello.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 1 rule per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 2 rules per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: %.tsk: %.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+hello.tsk:: %.tsk: %.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+hello.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+hello.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+bye.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+bye.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+!, 'hello.tsk',
+"1 second expansion of hello.tsk prereqs
+1 second expansion of hello.o prereqs
+1 hello.o
+2 second expansion of hello.o prereqs
+2 hello.o
+1 hello.tsk from hello.o
+2 second expansion of hello.tsk prereqs
+2 hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Test that the prerequisites of 'hello.tsk' are second expanded once.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk hello.q
+hello.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+hello.q: %.q: %.tsk $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+!, '',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+second expansion of hello.q prereqs
+hello.q from hello.tsk
+#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.1');
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk
+hello.tsk: %.tsk: %.o; exit 1
+hello.o:;
+bye.tsk: %.tsk: $$(shell touch hello.1);
+!, '',
+"exit 1
+#MAKE#: *** [#MAKEFILE#:4: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is static pattern.
+# .SECONDARY marks hello.x as intermediate.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+.SECONDARY: hello.x
+all: hello.x
+hello.x: %.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\n#MAKE#: Nothing to be done for 'all'.\n");
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/statipattrules b/tests/scripts/features/statipattrules
index 3f363de..e4e118e 100644
--- a/tests/scripts/features/statipattrules
+++ b/tests/scripts/features/statipattrules
@@ -72,13 +72,15 @@ foo.baz: ;@:
# perprerequisite's stem (Savannah bug #16053).
#
run_make_test('
+.RECIPEPREFIX := >
+
all.foo.bar: %.foo.bar: %.one
all.foo.bar: %.bar: %.two
all.foo.bar:
- @echo $*
- @echo $^
+> @echo $*
+> @echo $^
.DEFAULT:;@:
',
@@ -92,6 +94,7 @@ all.one all.foo.two');
# (Savannah bug #16053).
#
run_make_test('
+.RECIPEPREFIX := >
.SECONDEXPANSION:
all.foo.bar: %.foo.bar: %.one $$*-one
@@ -99,8 +102,8 @@ all.foo.bar: %.foo.bar: %.one $$*-one
all.foo.bar: %.bar: %.two $$*-two
all.foo.bar:
- @echo $*
- @echo $^
+> @echo $*
+> @echo $^
.DEFAULT:;@:
',
@@ -108,4 +111,201 @@ all.foo.bar:
'all.foo
all.one all-one all.foo.two all.foo-two');
+# Test #8:
+# sv 60188.
+# Static pattern rules are considered explicit rules: no prerequisite of
+# a static pattern rule can ever be considered intermediate.
+
+touch('hello.z');
+
+# subtest 1
+run_make_test(q!
+hello.z: %.z: %.x ; @echo $@
+%.x: ;
+!, '', "hello.z\n");
+
+# subtest 2
+run_make_test(q!
+hello.z: %.z: %.x test.x ; @echo $@
+%.x: ;
+!, '', "hello.z\n");
+
+# subtest 3
+# 'hello.x' is mentioned explicitly on an unrelated rule.
+run_make_test(q!
+hello.z: %.z: %.x ; @echo $@
+%.x: ;
+unrelated: hello.x
+!, '', "hello.z\n");
+
+unlink('hello.z');
+
+# sv 17374 Ensure double-colon static pattern rules work
+
+touch(qw(a.src b.src));
+
+run_make_test(q!
+all: a.tgt b.tgt
+a.tgt b.tgt:: %.tgt : %.src ; cp $< $@
+!,
+ '', "cp a.src a.tgt\ncp b.src b.tgt\n");
+
+unlink(qw(a.src b.src a.tgt b.tgt));
+
+my @dir = ('', 'lib/'); # With and without last slash.
+my @secondexpansion = ('', '.SECONDEXPANSION:');
+
+# The following combinations are generated with and without second expansion.
+# 1.
+# all: bye.x
+# bye.x: %.x: ...
+#
+# 2.
+# all: lib/bye.x
+# lib/bye.x: %.x: ...
+#
+# 3.
+# all: lib/bye.x
+# lib/bye.x: lib/%.x: ...
+#
+# The following combination is not generated, because there is no rule to
+# build bye.x, no stem substitution takes place, not of interest of this test.
+# 4.
+# all: bye.x
+# bye.x: lib/%.x: ...
+#
+
+for my $se (@secondexpansion) {
+for my $d (@dir) { # The directory of the prerequisite of 'all'.
+for my $r (@dir) { # The directory of the prerequisite in the rule definition.
+(!$d && $r) && next; # Combination 4.
+my $dollar = $se ? '$' : '';
+
+# The prerequisite should only have directory if the prerequisite of 'all' has
+# it and if the prequisite pattern in the rule definition does not have it.
+# That is combination 2.
+my $pdir = $d && !$r ? $d : '';
+
+
+# One func, one %.
+my $prereqs = "${pdir}bye.1";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(firstword %.1); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Multiple funcs, each has one %.
+$prereqs = "${pdir}bye.1 ${pdir}bye.2";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(firstword %.1) $dollar\$(firstword %.2); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Multiple funcs, each has multiple %.
+$prereqs = "${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, %.1 %.2) $dollar\$(wordlist 1, 99, %.3 %.4); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Multiple funcs, each has multiple %, each prerequisite has multiple %.
+$prereqs = "${pdir}bye_%_%.1 ${pdir}bye_%_%.2 ${pdir}bye_%_%.3 ${pdir}bye_%_%.4";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, %_%_%.1 %_%_%.2) $dollar\$(wordlist 1, 99, %_%_%.3 %_%_%.4); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Nested functions.
+$prereqs = "${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, $dollar\$(wordlist 1, 99, %.1 %.2)) $dollar\$(wordlist 1, 99, $dollar\$(wordlist 1,99, %.3 %.4)); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# Multiple funcs, each has multiple words, each word has multiple %, sole %,
+# various corner cases.
+# Make should substitude the first % and only the first % in each word with the
+# stem.
+$prereqs = "${pdir}bye1%2% ${pdir}bye 3${pdir}bye4%5 6${pdir}bye ${pdir}bye7%8 ${pdir}bye9 ${pdir}bye10% 11${pdir}bye12 13";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, %1%2% % 3%4%5 6%) %7%8 %9 $dollar\$(wordlist 1, 99, %10% 11%12) 13; \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+if ($port_type eq 'UNIX') {
+# Test that make does not use some hardcoded array of a finite size on stack.
+# Long prerequisite name. This prerequisite name is over 66K long.
+my $prefix = 'abcdefgh' x 128 x 33; # 33K long.
+my $suffix = 'stuvwxyz' x 128 x 33; # 33K long.
+$prereqs = "${prefix}${pdir}bye${suffix}.1 ${prefix}${pdir}bye${suffix}.2";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(wordlist 1, 99, ${prefix}%${suffix}.1 ${prefix}%${suffix}.2); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+}
+
+
+# Empty stem.
+$prereqs = "${pdir}.1";
+run_make_test("
+$se
+.PHONY: $prereqs
+all: ${d}bye.x
+${d}bye.x: $r%bye.x: $dollar\$(firstword %.1); \$(info \$@ from \$^)
+", '', "${d}bye.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
+# A word expands to an empty prerequisite.
+run_make_test("
+$se
+all: ${d}bye.x
+${d}bye.x: $r%.x: $dollar\$(%); \$(info \$@ from \$^)
+", '', "${d}bye.x from \n#MAKE#: Nothing to be done for 'all'.\n");
+
+}
+}
+}
+
+# Escaped %.
+# The following combinations are generated without second expansion.
+# 1.
+# all: the%weird\\_hello_pattern\\.x
+# the\\%weird\\_hello_pattern\\.x: the\\%weird\\_%_pattern\\.x: ...
+#
+# 2.
+# all: lib/the%weird\\_hello_pattern\\.x
+# lib/the\\%weird\\_hello_pattern\\.x: lib/the\\%weird\\_%_pattern\\.x: ...
+#
+# Other combinations or second expansion are not tested, because escaped % is
+# not implemented for those.
+
+for my $d (@dir) {
+my $prereqs = "${d}the%weird\\\\_hello_pattern%\\\\.1 ${d}the%weird\\\\_hello_pattern%\\\\.2";
+run_make_test("
+.PHONY: $prereqs
+all: ${d}the%weird\\\\_hello_pattern\\\\.x
+${d}the\\%weird\\\\_hello_pattern\\\\.x: ${d}the\\%weird\\\\_%_pattern\\\\.x: \$(wordlist 1, 99, ${d}the\\%weird\\\\_%_pattern%\\\\.1 ${d}the\\%weird\\\\_%_pattern%\\\\.2); \$(info \$@ from \$^)
+", '', "${d}the%weird\\\\_hello_pattern\\\\.x from $prereqs\n#MAKE#: Nothing to be done for 'all'.\n");
+}
+
1;
diff --git a/tests/scripts/features/targetvars b/tests/scripts/features/targetvars
index 2929b2c..5088251 100644
--- a/tests/scripts/features/targetvars
+++ b/tests/scripts/features/targetvars
@@ -12,8 +12,9 @@ export BAR = bar
one: override FOO = one
one two: ; @echo $(FOO) $(BAR)
two: BAR = two
+.RECIPEPREFIX = >
three: ; BAR=1000
- @echo $(FOO) $(BAR)
+> @echo $(FOO) $(BAR)
# Some things that shouldn not be target vars
funk : override
funk : override adelic
@@ -86,7 +87,6 @@ run_make_test(undef, "foo.q bar.q", "qvar = rvar\nqvar =\n");
run_make_test(undef, "foo.t bar.s", "qvar = qvar\nqvar =\n");
-
# TEST #8
# For PR/1378: Target-specific vars don't inherit correctly
@@ -183,7 +183,7 @@ run_make_test(undef, 'foo PATTERN=yes', "ok ok foo pat\nok ok foo pat\n");
# (> make default buffer length)
run_make_test('
-base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if [ -f "build_information.generate" ]; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi )
+base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if test -f "build_information.generate" ; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi )
deals_changed_since: ; @echo $(BUILD_OBJ)
',
@@ -270,17 +270,158 @@ all: ; $sname >/dev/null
# Don't use the general PATH if not found on the target path
-$extraENV{PATH} = "$ENV{PATH}:sd";
+$ENV{PATH} = "$ENV{PATH}:sd";
+
+my ($ernum, $erstr);
+if ($port_type eq 'W32') {
+ $ernum = 1;
+ $erstr = "'$sname' is not recognized as an internal or external command,\noperable program or batch file.";
+} else {
+ $ernum = 127;
+ $erstr = "#MAKE#: $sname: $ERR_no_such_file";
+}
run_make_test(qq!
all: PATH := ..
all: ; $sname
!,
- '', "$sname\n#MAKE#: $sname: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:3: all] Error 127", 512);
+ '', "$sname\n$erstr\n#MAKE#: *** [#MAKEFILE#:3: all] Error $ernum", 512);
unlink("sd/$sname");
rmdir ('sd');
+# SV 59230: Conditional (non-)assignment of target-specific variables should
+# preserve export settings.
+
+$ENV{hello} = 'moon';
+run_make_test(q!
+all:; @echo hello=$$hello
+dummy: hello?=world
+!,
+ '', 'hello=moon');
+
+# SV 59230: Assignment of a global variable should not affect export of a
+# target specific variable.
+
+$ENV{hello} = "moon";
+run_make_test(q!
+all:; @echo hello=$$hello
+hello=sun
+dummy: hello?=world
+!,
+ '', 'hello=sun');
+
+# Support target-specific unexport
+
+$ENV{hello} = "moon";
+run_make_test(q!
+unexport hello=sun
+all: base exp
+base exp: ; @echo hello=$$hello
+exp: export hello=world
+!,
+ '', "hello=\nhello=world\n");
+
+$ENV{hello} = "moon";
+run_make_test(q!
+hello=sun
+all: base exp
+base exp: ; @echo hello=$$hello
+exp: unexport hello=world
+!,
+ '', "hello=sun\nhello=\n");
+
+run_make_test(q!
+all:; @echo hello=$$hello
+unexport hello=sun
+dummy: hello?=world
+!,
+ '', 'hello=');
+
+$ENV{hello} = "moon";
+run_make_test(q!
+all:; @echo hello=$$hello
+hello=sun
+dummy: unexport hello=world
+!,
+ '', 'hello=sun');
+
+run_make_test(q!
+all: mid
+mid: base
+
+ifeq ($(midexport),export)
+mid: export hello=mid
+else ifeq ($(midexport),unexport)
+mid: unexport hello=mid
+else
+mid: hello=mid
+endif
+
+ifeq ($(baseexport),export)
+base: export hello=base
+else ifeq ($(baseexport),unexport)
+base: unexport hello=base
+else
+base: hello=base
+endif
+
+all mid base:; @echo $@ make=$(hello) shell=$$hello
+!,
+ '', "base make=base shell=\nmid make=mid shell=\nall make= shell=\n");
+
+# Test base settings with env var
+$ENV{hello} = "environ";
+run_make_test(undef,
+ '', "base make=base shell=base\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'baseexport=export', "base make=base shell=base\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'baseexport=unexport', "base make=base shell=\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+# Test mid settings with env var
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'midexport=export', "base make=base shell=base\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'midexport=export baseexport=unexport', "base make=base shell=\nmid make=mid shell=mid\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'midexport=unexport', "base make=base shell=\nmid make=mid shell=\nall make=environ shell=environ\n");
+
+$ENV{hello} = "environ";
+run_make_test(undef,
+ 'midexport=unexport baseexport=export', "base make=base shell=base\nmid make=mid shell=\nall make=environ shell=environ\n");
+
+# Test base settings without env var
+run_make_test(undef,
+ 'baseexport=export', "base make=base shell=base\nmid make=mid shell=\nall make= shell=\n");
+
+run_make_test(undef,
+ 'baseexport=unexport', "base make=base shell=\nmid make=mid shell=\nall make= shell=\n");
+
+# Test mid settings with env var
+run_make_test(undef,
+ 'midexport=export', "base make=base shell=base\nmid make=mid shell=mid\nall make= shell=\n");
+
+run_make_test(undef,
+ 'midexport=export baseexport=unexport', "base make=base shell=\nmid make=mid shell=mid\nall make= shell=\n");
+
+run_make_test(undef,
+ 'midexport=unexport', "base make=base shell=\nmid make=mid shell=\nall make= shell=\n");
+
+run_make_test(undef,
+ 'midexport=unexport baseexport=export', "base make=base shell=base\nmid make=mid shell=\nall make= shell=\n");
+
+
+
# TEST #19: Test define/endef variables as target-specific vars
# run_make_test('
@@ -296,7 +437,3 @@ rmdir ('sd');
# '', "local\n");
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/features/temp_stdin b/tests/scripts/features/temp_stdin
new file mode 100644
index 0000000..b06df53
--- /dev/null
+++ b/tests/scripts/features/temp_stdin
@@ -0,0 +1,118 @@
+# -*-mode: perl-*-
+
+$description = "Test handling of temporary file created from stdin.";
+
+# These tests rely on the test_driver checking for leftover temporary content
+
+create_file('input.mk', "world:=1\n");
+create_file('bye.mk', "moon:=2\n");
+
+# sv 62118,62145.
+# Test that makes leaves no temp file when make code is piped to stdin and -v,
+# -h or an invalid option is specified.
+my @opts = ('-v', '-h', '--nosuchopt');
+my @exit_codes = (0, 0, 512);
+for my $i (0 .. $#opts) {
+ close(STDIN);
+ open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+ run_make_test(q!
+all:; $(info hello world)
+!,
+ "$opts[$i] -f-", "/uilt for /", $exit_codes[$i]);
+}
+
+# sv 62118,62145.
+# Test that a stdin temp file is removed.
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+run_make_test(q!
+all:; $(info world=$(world))
+!,
+ '-f-', "world=1\n#MAKE#: 'all' is up to date.\n");
+
+# sv 62118,62145.
+# Test that a stdin temp file is removed, even when make re-execs.
+# Also test that make honors TMPDIR to create the temp file.
+# Ensure touching bye.mk causes re-exec.
+&utouch(-600, 'bye.mk');
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+run_make_test(q!
+include bye.mk
+all:; $(info hello)
+$(MAKE_RESTARTS)bye.mk: force; touch $@
+force:
+!,
+ '-R --debug=b -f-', "/Re-executing.+?--temp-stdin=\Q$temppath\E/");
+
+if ($port_type eq 'UNIX') {
+# POSIX doesn't require sh to set PPID so test this
+my $cmd = create_command();
+add_options($cmd, '-f', '/dev/null', '-E', q!all:;@echo $$PPID!);
+my $fout = 'ppidtest.out';
+run_command_with_output($fout, @$cmd);
+$_ = read_file_into_string($fout);
+chomp($_);
+if (/^[0-9]+$/) {
+use POSIX ();
+
+# sv 63157.
+# Test that make removes the temporary file which holds make code from stdin,
+# even when a signal is received.
+# include bye.mk and bye.mk: rule is needed to cause make to keep the temporary
+# file for re-exec. Without re-exec make will remove the file before the signal
+# arrives.
+# sleep is needed to let make write its "... Terminated" message to the log
+# file.
+&utouch(-600, 'bye.mk');
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+run_make_test(q!
+include bye.mk
+pid:=$(shell echo $$PPID)
+all:;
+bye.mk: force; @kill -TERM $(pid) && sleep 16
+force:
+!, '-f-', '/#MAKE#: \*\*\* \[#MAKEFILE#:5: bye.mk] Terminated/', POSIX::SIGTERM);
+}
+unlink($fout);
+
+# sv 62118,62145.
+# Test that a stdin temp file is removed, when execvp fails to re-exec make.
+# In order to cause execvp to fail, copy the tested make binary to the temp
+# directory and take away the 'x' bit.
+use File::Spec;
+use File::Copy;
+
+my $tmakedir = File::Spec->catfile($cwdpath, 'tmakedir');
+mkdir($tmakedir, 0770);
+my $makecopy = File::Spec->catfile($tmakedir, 'make');
+copy("$mkpath", $makecopy);
+# Set file mode bits, because perl copy won't.
+chmod 0700, $makecopy;
+
+my @make_orig = @make_command;
+@make_command = ($makecopy);
+
+# Ensure touching bye.mk causes re-exec.
+&utouch(-600, 'bye.mk');
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+run_make_test("
+include bye.mk
+all:; \$(info hello)
+\$(MAKE_RESTARTS)bye.mk: force; touch \$@ && chmod u-x $makecopy
+force:
+",
+ "-f-", "touch bye.mk && chmod u-x $makecopy\nmake: $makecopy: $ERR_nonexe_file\n", 32512);
+
+@make_command = @make_orig;
+unlink($makecopy);
+rmdir($tmakedir);
+}
+
+close(STDIN);
+unlink('input.mk', 'bye.mk');
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/varnesting b/tests/scripts/features/varnesting
index d8f3ffb..0fbb332 100644
--- a/tests/scripts/features/varnesting
+++ b/tests/scripts/features/varnesting
@@ -9,8 +9,7 @@ variable2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z)))
-all:
- @echo $(a)
+all: ; @echo $(a)
',
'', "Hello\n");
@@ -21,15 +20,8 @@ all:
run_make_test('
VARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE)
-wololo:
- @$(VARIABLE)
+wololo: ; @$(VARIABLE)
',
'', "hi\n");
1;
-
-
-
-
-
-
diff --git a/tests/scripts/features/vpath b/tests/scripts/features/vpath
index ec24165..7c034b5 100644
--- a/tests/scripts/features/vpath
+++ b/tests/scripts/features/vpath
@@ -1,65 +1,34 @@
# -*-perl-*-
-$description = "The following test creates a makefile to test the \n"
- ."vpath directive which allows you to specify a search \n"
- ."path for a particular class of filenames, those that\n"
- ."match a particular pattern.";
-
-$details = "This tests the vpath directive by specifying search directories\n"
- ."for one class of filenames with the form: vpath pattern directories"
- ."\nIn this test, we specify the working directory for all files\n"
- ."that end in c or h. We also test the variables $@ (which gives\n"
- ."target name) and $^ (which is a list of all dependencies \n"
- ."including the directories in which they were found). It also\n"
- ."uses the function firstword used to extract just the first\n"
- ."dependency from the entire list.";
-
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "vpath %.c foo\n";
-print MAKEFILE "vpath %.c $workdir\n";
-print MAKEFILE "vpath %.h $workdir\n";
-print MAKEFILE "objects = main.o kbd.o commands.o display.o insert.o\n";
-print MAKEFILE "edit: \$(objects)\n";
-print MAKEFILE "\t\@echo cc -o \$@ \$^\n";
-print MAKEFILE "main.o : main.c defs.h\n";
-print MAKEFILE "\t\@echo cc -c \$(firstword \$^)\n";
-print MAKEFILE "kbd.o : kbd.c defs.h command.h\n";
-print MAKEFILE "\t\@echo cc -c kbd.c\n";
-print MAKEFILE "commands.o : command.c defs.h command.h\n";
-print MAKEFILE "\t\@echo cc -c commands.c\n";
-print MAKEFILE "display.o : display.c defs.h buffer.h\n";
-print MAKEFILE "\t\@echo cc -c display.c\n";
-print MAKEFILE "insert.o : insert.c defs.h buffer.h\n";
-print MAKEFILE "\t\@echo cc -c insert.c\n";
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
+$description = "Test vpath for particular classes of filenames.";
+$details = "";
@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
- "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
- "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
- "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
- "$workdir${pathsep}command.c");
+ "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
+ "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+ "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
+ "$workdir${pathsep}command.c");
&touch(@files_to_touch);
-&run_make_with_options($makefile,"",&get_logfile);
-
-# Create the answer to what should be produced by this Makefile
-$answer = "cc -c $workdir${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n"
- ."cc -c display.c\n"
- ."cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o "
- ."insert.o\n";
+run_make_test(q!
+vpath %.c foo
+vpath %.c #WORK#
+vpath %.h #WORK#
+objects = main.o kbd.o commands.o display.o insert.o
+edit: $(objects) ; @echo cc -o $@ $^
+main.o : main.c defs.h ; @echo cc -c $(firstword $^)
+kbd.o : kbd.c defs.h command.h ; @echo cc -c kbd.c
+commands.o : command.c defs.h command.h ; @echo cc -c commands.c
+display.o : display.c defs.h buffer.h ; @echo cc -c display.c
+insert.o : insert.c defs.h buffer.h ; @echo cc -c insert.c
+!,
+ '', "cc -c $workdir${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n"
+ ."cc -c display.c\ncc -c insert.c\n"
+ ."cc -o edit main.o kbd.o commands.o display.o insert.o\n");
-if (&compare_output($answer,&get_logfile(1)))
-{
- unlink @files_to_touch;
-}
+unlink(@files_to_touch);
# TEST 2: after vpath lookup ensure we don't get incorrect circular dependency
# warnings due to change of struct file ptr. Savannah bug #13529.
@@ -78,4 +47,68 @@ vpath-d/fail.te:
rmdir('vpath-d');
+# Test VPATH vs vpath
+
+run_make_test(q!
+VPATH = #WORK#:#PWD#
+vpath %.c foo
+vpath %.c #WORK#
+vpath %.c #PWD#
+vpath %.h #WORK#
+vpath %.c
+vpath
+all: ; @echo ALL IS WELL
+!,
+ '', "ALL IS WELL\n");
+
+# Test interaction of -lfoo and vpath
+
+my @dirs_to_make = qw(a1 b1 a2 b2 b3);
+for my $d (@dirs_to_make) {
+ mkdir($d, 0777);
+}
+
+my @files_to_touch = ("a1${pathsep}lib1.a",
+ "a1${pathsep}libc.a",
+ "b1${pathsep}lib1.so",
+ "a2${pathsep}lib2.a",
+ "b2${pathsep}lib2.so",
+ "lib3.a",
+ "b3${pathsep}lib3.so");
+&touch(@files_to_touch);
+
+my $answer = "a1${pathsep}lib1.a a1${pathsep}libc.a " .
+ "a2${pathsep}lib2.a lib3.a\n";
+if ($port_type eq 'VMS-DCL') {
+ $answer =~ s/ /,/g;
+}
+
+run_make_test('
+vpath %.h b3
+vpath %.a a1
+vpath %.so b1
+vpath % a2 b2
+vpath % b3
+all: -l1 -lc -l2 -l3; @echo $^
+',
+ '', $answer);
+
+unlink(@files_to_touch);
+for my $d (@dirs_to_make) {
+ rmdir($d);
+}
+
+# Check that if we find find files with VPATH, we don't do pattern search
+
+mkdir("vpa");
+
+run_make_test(q!
+VPATH = vpa
+%.x: ; @echo pattern $@
+vpa/foo.x: ; @echo vpath $@
+!,
+ 'foo.x', "vpath vpa/foo.x\n");
+
+rmdir("vpa");
+
1;
diff --git a/tests/scripts/features/vpath2 b/tests/scripts/features/vpath2
deleted file mode 100644
index c8de29b..0000000
--- a/tests/scripts/features/vpath2
+++ /dev/null
@@ -1,45 +0,0 @@
-$description = "This is part 2 in a series to test the vpath directive\n"
- ."It tests the three forms of the directive:\n"
- ." vpath pattern directive\n"
- ." vpath pattern (clears path associated with pattern)\n"
- ." vpath (clears all paths specified with vpath)\n";
-
-$details = "This test simply adds many search paths using various vpath\n"
- ."directive forms and clears them afterwards. It has a simple\n"
- ."rule to print a message at the end to confirm that the makefile\n"
- ."ran with no errors.\n";
-
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "VPATH = $workdir:$scriptdir\n";
-print MAKEFILE "vpath %.c foo\n";
-print MAKEFILE "vpath %.c $workdir\n";
-print MAKEFILE "vpath %.c $scriptdir\n";
-print MAKEFILE "vpath %.h $workdir\n";
-print MAKEFILE "vpath %.c\n";
-print MAKEFILE "vpath\n";
-print MAKEFILE "all:\n";
-print MAKEFILE "\t\@echo ALL IS WELL\n";
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile,"",&get_logfile);
-
-# Create the answer to what should be produced by this Makefile
-$answer = "ALL IS WELL\n";
-
-&compare_output($answer,&get_logfile(1));
-
-1;
-
-
-
-
-
-
-
-
-
diff --git a/tests/scripts/features/vpath3 b/tests/scripts/features/vpath3
deleted file mode 100644
index 839fb72..0000000
--- a/tests/scripts/features/vpath3
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*-perl-*-
-
-$description = "Test the interaction of the -lfoo feature and vpath";
-$details = "";
-
-my @dirs_to_make = qw(a1 b1 a2 b2 b3);
-for my $d (@dirs_to_make) {
- mkdir($d, 0777);
-}
-
-my @files_to_touch = ("a1${pathsep}lib1.a",
- "a1${pathsep}libc.a",
- "b1${pathsep}lib1.so",
- "a2${pathsep}lib2.a",
- "b2${pathsep}lib2.so",
- "lib3.a",
- "b3${pathsep}lib3.so");
-&touch(@files_to_touch);
-
-my $answer = "a1${pathsep}lib1.a a1${pathsep}libc.a " .
- "a2${pathsep}lib2.a lib3.a\n";
-if ($port_type eq 'VMS-DCL') {
- $answer =~ s/ /,/g;
-}
-
-run_make_test('
-vpath %.h b3
-vpath %.a a1
-vpath %.so b1
-vpath % a2 b2
-vpath % b3
-all: -l1 -lc -l2 -l3; @echo $^
-',
- '', $answer);
-
-unlink(@files_to_touch);
-for my $d (@dirs_to_make) {
- rmdir($d);
-}
-
-1;
diff --git a/tests/scripts/features/vpathgpath b/tests/scripts/features/vpathgpath
index 5e6217b..5c5996c 100644
--- a/tests/scripts/features/vpathgpath
+++ b/tests/scripts/features/vpathgpath
@@ -40,7 +40,7 @@ close(MAKEFILE);
$off = -500;
-sub touchfiles {
+sub gtouchfiles {
foreach (@_) {
($f = $_) =~ s,VP/,$VP,g;
&utouch($off, $f);
@@ -51,7 +51,7 @@ sub touchfiles {
# Run the general-case test
-&touchfiles("VP/foo.d", "VP/bar.d", "VP/foo.c", "VP/bar.c", "foo.b", "bar.d");
+&gtouchfiles("VP/foo.d", "VP/bar.d", "VP/foo.c", "VP/bar.c", "foo.b", "bar.d");
&run_make_with_options($makefile,"general",&get_logfile());
diff --git a/tests/scripts/features/vpathplus b/tests/scripts/features/vpathplus
index 978aecb..da16983 100644
--- a/tests/scripts/features/vpathplus
+++ b/tests/scripts/features/vpathplus
@@ -5,13 +5,23 @@ $details = "";
$VP = "$workdir$pathsep";
-open(MAKEFILE,"> $makefile");
+@touchedfiles = ();
+
+$off = -500;
-# The Contents of the MAKEFILE ...
+sub touchfiles {
+ foreach (@_) {
+ &utouch($off, $_);
+ $off += 10;
+ push(@touchedfiles, $_);
+ }
+}
-print MAKEFILE "VPATH = $VP\n";
+&touchfiles("$VP/foo.d", "$VP/bar.d", "$VP/foo.c", "$VP/bar.c", "foo.b", "bar.d");
-print MAKEFILE <<'EOMAKE';
+# Run the general-case test
+
+run_make_test(qq!VPATH = $VP! . q!
.SUFFIXES: .a .b .c .d
.PHONY: general rename notarget intermediate
@@ -20,12 +30,9 @@ print MAKEFILE <<'EOMAKE';
%.c:
%.d:
-%.a : %.b
- cat $^ > $@
-%.b : %.c
- cat $^ > $@ 2>/dev/null || exit 1
-%.c :: %.d
- cat $^ > $@
+%.a : %.b ; cat $^ > $@
+%.b : %.c ; cat $^ > $@ 2>/dev/null || exit 1
+%.c :: %.d ; cat $^ > $@
# General testing info:
@@ -39,71 +46,32 @@ rename: $(VPATH)/foo.c foo.d
# Target not made testing info:
notarget: notarget.b
-notarget.c: notarget.d
- -@echo "not creating $@ from $^"
+notarget.c: notarget.d ; -@echo "not creating $@ from $^"
# Intermediate files:
intermediate: inter.a
-
-EOMAKE
-
-close(MAKEFILE);
-
-@touchedfiles = ();
-
-$off = -500;
-
-sub touchfiles {
- foreach (@_) {
- &utouch($off, $_);
- $off += 10;
- push(@touchedfiles, $_);
- }
-}
-
-# Run the general-case test
-
-&touchfiles("$VP/foo.d", "$VP/bar.d", "$VP/foo.c", "$VP/bar.c", "foo.b", "bar.d");
-
-&run_make_with_options($makefile,"general",&get_logfile);
+!,
+ 'general', "cat bar.d > bar.c\ncat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1\n");
push(@touchedfiles, "bar.c");
-$answer = "cat bar.d > bar.c
-cat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1
-";
-&compare_output($answer,&get_logfile(1));
-
# Test rules that don't make the target correctly
&touchfiles("$VP/notarget.c", "notarget.b", "notarget.d");
-&run_make_with_options($makefile,"notarget",&get_logfile,512);
-
-$answer = "not creating notarget.c from notarget.d
-cat notarget.c > notarget.b 2>/dev/null || exit 1
-$make_name: *** [$makefile:13: notarget.b] Error 1
-";
-
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, 'notarget', "not creating notarget.c from notarget.d\ncat notarget.c > notarget.b 2>/dev/null || exit 1\n#MAKE#: *** [#MAKEFILE#:11: notarget.b] Error 1\n", 512);
# Test intermediate file handling (part 1)
&touchfiles("$VP/inter.d");
-&run_make_with_options($makefile,"intermediate",&get_logfile);
-
-push(@touchedfiles, "inter.a", "inter.b");
-
my $be = pack("L", 1) eq pack("N", 1);
my $intfiles = $be ? "inter.c inter.b" : "inter.b inter.c";
-$answer = "cat ${VP}inter.d > inter.c
-cat inter.c > inter.b 2>/dev/null || exit 1
-cat inter.b > inter.a
-rm $intfiles
-";
-&compare_output($answer,&get_logfile(1));
+
+run_make_test(undef, 'intermediate', "cat ${VP}inter.d > inter.c\ncat inter.c > inter.b 2>/dev/null || exit 1\ncat inter.b > inter.a\nrm $intfiles\n");
+
+push(@touchedfiles, "inter.a", "inter.b");
# Test intermediate file handling (part 2)
@@ -111,21 +79,10 @@ rm $intfiles
&utouch(-10, "$VP/inter.b");
&touch("$VP/inter.d");
-push(@touchedfiles, "$VP/inter.b", "$VP/inter.d");
-
-&run_make_with_options($makefile,"intermediate",&get_logfile);
+run_make_test(undef, 'intermediate', "cat ${VP}inter.d > inter.c\ncat inter.c > inter.b 2>/dev/null || exit 1\ncat inter.b > inter.a\nrm inter.c\n");
-$answer = "cat ${VP}inter.d > inter.c
-cat inter.c > inter.b 2>/dev/null || exit 1
-cat inter.b > inter.a
-rm inter.c
-";
-&compare_output($answer,&get_logfile(1));
+push(@touchedfiles, "$VP/inter.b", "$VP/inter.d");
unlink @touchedfiles unless $keep;
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/functions/eval b/tests/scripts/functions/eval
index 90513bd..a3fba87 100644
--- a/tests/scripts/functions/eval
+++ b/tests/scripts/functions/eval
@@ -127,7 +127,7 @@ EOF
close(MAKEFILE);
-$extraENV{EVAR} = '1';
+$ENV{EVAR} = '1';
&run_make_with_options($makefile4, "", &get_logfile);
$answer = "OK\n";
&compare_output($answer,&get_logfile(1));
diff --git a/tests/scripts/functions/file b/tests/scripts/functions/file
index eaabd3a..50948a0 100644
--- a/tests/scripts/functions/file
+++ b/tests/scripts/functions/file
@@ -118,6 +118,77 @@ x:;@echo '$(X1)'; echo '$(A)'; echo '$(B)'
unlink('file.out');
+# Read an empty file.
+touch("file.out");
+run_make_test(q!# empty file
+X1 := x$(file <file.out)y
+x:;@echo '$(X1)'
+!,
+ '', "xy\n");
+
+unlink('file.out');
+
+# Read a file whose full contents is a newline.
+create_file('file.out', "\n");
+run_make_test(q!# <nl>
+X1 := x$(file <file.out)y
+x:;@echo '$(X1)'
+!,
+ '', "xy\n");
+
+unlink('file.out');
+
+# Read a file which does not end with a newline.
+create_file('file.out', "hello");
+# echo prints a trailig newline, because run_make_test appends a newline.
+run_make_test(q!# hello
+X1 := x$(file <file.out)y
+x:;@echo $(X1)
+!,
+ '', "xhelloy\n");
+
+unlink('file.out');
+
+# Read a file which ends with a newline.
+create_file('file.out', "hello\n");
+# echo prints a trailig newline, because run_make_test appends a newline.
+run_make_test(q!# hello<nl>
+X1 := x$(file <file.out)y
+x:;@echo '$(X1)'
+!,
+ '', "xhelloy\n");
+
+
+unlink('file.out');
+
+# Read a file which ends with multiple newlines.
+create_file('file.out', "hello\n\n");
+run_make_test(q!# hello<nl><nl>
+X1 := x$(file <file.out)y
+export X1
+x:;@echo "$$X1"
+!,
+ '', "xhello\ny\n");
+
+unlink('file.out');
+
+# Read a file whose contents exceed 200 bytes.
+# 200 is the initial size of variable_buffer.
+# File bigger than 200 bytes causes a realloc.
+# The size of the file in this test not only exceeds 200 bytes, it exceeds 65k.
+# Use $(info ...) here to avoid command line limitations
+
+my $s = "hello world, hello world, hello world, hello world, hello world";
+my $answer = $s x 2000;
+create_file('file.out', $answer);
+run_make_test(q!# <hugestring>
+X1 := x$(file <file.out)y
+x:;@$(info $(X1))
+!,
+ '', "x${answer}y\n#MAKE#: 'x' is up to date.\n");
+
+unlink('file.out');
+
# Reading from non-existent file
run_make_test(q!
X1 := $(file <file.out)
diff --git a/tests/scripts/functions/filter-out b/tests/scripts/functions/filter-out
index 1fe4819..dec5343 100644
--- a/tests/scripts/functions/filter-out
+++ b/tests/scripts/functions/filter-out
@@ -27,6 +27,22 @@ all: ; @echo '$(files1) $(files2)'
!,
'', "foo.elc foo.elc\n");
+# Force use of hash (see function.c:func_filter_filterout for params)
+
+my $base = 'foo.1 foo.2 foo.3 foo.4 foo.5 foo.6 foo.7 foo.8 foo.9 foo.10';
+
+my $base10 = join(' ', ($base) x 10);
+my $out3 = join(' ', ('foo.3') x 10);
+my $out456 = join(' ', ('foo.4 foo.5 foo.6') x 10);
+
+run_make_test("words := $base10" . q!
+files1 := $(filter %.3, $(words))
+files2 := $(filter %.4 foo.5 foo.6, $(words))
+all: ; @echo '$(files1) $(files2)'
+!,
+ '', "$out3 $out456\n");
+
+
# Escaped patterns
run_make_test(q!all:;@echo '$(filter foo\%bar,foo%bar fooXbar)'!,
'', "foo%bar\n");
diff --git a/tests/scripts/functions/foreach b/tests/scripts/functions/foreach
index 9badc52..6a06109 100644
--- a/tests/scripts/functions/foreach
+++ b/tests/scripts/functions/foreach
@@ -14,7 +14,7 @@ types of foreach loops are tested\n";
# TEST 0
# Set an environment variable that we can test in the makefile.
-$extraENV{FOOFOO} = 'foo foo';
+$ENV{FOOFOO} = 'foo foo';
run_make_test("space = ' '".'
null :=
@@ -31,8 +31,6 @@ for2: ; @echo $(fe)',
"undefined file default file environment default file command line override automatic automatic
foo.o bletch.o null.o @.o garf.o .o .o undefined.o file.o default.o file.o environment.o default.o file.o command.o line.o override.o automatic.o automatic.o");
-delete $extraENV{FOOFOO};
-
# TEST 1: Test that foreach variables take precedence over global
# variables in a global scope (like inside an eval). Tests bug #11913
diff --git a/tests/scripts/functions/intcmp b/tests/scripts/functions/intcmp
new file mode 100644
index 0000000..24e25b2
--- /dev/null
+++ b/tests/scripts/functions/intcmp
@@ -0,0 +1,72 @@
+# -*-perl-*-
+$description = "Test the intcmp function.\n";
+
+$details = "Try various uses of intcmp and ensure they all give the correct
+results.\n";
+
+run_make_test('# Negative
+n = -10
+# Zero
+z = 0
+# Positive
+p = 888
+min = -9223372036854775808
+max = 9223372036854775807
+huge = 8857889956778499040639527525992734031025567913257255490371761260681427
+.RECIPEPREFIX = >
+all:
+> @echo 0_1 $(intcmp $n,$n)
+> @echo 0_2 $(intcmp $z,$z)
+> @echo 0_3 $(intcmp -$z,$z)
+> @echo 0_4 $(intcmp $p,$p)
+> @echo 0_5 $(intcmp $n,$z)
+> @echo 0_6 $(intcmp $z,$n)
+> @echo 1_1 $(intcmp $n,$n,$(shell echo lt))
+> @echo 1_2 $(intcmp $n,$z,$(shell echo lt))
+> @echo 1_3 $(intcmp $z,$n,$(shell echo lt))
+> @echo 2_1 $(intcmp $n,$p,lt,ge)
+> @echo 2_2 $(intcmp $z,$z,lt,ge)
+> @echo 2_3 $(intcmp $p,$n,lt,ge)
+> @echo 3_0 $(intcmp $p,$n,lt,eq,)
+> @echo 3_1 $(intcmp $z,$p,lt,eq,gt)
+> @echo 3_2 $(intcmp $p,$z,lt,eq,gt)
+> @echo 3_3 $(intcmp $p,$p,lt,eq,gt)
+> @echo 4_0 $(intcmp $(min),$(max),lt,eq,gt)
+> @echo 4_1 $(intcmp $(max),$(min),lt,eq,gt)
+> @echo 4_2 $(intcmp $(min),$(min),lt,eq,gt)
+> @echo 4_3 $(intcmp $(max),$(max),lt,eq,gt)
+> @echo 5_0 $(intcmp -$(huge),$(huge),lt,eq,gt)
+> @echo 5_1 $(intcmp $(huge),-$(huge),lt,eq,gt)
+> @echo 5_2 $(intcmp -$(huge),-$(huge),lt,eq,gt)
+> @echo 5_3 $(intcmp +$(huge),$(huge),lt,eq,gt)
+', '', "0_1 -10\n0_2 0\n0_3 0\n0_4 888\n0_5\n0_6\n1_1\n1_2 lt\n1_3\n2_1 lt\n2_2 ge\n2_3 ge\n3_0\n3_1 lt\n3_2 gt\n3_3 eq\n4_0 lt\n4_1 gt\n4_2 eq\n4_3 eq\n5_0 lt\n5_1 gt\n5_2 eq\n5_3 eq\n");
+
+# Test error conditions
+
+run_make_test('
+intcmp-e1: ; @echo $(intcmp 12a,1,foo)
+intcmp-e2: ; @echo $(intcmp 0,,foo)
+intcmp-e3: ; @echo $(intcmp -1,)
+intcmp-e4: ; @echo $(intcmp ,55)',
+ 'intcmp-e1',
+ "#MAKEFILE#:2: *** non-numeric first argument to 'intcmp' function: '12a'. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'intcmp-e2',
+ "#MAKEFILE#:3: *** non-numeric second argument to 'intcmp' function: empty value. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'intcmp-e3',
+ "#MAKEFILE#:4: *** non-numeric second argument to 'intcmp' function: empty value. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'intcmp-e4',
+ "#MAKEFILE#:5: *** non-numeric first argument to 'intcmp' function: empty value. Stop.",
+ 512);
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/functions/let b/tests/scripts/functions/let
new file mode 100644
index 0000000..48aec78
--- /dev/null
+++ b/tests/scripts/functions/let
@@ -0,0 +1,111 @@
+# -*-perl-*-
+# $Id$
+
+$description = "Test the let function.";
+
+$details = "This is a test of the let function in gnu make.
+This function destructures a list of values and binds each
+value to a variable name in a list of variable names.
+Superfluous variable names are assigned the empty string and
+the remaining values are assigned to the last variable name.
+The binding holds for the duration of the evaluation of the
+given text and no longer. The general form of the command
+is $(let \$vars,\$list,\$text). Several types of let
+assignments are tested\n";
+
+# check for mismatched var and list word counts
+run_make_test(q!
+a = bad
+b = news
+x = $(let a b,1 2,$a $b)
+y = $(let a,1 2,$a)
+z = $(let a b,1,$a $b)
+all:;@echo 'a=,$a,' 'b=,$b,' 'x=,$x,' 'y=,$y,' 'z=,$z,'
+!,
+ '', "a=,bad, b=,news, x=,1 2, y=,1 2, z=,1 ,\n");
+
+# check for whitespace
+run_make_test(q!
+a = bad
+b = news
+x = $(let a b, 1 2 ,+$a+$b+)
+y = $(let a, 1 2 ,+$a+)
+z = $(let a b, 1 ,+$a+$b+)
+all:;@echo 'a=,$a,' 'b=,$b,' 'x=,$x,' 'y=,$y,' 'z=,$z,'
+!,
+ '', "a=,bad, b=,news, x=,+1+2 +, y=,+1 2 +, z=,+1++,\n");
+
+# Allow empty variable names and empty value list.
+# We still expand the list and body.
+run_make_test('
+null =
+v = $(let ,$(info blankvar),abc)
+x = $(let $(null),$(info side-effect),abc)
+y = $(let y,,$ydef)
+
+all: ; @echo $v/$x/$y',
+ '', "blankvar\nside-effect\nabc/abc/def\n");
+
+# The example macro from the manual.
+run_make_test('
+reverse = $(let first rest,$1,$(if $(rest),$(call reverse,$(rest)) )$(first))
+
+all: ; @echo $(call reverse, \
+ moe miny meeny eeny \
+ )',
+ '', "eeny meeny miny moe\n");
+
+
+# Set an environment variable that we can test in the makefile.
+$ENV{FOOFOO} = 'foo foo';
+
+# Verify masking: expansion outside the scope of let is unaffected.
+run_make_test('
+auto_var = \
+ udef \
+ CC \
+ FOOFOO \
+ MAKE \
+ foo \
+ CFLAGS \
+ WHITE \
+ @ \
+ <
+av = $(foreach var, $(auto_var), $(origin $(var)) )
+foo = bletch null @ garf
+override WHITE := BLACK
+
+define mktarget
+target: foo := $(foo)
+target: ; @echo $(AR)_$(foo)_
+endef
+
+all: auto target
+auto: ; @echo $(let $(auto_var),,$(av)) $(av)
+$(let AR foo,bar foo ,$(eval $(value mktarget)))',
+ '-e WHITE=WHITE CFLAGS=',
+ "automatic automatic automatic automatic automatic automatic automatic automatic automatic undefined default environment default file command line override automatic automatic
+ar_foo _
+");
+
+
+# Check some error conditions.
+run_make_test('
+x = $(let )
+y = $x
+
+all: ; @echo $y',
+ '',
+ "#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'let'. Stop.",
+ 512);
+
+run_make_test('
+x = $(let x,y)
+y := $x
+
+all: ; @echo $y',
+ '',
+ "#MAKEFILE#:2: *** insufficient number of arguments (2) to function 'let'. Stop.",
+ 512);
+
+1;
diff --git a/tests/scripts/functions/origin b/tests/scripts/functions/origin
index f7b7eb8..9b9fd56 100644
--- a/tests/scripts/functions/origin
+++ b/tests/scripts/functions/origin
@@ -16,26 +16,27 @@ defined per the following list:
'automatic' Automatic variable\n";
# Set an environment variable
-$extraENV{MAKETEST} = 1;
+$ENV{MAKETEST} = 1;
run_make_test('
foo := bletch garf
auto_var = undefined CC MAKETEST MAKE foo CFLAGS WHITE @
av = $(foreach var, $(auto_var), $(origin $(var)) )
override WHITE := BLACK
+.RECIPEPREFIX = >
all: auto
- @echo $(origin undefined)
- @echo $(origin CC)
- @echo $(origin MAKETEST)
- @echo $(origin MAKE)
- @echo $(origin foo)
- @echo $(origin CFLAGS)
- @echo $(origin WHITE)
- @echo $(origin @)
+> @echo $(origin undefined)
+> @echo $(origin CC)
+> @echo $(origin MAKETEST)
+> @echo $(origin MAKE)
+> @echo $(origin foo)
+> @echo $(origin CFLAGS)
+> @echo $(origin WHITE)
+> @echo $(origin @)
auto :
- @echo $(av)',
- '-e WHITE=WHITE CFLAGS=',
- 'undefined default environment default file command line override automatic
+> @echo $(av)',
+ '-e WHITE=WHITE CFLAGS=',
+ 'undefined default environment default file command line override automatic
undefined
default
environment
@@ -45,7 +46,4 @@ command line
override
automatic');
-# Reset an environment variable
-delete $extraENV{MAKETEST};
-
1;
diff --git a/tests/scripts/functions/shell b/tests/scripts/functions/shell
index 5986529..d89a0c8 100644
--- a/tests/scripts/functions/shell
+++ b/tests/scripts/functions/shell
@@ -32,24 +32,98 @@ foo: ; echo '$(FOO)'
!,
'', "echo '#'\n#\n");
-# Test shells inside exported environment variables.
-# This is the test that fails if we try to put make exported variables into
-# the environment for a $(shell ...) call.
+# Test that exported variables are passed to $(shell ...)
+$ENV{FOO} = 'baz';
+run_make_test(q!
+OUT = $(shell echo $$FOO)
+foo: ; @echo '$(OUT)'
+!,
+ '', 'baz');
+
+$ENV{FOO} = 'baz';
+run_make_test(q!
+FOO = bar
+OUT = $(shell echo $$FOO)
+foo: ; @echo '$(OUT)'
+!,
+ '', 'bar');
+
+run_make_test(q!
+export FOO = bar
+OUT = $(shell echo $$FOO)
+foo: ; @echo '$(OUT)'
+!,
+ '', 'bar');
+
+# Test shells inside exported environment variables, simply expanded.
+run_make_test('
+export HI := $(shell echo hi)
+.PHONY: all
+all: ; @echo $$HI
+',
+ '','hi');
+
+# Test shells inside exported environment variables. See SV 10593
run_make_test('
export HI = $(shell echo hi)
.PHONY: all
all: ; @echo $$HI
- ','','hi');
+',
+ '',"hi");
+
+$ENV{HI} = 'foo';
+run_make_test('
+HI = $(shell echo hi)
+.PHONY: all
+all: ; @echo $$HI
+',
+ '',"hi");
+
+$ENV{HI} = 'foo';
+run_make_test('
+HI = $(shell echo hi)
+bad := $(HI)
+.PHONY: all
+all: ; @echo $$HI $(bad)
+',
+ '',"hi hi");
+
+# SV 63016: Exported variable that contains a variable containing $(shell...)
+
+run_make_test('
+HI = $(shell echo hi)
+export bad = $(HI)
+.PHONY: all
+all:; : $(HI)
+',
+ '',": hi");
+
+$ENV{HI} = 'outer';
+run_make_test('
+export HI = $(shell echo $$HI)
+.PHONY: all
+all:; @echo $$HI
+',
+ '',"outer");
+
+$ENV{HI} = 'outer';
+run_make_test('
+export HI = $(shell echo $$HI)
+.PHONY: all
+all:; : $(HI)
+',
+ '',": outer");
if ($port_type ne 'W32') {
# Test shell errors in recipes including offset
# This needs to be ported to Windows, or else Windows error messages
# need to converted to look like more normal make errors.
run_make_test('
+.RECIPEPREFIX = >
all:
- @echo hi
- $(shell ./basdfdfsed there)
- @echo $(.SHELLSTATUS)
+>@echo hi
+>$(shell ./basdfdfsed there)
+>@echo $(.SHELLSTATUS)
',
'', "#MAKE#: ./basdfdfsed: $ERR_no_such_file\nhi\n127\n");
@@ -81,10 +155,60 @@ $(shell kill -2 $$$$)
STAT := $(.SHELLSTATUS)
all: ; @echo STAT=$(STAT)
','',"STAT=$ret\n");
+
+ # Test that not-found errors can be redirected
+ if ($ERR_command_not_found) {
+ $_ = $ERR_command_not_found;
+ s/#CMDNAME#/bad-command/g;
+ run_make_test(q!
+out := $(shell bad-command 2>&1)
+all: ; @echo '$(.SHELLSTATUS): $(out)'
+!,
+ '', "127: $_\n");
+ }
+
+ # If we're using pipes for jobserver, then we will close them and not
+ # allow them to be available to sub-makes invoked via $(shell ...)
+ if (exists $FEATURES{'jobserver'}) {
+ run_make_test(q!
+ifeq ($(ELT),)
+default:; @$(MAKE) -f #MAKEFILE# ELT=1
+else ifeq ($(ELT),1)
+OUTPUT := $(shell $(MAKE) -f #MAKEFILE# ELT=2)
+$(info $(OUTPUT))
+default:;: $(ELT)
+else
+default:;: $(ELT)
+endif
+!,
+ '--no-print-directory -j2 --jobserver-style=pipe', "#MAKE#[2]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.\n: 2\n: 1");
+ }
+
+ # This crashes if we use vfork and don't reset environ properly
+ run_make_test(q!
+export PATH = $(shell echo "tests:$$PATH")
+foo = $(shell echo yes)
+
+all:;echo $(foo)
+!,
+ '', "echo yes\nyes\n");
}
-1;
+# If we're not using pipes for jobserver, then they are available in sub-makes
+# invoked by $(shell ...)
+if ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) {
+ run_make_test(q!
+ifeq ($(ELT),)
+default:; @$(MAKE) -f #MAKEFILE# ELT=1
+else ifeq ($(ELT),1)
+OUTPUT := $(shell $(MAKE) -f #MAKEFILE# ELT=2)
+$(info $(OUTPUT))
+default:;: $(ELT)
+else
+default:;: $(ELT)
+endif
+!,
+ '--no-print-directory -j2', ": 2\n: 1");
+}
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
+1;
diff --git a/tests/scripts/functions/word b/tests/scripts/functions/word
index 4dcc940..217e693 100644
--- a/tests/scripts/functions/word
+++ b/tests/scripts/functions/word
@@ -6,43 +6,42 @@ $details = "\
Produce a variable with a large number of words in it,
determine the number of words, and then read each one back.\n";
-open(MAKEFILE,"> $makefile");
-print MAKEFILE <<'EOF';
+run_make_test('
string := word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl
string2 := $(string) $(string) $(string) $(string) $(string) $(string) $(string)
string3 := $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) $(string2)
string4 := $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) $(string3)
+.RECIPEPREFIX = >
all:
- @echo $(words $(string))
- @echo $(words $(string4))
- @echo $(word 1, $(string))
- @echo $(word 100, $(string))
- @echo $(word 1, $(string))
- @echo $(word 1000, $(string3))
- @echo $(wordlist 3, 4, $(string))
- @echo $(wordlist 4, 3, $(string))
- @echo $(wordlist 1, 6, $(string))
- @echo $(wordlist 5, 7, $(string))
- @echo $(wordlist 100, 110, $(string))
- @echo $(wordlist 7, 10, $(string2))
-EOF
-close(MAKEFILE);
-
-&run_make_with_options($makefile, "", &get_logfile);
-$answer = "6\n"
- ."2058\n"
- ."word.pl\n"
- ."\n"
- ."word.pl\n"
- ."\n"
- ."FORCE.pl word.pl\n"
- ."\n"
- ."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n"
- ."generic_test.perl MAKEFILES_variable.pl\n"
- ."\n"
- ."word.pl general_test2.pl FORCE.pl word.pl\n";
-&compare_output($answer, &get_logfile(1));
-
+> @echo $(words $(string))
+> @echo $(words $(string4))
+> @echo $(word 1, $(string))
+> @echo $(word 100, $(string))
+> @echo $(word 1 , $(string))
+> @echo $(word 1000, $(string3))
+> @echo $(word 9223372036854775807, $(string2))
+> @echo $(wordlist 3, 4, $(string))
+> @echo $(wordlist 4, 3, $(string))
+> @echo $(wordlist 1 , 6 , $(string))
+> @echo $(wordlist 5,7, $(string))
+> @echo $(wordlist 100, 110, $(string))
+> @echo $(wordlist 7, 10, $(string2))
+> @echo $(wordlist 9223372036854775807, 0, $(string2))
+', '', "6\n"
+ ."2058\n"
+ ."word.pl\n"
+ ."\n"
+ ."word.pl\n"
+ ."\n"
+ ."\n"
+ ."FORCE.pl word.pl\n"
+ ."\n"
+ ."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n"
+ ."generic_test.perl MAKEFILES_variable.pl\n"
+ ."\n"
+ ."word.pl general_test2.pl FORCE.pl word.pl\n"
+ ."\n"
+);
# Test error conditions
@@ -51,37 +50,43 @@ run_make_test('FOO = foo bar biz baz
word-e1: ; @echo $(word ,$(FOO))
word-e2: ; @echo $(word abc ,$(FOO))
word-e3: ; @echo $(word 1a,$(FOO))
+word-e4: ; @echo $(word 9999999999999999999,$(FOO))
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: *** invalid first argument to 'word' function: empty value. Stop.",
512);
run_make_test(undef,
'word-e2',
- "#MAKEFILE#:4: *** non-numeric first argument to 'word' function: 'abc '. Stop.",
+ "#MAKEFILE#:4: *** invalid 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: *** invalid first argument to 'word' function: '1a'. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'word-e4',
+ "#MAKEFILE#:6: *** invalid first argument to 'word' function: '9999999999999999999' out of range. Stop.",
512);
run_make_test(undef,
'wordlist-e1',
- "#MAKEFILE#:7: *** non-numeric first argument to 'wordlist' function: ''. Stop.",
+ "#MAKEFILE#:8: *** invalid first argument to 'wordlist' function: empty value. Stop.",
512);
run_make_test(undef,
'wordlist-e2',
- "#MAKEFILE#:8: *** non-numeric first argument to 'wordlist' function: 'abc '. Stop.",
+ "#MAKEFILE#:9: *** invalid 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#:10: *** invalid second argument to 'wordlist' function: ' 12a '. Stop.",
512);
# Test error conditions again, but this time in a variable reference
@@ -94,12 +99,12 @@ 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: *** invalid first argument to 'word' function: empty value. Stop.",
512);
run_make_test(undef,
'word-e x=abc',
- "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: 'abc'. Stop.",
+ "#MAKEFILE#:3: *** invalid first argument to 'word' function: 'abc'. Stop.",
512);
run_make_test(undef,
@@ -109,17 +114,17 @@ run_make_test(undef,
run_make_test(undef,
'wordlist-e s= e=',
- "#MAKEFILE#:4: *** non-numeric first argument to 'wordlist' function: ''. Stop.",
+ "#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: empty value. Stop.",
512);
run_make_test(undef,
'wordlist-e s=abc e=',
- "#MAKEFILE#:4: *** non-numeric first argument to 'wordlist' function: 'abc'. Stop.",
+ "#MAKEFILE#:4: *** invalid 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: *** invalid second argument to 'wordlist' function: '12a'. Stop.",
512);
run_make_test(undef,
@@ -127,6 +132,11 @@ run_make_test(undef,
"#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: '0'. Stop.",
512);
+run_make_test(undef,
+ 'wordlist-e s=1 e=-1',
+ "#MAKEFILE#:4: *** invalid second argument to 'wordlist' function: '-1'. Stop.",
+ 512);
+
# TEST #8 -- test $(firstword )
#
@@ -139,8 +149,7 @@ b := $(firstword $(list))
.PHONY: all
-all:
- @test "$a" = "$b" && echo $a
+all: ; @test "$a" = "$b" && echo $a
',
'',
'foo');
@@ -157,8 +166,7 @@ b := $(lastword $(list))
.PHONY: all
-all:
- @test "$a" = "$b" && echo $a
+all: ; @test "$a" = "$b" && echo $a
',
'',
'baz');
diff --git a/tests/scripts/misc/bs-nl b/tests/scripts/misc/bs-nl
index fdf4aab..e8ba046 100644
--- a/tests/scripts/misc/bs-nl
+++ b/tests/scripts/misc/bs-nl
@@ -88,7 +88,6 @@ var:;@echo '|$(var)|'!,
# POSIX: Preserve trailing space
run_make_test(q!
.POSIX:
-x = y
var = he \
llo
var:;@echo '|$(var)|'!,
@@ -97,7 +96,6 @@ var:;@echo '|$(var)|'!,
# POSIX: One space per bs-nl
run_make_test(q!
.POSIX:
-x = y
var = he\
\
\
diff --git a/tests/scripts/misc/close_stdout b/tests/scripts/misc/close_stdout
index b16ea8d..c8c839e 100644
--- a/tests/scripts/misc/close_stdout
+++ b/tests/scripts/misc/close_stdout
@@ -4,6 +4,6 @@ $description = "Make sure make exits with an error if stdout is full.";
-e '/dev/full' or return -1;
-run_make_test('', '-v > /dev/full', '/^#MAKE#: write error/', 256);
+run_make_test("\n", '-v > /dev/full', '/^#MAKE#: write error/', 256);
1;
diff --git a/tests/scripts/misc/fopen-fail b/tests/scripts/misc/fopen-fail
index 2ec9810..18e0b7d 100644
--- a/tests/scripts/misc/fopen-fail
+++ b/tests/scripts/misc/fopen-fail
@@ -2,6 +2,10 @@
$description = "Make sure make exits with an error if fopen fails.";
+# For some reason on Cygwin, make exits with no error message after
+# it recurses for a while.
+$^O =~ /cygwin/ and return -1;
+
# 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.
diff --git a/tests/scripts/misc/general4 b/tests/scripts/misc/general4
index eeb8d10..cfd69a8 100644
--- a/tests/scripts/misc/general4
+++ b/tests/scripts/misc/general4
@@ -94,13 +94,23 @@ all: ; $sname >/dev/null
# Don't use the general PATH if not found on the target path
-$extraENV{PATH} = "$ENV{PATH}:sd";
+$ENV{PATH} = "$ENV{PATH}:sd";
+
+my ($ernum, $erstr);
+
+if ($port_type eq 'W32') {
+ $ernum = 2;
+ $erstr = "process_begin: CreateProcess(NULL, $sname, ...) failed.\nmake (e=2): The system cannot find the file specified.";
+} else {
+ $ernum = 127;
+ $erstr = "#MAKE#: $sname: $ERR_no_such_file";
+}
run_make_test(qq!
PATH := ..
all: ; $sname
!,
- '', "$sname\n#MAKE#: $sname: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:3: all] Error 127", 512);
+ '', "$sname\n$erstr\n#MAKE#: *** [#MAKEFILE#:3: all] Error $ernum", 512);
unlink("sd/$sname");
rmdir('sd');
@@ -110,12 +120,27 @@ rmdir('sd');
create_file($sname, '');
chmod 0755, $sname;
+if ($port_type eq 'W32') {
+ $ernum = -1;
+ $erstr = "";
+} else {
+ $ernum = 127;
+ $erstr = "#MAKE#: $sname: $ERR_no_such_file\n";
+}
+
run_make_test(qq!
PATH := ..
all: ; $sname
!,
- '', "$sname\n#MAKE#: $sname: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:3: all] Error 127", 512);
+ '', "$sname\n$erstr#MAKE#: *** [#MAKEFILE#:3: all] Error $ernum", 512);
unlink($sname);
+# SV 57674: ensure we use a system default PATH if one is not set
+delete $ENV{PATH};
+run_make_test(q!
+a: ; @echo hi
+!,
+ '', "hi\n");
+
1;
diff --git a/tests/scripts/options/dash-I b/tests/scripts/options/dash-I
index 5d2df38..64ee7c5 100644
--- a/tests/scripts/options/dash-I
+++ b/tests/scripts/options/dash-I
@@ -1,6 +1,6 @@
# -*-perl-*-
-$description ="The following test creates a makefile to test the -I option.";
+$description = "The following test creates a makefile to test the -I option.";
$details = "\
This test tests the -I option by including a filename in
@@ -9,53 +9,108 @@ under -I in the command line. Without this option, the make
would fail to find the included file. It also checks to make
sure that the -I option gets passed to recursive makes.";
-$makefile2 = &get_tmpfile;
+use File::Spec;
-open(MAKEFILE,"> $makefile");
+# Create a directory and put a makefile in it.
+# We can't put it in the current directory since that's automatically searched
+# anyway.
+my $subdir = 'idir';
+mkdir($subdir, 0777);
-# The Contents of the MAKEFILE ...
-
-$mf2 = substr ($makefile2, index ($makefile2, $pathsep) + 1);
-print MAKEFILE <<EOF;
-include $mf2
-all:
-\t\@echo There should be no errors for this makefile.
-EOF
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-
-open(MAKEFILE,"> $makefile2");
-
-print MAKEFILE <<EOF;
+my $included = 'ifile.mk';
+my $ipath = File::Spec->catfile($subdir, $included);
+create_file($ipath, "
ANOTHER:
\t\@echo This is another included makefile
recurse:
-\t\$(MAKE) ANOTHER -f $makefile
-EOF
+\t\@\$(MAKE) ANOTHER -f \$(main_makefile)\n");
+
+my $nosuch = "#MAKEFILE#:5: $included: $ERR_no_such_file
+#MAKE#: *** No rule to make target '$included'. Stop.\n";
+
-close(MAKEFILE);
+# Verify that we get an error if we don't have -I
+run_make_test(qq!
+main_makefile := \$(firstword \$(MAKEFILE_LIST))
+all:
+\t\@echo There should be no errors for this makefile
+include $included
+!,
+ '', $nosuch, 512);
+
+# Check basic -I works
+run_make_test(undef, "-I $subdir all",
+ "There should be no errors for this makefile\n");
+
+# Check that the included target works
+run_make_test(undef, "-I $subdir ANOTHER",
+ "This is another included makefile\n");
+
+# Check that -I is passed down through MAKEFLAGS
+run_make_test(undef, "-I $subdir recurse",
+ "#MAKE#[1]: Entering directory '#PWD#'
+This is another included makefile
+#MAKE#[1]: Leaving directory '#PWD#'\n");
-&run_make_with_options($makefile,"-I $workdir all",&get_logfile);
+# Verify that we get an error if we add -I- to delete previous includes
+run_make_test(undef, "-I $subdir -I- all", $nosuch, 512);
-# Create the answer to what should be produced by this Makefile
-$answer = "There should be no errors for this makefile.\n";
-&compare_output($answer,&get_logfile(1));
+# Make another directory with the same name and make sure the right one is
+# chosen if -I- stops the path.
+mkdir('idir2', 0777);
+my $ipath2 = File::Spec->catfile('idir2', $included);
+create_file($ipath2, "This is a bad makefile!!\n");
-$answer = "This is another included makefile\n";
-&run_make_with_options($makefile,"-I $workdir ANOTHER",&get_logfile);
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "-I idir2 -I $subdir ANOTHER",
+ "$included:1: *** missing separator. Stop.\n", 512);
+run_make_test(undef, "-I idir2 -I - -I $subdir ANOTHER",
+ "This is another included makefile\n");
-$answer = subst_make_string("$mkpath ANOTHER -f $makefile
-#MAKE#[1]: Entering directory '#PWD#'
+# Check that -I- is passed down through MAKEFLAGS
+run_make_test(undef, "-I idir2 -I - -I $subdir recurse",
+ "#MAKE#[1]: Entering directory '#PWD#'
This is another included makefile
#MAKE#[1]: Leaving directory '#PWD#'\n");
-&run_make_with_options($makefile,"-I $workdir recurse",&get_logfile);
-&compare_output($answer,&get_logfile(1));
+unlink($ipath2);
+rmdir('idir2');
+
+# The only way to check if -I- voids included directories is to see if a file
+# exists in one and try to include it. We very likely can't add our own files
+# to the default directories since they're probably write-protected. This
+# won't work if none of the default directories contain any files :-/
+
+create_file('defaultdirs.mk', "\$(info \$(.INCLUDE_DIRS))\nall:;\@:\n");
+my $cmd = subst_make_string("#MAKEPATH# -f defaultdirs.mk");
+my @dirs = `$cmd`;
+my $dirs = $dirs[0];
+chomp $dirs;
+unlink('defaultdirs.mk');
+
+my $fn = undef;
+foreach my $dn (split ' ', $dirs) {
+ # On Windows the default is "." which is bogus!
+ if ($dn ne '.') {
+ my @files = glob(File::Spec->catfile($dn, "*"));
+ if (@files) {
+ (undef, undef, $fn) = File::Spec->splitpath($files[0]);
+ last;
+ }
+ }
+}
+
+if ($fn) {
+ run_make_test("
+all:;
+include $fn
+",
+ '-I-', "#MAKEFILE#:3: $fn: $ERR_no_such_file
+#MAKE#: *** No rule to make target '$fn'. Stop.\n", 512);
+}
+
+unlink($ipath);
+rmdir($subdir);
1;
diff --git a/tests/scripts/options/dash-d b/tests/scripts/options/dash-d
new file mode 100644
index 0000000..ec2e39a
--- /dev/null
+++ b/tests/scripts/options/dash-d
@@ -0,0 +1,9 @@
+# -*-perl-*-
+
+$description = "Test make -d option.\n";
+
+# sv 60777.
+# Test that debug output is printed when both -d and --trace are specified.
+run_make_test('all: ; :', '-d --trace', "/GNU Make/");
+
+1;
diff --git a/tests/scripts/options/dash-e b/tests/scripts/options/dash-e
index 17c3fc8..944c39d 100644
--- a/tests/scripts/options/dash-e
+++ b/tests/scripts/options/dash-e
@@ -4,21 +4,12 @@ $description = "The following test creates a makefile to ...";
$details = "";
-$extraENV{GOOGLE} = 'boggle';
+$ENV{GOOGLE} = 'boggle';
-open(MAKEFILE,"> $makefile");
-
-print MAKEFILE <<'EOF';
+run_make_test(q!
GOOGLE = bazzle
all:; @echo "$(GOOGLE)"
-EOF
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile, '-e' ,&get_logfile);
-
-$answer = "boggle\n";
-
-&compare_output($answer,&get_logfile(1));
+!,
+ '-e', "boggle\n");
1;
diff --git a/tests/scripts/options/dash-f b/tests/scripts/options/dash-f
index 3aa4746..ab225ce 100644
--- a/tests/scripts/options/dash-f
+++ b/tests/scripts/options/dash-f
@@ -1,3 +1,4 @@
+# -*-perl-*-
$description = "The following test tests that if you specify greater \n"
."than one '-f makefilename' on the command line, \n"
."that make concatenates them. This test creates three \n"
@@ -50,7 +51,7 @@ $answer = "This is the output from makefile 2\n";
&run_make_with_options($makefile,"-f $makefile2 -f $makefile3 TWO",&get_logfile,0);
&compare_output($answer,&get_logfile(1));
-
+
# Run Make again with the rule from the third makefile: THREE
@@ -70,16 +71,92 @@ $answer .= "This is the output from the original makefile\n";
$answer .= "This is the output from makefile 3\n";
&run_make_with_options($makefile,
"-f $makefile2 -f $makefile3 TWO all THREE",
- &get_logfile,
+ &get_logfile,
0);
&compare_output($answer,&get_logfile(1));
-
-
-
-
-
-
-
-
+# sv 62118.
+# Validate all sorts of -f etc. options
+
+my $hello = 'hello.mk';
+my $bye = 'bye.mk';
+my $byesrc = 'bye.mk.src';
+
+create_file($hello, 'all:; $(info hello, world)
+');
+
+create_file($bye, 'def:; $(info bye, world)
+bye.mk: bye.mk.src; touch $@
+bye.mk.src:; touch $@
+');
+
+# These invocations use the empty filename string so that the test framework
+# doesn't add any -f options on its own.
+
+# Incorrect order of options. -R follows -f.
+# Invocation of make is equivalent to
+# echo 'all:; $(info hello, world)' | make -f bye.mk -fR - all
+# There is bye.mk, but there is no 'R'.
+# make runs the recipes from bye.mk and prints the error about missing 'R'.
+
+# Ensure the newly created bye.src.mk is newer than bye.mk.
+&utouch(-600, $bye);
+run_make_test('', "-f$bye -fR - all", "#MAKE#: R: No such file or directory
+touch bye.mk.src
+touch bye.mk
+#MAKE#: *** No rule to make target 'R'. Stop.
+", 512);
+
+my @opts;
+my $answer;
+
+# Test double -f-.
+@opts = ('-f- -f-', '-f - -f -', '-f- -f -', '-f - -f-',
+ '-f- --file=-', '-f- --file -', '-f - --file=-', '-f - --file -',
+ '-f- --makefile=-', '-f- --makefile -',
+ '-f - --makefile=-', '-f - --makefile -',
+ '--file=- --makefile=-', '--file=- --makefile -',
+ '--file - --makefile=-', '--file - --makefile -');
+
+for my $opt (@opts) {
+ # We shouldn't need this; if the options are wrong then make shouldn't try
+ # to read from stdin.
+ close(STDIN);
+ open(STDIN, "<", $hello) || die "$0: cannot open $hello for reading: $!";
+ run_make_test('', "-f$bye $opt", "#MAKE#: *** Makefile from standard input specified twice. Stop.\n", 512);
+}
+
+# -f is not followed by filename.
+@opts = ('-f', '--file', '--makefile');
+$answer = "/requires an argument/";
+for my $opt (@opts) {
+ run_make_test('', $opt, $answer, 512);
+}
+
+# Test that make correctly parses all possible syntaxes to pipe make code to
+# the standard input.
+
+$answer = "touch bye.mk.src
+touch bye.mk
+hello, world
+#MAKE#: 'all' is up to date.\n";
+
+@opts = ('-f- all', '-f - all', '-Rf- all', '-Rf - all',
+ '--file=- all', '--file - all',
+ '--makefile=- all', '--makefile - all');
+for my $opt (@opts) {
+ unlink($byesrc);
+ close(STDIN);
+ open(STDIN, "<", $hello) || die "$0: cannot open $hello for reading: $!";
+ # Ensure the newly created bye.src.mk is newer than bye.mk.
+ &utouch(-600, $bye);
+
+ run_make_test('', "-f$bye $opt", $answer);
+}
+
+close(STDIN);
+unlink($hello, $bye, $byesrc);
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/options/dash-k b/tests/scripts/options/dash-k
index cd78e7f..4bd68f0 100644
--- a/tests/scripts/options/dash-k
+++ b/tests/scripts/options/dash-k
@@ -103,13 +103,12 @@ $make_name: Target 'all' not remade because of errors.\n";
if (defined $ERR_no_such_file) {
run_make_test('all: ; @echo hi
include ifile
-ifile: no-such-file; @false
+ifile: no-such-file; exit 1
',
'-k',
"#MAKEFILE#:2: ifile: $ERR_no_such_file
#MAKE#: *** No rule to make target 'no-such-file', needed by 'ifile'.
-#MAKE#: Failed to remake makefile 'ifile'.
-hi\n",
+#MAKEFILE#:2: Failed to remake makefile 'ifile'.\n",
512);
}
diff --git a/tests/scripts/options/dash-l b/tests/scripts/options/dash-l
index 637c8bd..d1e6049 100644
--- a/tests/scripts/options/dash-l
+++ b/tests/scripts/options/dash-l
@@ -42,9 +42,10 @@ $mkoptions .= " -j 4" if ($parallel_jobs);
# We have to wait longer than the default (5s).
&run_make_with_options($makefile, $mkoptions, &get_logfile, 0, 8);
-$slurp = &read_file_into_string (&get_logfile(1));
-if ($slurp !~ /cannot enforce load limit/) {
- &compare_output("", &get_logfile(1));
+$slurp = &read_file_into_string(&get_logfile(1));
+if ($slurp =~ /cannot enforce load limit/) {
+ return -1;
}
+&compare_output("", &get_logfile(1));
1;
diff --git a/tests/scripts/options/dash-r b/tests/scripts/options/dash-r
new file mode 100644
index 0000000..7157f71
--- /dev/null
+++ b/tests/scripts/options/dash-r
@@ -0,0 +1,44 @@
+# -*-perl-*-
+
+$description = "Test removing default rules and variables";
+
+$details = "DETAILS";
+
+touch('xxx.c');
+
+# Simple check
+run_make_test("\n", '-r COMPILE.c=echo xxx.o',
+ "#MAKE#: *** No rule to make target 'xxx.o'. Stop.", 512);
+
+# Make sure we can set it from within the makefile too
+run_make_test(q!
+COMPILE.c = echo
+MAKEFLAGS += -r
+!,
+ 'xxx.o',
+ "#MAKE#: *** No rule to make target 'xxx.o'. Stop.", 512);
+
+unlink('xxx.c');
+
+# Simple check for -R
+run_make_test(q!
+all:;$(info CC='$(CC)')
+!,
+ '-sR', "CC=''");
+
+# Make sure we can set -R from within the makefile too
+run_make_test(q!
+MAKEFLAGS += -R
+all:;$(info CC='$(CC)')
+!,
+ '-s', "CC=''");
+
+# sv 62356.
+# Setting -R in MAKEFLAGS sets -r.
+run_make_test(q!
+MAKEFLAGS := -R
+.PHONY: hello.c
+all: hello.o
+!, '', "#MAKE#: *** No rule to make target 'hello.o', needed by 'all'. Stop.", 512);
+
+1;
diff --git a/tests/scripts/options/print-directory b/tests/scripts/options/print-directory
index db762b2..7ba9a2e 100644
--- a/tests/scripts/options/print-directory
+++ b/tests/scripts/options/print-directory
@@ -2,15 +2,25 @@
$description = "Test the -w option to GNU make.";
+my $enter = "#MAKE#: Entering directory '#PWD#'";
+my $leave = "#MAKE#: Leaving directory '#PWD#'";
+
# Simple test without -w
run_make_test(q!
all: ; @echo hi
!,
"", "hi\n");
+my $ans = "$enter\nhi\n$leave\n";
+
# Simple test with -w
-run_make_test(undef, "-w",
- "#MAKE#: Entering directory '#PWD#'\nhi\n#MAKE#: Leaving directory '#PWD#'\n");
+run_make_test(undef, "-w", $ans);
+
+# Simple test with overriding -w
+run_make_test(undef, "-w --no-print-directory", "hi\n");
+
+# Simple test with overriding --no-print-directory
+run_make_test(undef, "--no-print-directory --print-directory", $ans);
# Test makefile rebuild to ensure no enter/leave
run_make_test(q!
@@ -21,13 +31,40 @@ foo: ; touch foo
"", "touch foo\n");
unlink('foo');
+$ans = "$enter\ntouch foo\n$leave\n";
+
# Test makefile rebuild with -w
+run_make_test(undef, "-w", $ans);
+unlink('foo');
+
+# Test makefile rebuild with -w overridden
+run_make_test(undef, "-w --no-print-directory", "touch foo\n");
+unlink('foo');
+
+# Test makefile rebuild with --no-print-directory overridden
+run_make_test(undef, "--no-print-directory --print-directory", $ans);
+unlink('foo');
+
+my $enter1 = "#MAKE#[1]: Entering directory '#PWD#'";
+my $leave1 = "#MAKE#[1]: Leaving directory '#PWD#'";
+
+$ans = "$enter1\nhi\n$leave1\n";
+
+# Test makefile recursion with default enter/leave
run_make_test(q!
-include foo
-all: ;@:
-foo: ; touch foo
+all: ;@$(MAKE) -f #MAKEFILE# recurse
+recurse: ; @echo hi
!,
- "-w", "#MAKE#: Entering directory '#PWD#'\ntouch foo\n#MAKE#: Leaving directory '#PWD#'\n");
-unlink('foo');
+ "", $ans);
+
+# Disable enter/leave
+run_make_test(undef, "--no-print-directory", "hi\n");
+
+# Re-enable enter/leave
+$ans = "$enter\n$ans$leave\n";
+run_make_test(undef, "--no-print-directory -w", $ans);
+
+# Override enter/leave
+run_make_test(undef, "-w --no-print-directory", "hi\n");
1;
diff --git a/tests/scripts/options/shuffle b/tests/scripts/options/shuffle
new file mode 100644
index 0000000..5661683
--- /dev/null
+++ b/tests/scripts/options/shuffle
@@ -0,0 +1,128 @@
+# -*-perl-*-
+
+$description = "Test the --shuffle option.";
+
+$details = "Verify that --shuffle has expected effect on target order and argument order.";
+
+#
+# Test --shuffle=random
+#
+
+# TEST 1: Fixed seed should yield the same order from run to run.
+
+$makefile = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile");
+print MAKEFILE <<'EOF';
+# More target prerequisites lower collision chance in TEST 2
+all: a_ b_ c_ d_ e_ f_ g_ i_ j_ k_ l_
+%: ; echo $@
+EOF
+close(MAKEFILE);
+
+$log1 = &get_logfile;
+$log2 = &get_logfile;
+&run_make_with_options($makefile, "--shuffle=12345", $log1);
+&run_make_with_options($makefile, "--shuffle=12345", $log2);
+
+&compare_output(&read_file_into_string($log1), $log2);
+
+# TEST 2: Sequential runs should produce different orders.
+
+$log3 = &get_logfile;
+$log4 = &get_logfile;
+&run_make_with_options($makefile, "--shuffle", $log3);
+&run_make_with_options($makefile, "--shuffle", $log4);
+
+++$tests_run;
+if (&read_file_into_string($log3) ne &read_file_into_string($log4)) {
+ print "ok\n" if $debug;
+ ++$tests_passed;
+}
+
+#
+# Test --shuffle=reverse
+#
+
+run_make_test('
+%: ; @echo $@
+all: a b c
+',
+ '--shuffle=reverse', "c\nb\na\nall");
+
+run_make_test('
+%: ; @echo $@
+all: a b c
+',
+ '--shuffle=none', "a\nb\nc\nall");
+
+run_make_test('
+%: ; @echo $@
+all: a b c
+',
+ '--shuffle=identity', "a\nb\nc\nall");
+
+# Make sure prerequisites get reverse order and commands don't get affected.
+run_make_test('
+all: foo.o ; @echo $@
+%.o : %.c ; @echo cc -c -o $@ $<
+foo.o : foo.c foo.h bar.h baz.h
+%.h: ; @echo $@
+%.c: ; @echo $@
+',
+ '--shuffle=reverse',
+ "baz.h\nbar.h\nfoo.h\nfoo.c\ncc -c -o foo.o foo.c\nall");
+
+# Make sure pattern prerequisites get reverse order and commands don't get
+# affected.
+run_make_test('
+all: foo_ ; @echo $@
+foo%: arg%1 arg%2 arg%3 arg%4 ; @echo bld $@ $< $(word 3,$^) $(word 2,$^) $(word 4,$^)
+
+arg%: ; @echo $@
+',
+ '--shuffle=reverse',
+ "arg_4\narg_3\narg_2\narg_1\nbld foo_ arg_1 arg_3 arg_2 arg_4\nall");
+
+# Check if make can survive circular dependency.
+run_make_test('
+all: a_ b_ ; @echo $@
+%_: ; @echo $@
+
+a_: b_
+b_: a_
+',
+ '--shuffle=reverse', "#MAKE#: Circular a_ <- b_ dependency dropped.\na_\nb_\nall");
+
+# Check if order-only dependencies get reordered.
+run_make_test('
+all: a_ ; @echo $@
+%_: ; @echo $@
+a_: b_ c_ | d_ e_
+',
+ '--shuffle=reverse', "e_\nd_\nc_\nb_\na_\nall");
+
+# Check if goals are reordered.
+run_make_test('
+%_: ; @echo $@
+',
+ '--shuffle=reverse a_ b_ c_', "c_\nb_\na_");
+
+# .NOTPARALLEL should prevent reordering from happening.
+run_make_test('
+%_: ; @echo $@
+# disable shuffling
+.NOTPARALLEL:
+',
+ '--shuffle=reverse a_ b_ c_', "a_\nb_\nc_");
+
+# Check if SECONDEXPANSION targets also get reshuffled.
+run_make_test('
+.SECONDEXPANSION:
+all: $$(var)
+%_: ; @echo $@
+var = a_ b_ c_
+',
+ '--shuffle=reverse', "c_\nb_\na_");
+
+1;
diff --git a/tests/scripts/options/symlinks b/tests/scripts/options/symlinks
index bf8a892..83dc84f 100644
--- a/tests/scripts/options/symlinks
+++ b/tests/scripts/options/symlinks
@@ -6,14 +6,7 @@ $details = "Verify that symlink handling with and without -L works properly.";
# Only run these tests if the system sypports symlinks
-# Apparently the Windows port of Perl reports that it does support symlinks
-# (in that the symlink() function doesn't fail) but it really doesn't, so
-# check for it explicitly.
-
-if ($port_type eq 'W32' || !( eval { symlink("",""); 1 })) {
- # This test is N/A
- return -1;
-}
+exists $FEATURES{'check-symlink'} or return -1;
use File::Spec;
diff --git a/tests/scripts/targets/INTERMEDIATE b/tests/scripts/targets/INTERMEDIATE
index 512498c..e942e8c 100644
--- a/tests/scripts/targets/INTERMEDIATE
+++ b/tests/scripts/targets/INTERMEDIATE
@@ -13,10 +13,11 @@ that the intermediate file is again deleted.
Try this with implicit rules and explicit rules: both should work.\n";
-open(MAKEFILE,"> $makefile");
+# TEST #0
-print MAKEFILE <<'EOF';
+&utouch(-20, 'foo.f', 'bar.f');
+run_make_test(q!
.INTERMEDIATE: foo.e bar.e
# Implicit rule test
@@ -27,82 +28,81 @@ foo.d: foo.e
# Explicit rule test
foo.c: foo.e bar.e; cat $^ > $@
-EOF
-
-close(MAKEFILE);
-
-# TEST #0
-
-&utouch(-20, 'foo.f', 'bar.f');
-
-&run_make_with_options($makefile,'foo.d',&get_logfile);
-$answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n";
-&compare_output($answer, &get_logfile(1));
+!,
+ 'foo.d', "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";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'foo.d', "#MAKE#: 'foo.d' is up to date.\n");
# TEST #2
&utouch(-10, 'foo.d');
&touch('foo.f');
-&run_make_with_options($makefile,'foo.d',&get_logfile);
-$answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'foo.d', "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n");
# TEST #3
-&run_make_with_options($makefile,'foo.c',&get_logfile);
-$answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm foo.e bar.e\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'foo.c', "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm foo.e bar.e\n");
# TEST #4
-&run_make_with_options($makefile,'foo.c',&get_logfile);
-$answer = "$make_name: 'foo.c' is up to date.\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'foo.c', "#MAKE#: 'foo.c' is up to date.\n");
# TEST #5
&utouch(-10, 'foo.c');
&touch('foo.f');
-&run_make_with_options($makefile,'foo.c',&get_logfile);
-$answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm foo.e bar.e\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'foo.c', "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm foo.e bar.e\n");
# TEST #6 -- added for PR/1669: don't remove files mentioned on the cmd line.
-&run_make_with_options($makefile,'foo.e',&get_logfile);
-$answer = "cp foo.f foo.e\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'foo.e', "cp foo.f foo.e\n");
unlink('foo.f', 'foo.e', 'foo.d', 'foo.c', 'bar.f', 'bar.e', 'bar.d', 'bar.c');
# TEST #7 -- added for PR/1423
-$makefile2 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile2");
-
-print MAKEFILE <<'EOF';
+run_make_test(q!
all: foo
foo.a: ; touch $@
%: %.a ; touch $@
.INTERMEDIATE: foo.a
-EOF
+!,
+ '-R', "touch foo.a\ntouch foo\nrm foo.a\n");
+
+unlink('foo');
-close(MAKEFILE);
+# sv 60188.
+# A file made by an implicit rule, but explicitly mentioned by the user, is
+# still considered intermediate if it's a prereq to .INTERMEDIATE.
-&run_make_with_options($makefile2, '-R', &get_logfile);
-$answer = "touch foo.a\ntouch foo\nrm foo.a\n";
-&compare_output($answer, &get_logfile(1));
+touch('hello.z');
+unlink('test.x');
-unlink('foo');
+run_make_test(q!
+all: hello.z
+%.z: test.x; touch $@
+%.x: ;
+.INTERMEDIATE: test.x
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.z');
+
+# A target explicitly listed as a prerequisite of a pattern rule, is still
+# considered mentioned and "ought to exist".
+
+run_make_test(q!
+1.all: 1.q ; touch $@
+%.q: 1.r ; touch $@
+%.r: ; touch $@
+.INTERMEDIATE: 1.r
+!,
+ '', "touch 1.r\ntouch 1.q\ntouch 1.all\nrm 1.r\n");
+
+unlink('1.all', '1.q', '1.r');
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/targets/NOTINTERMEDIATE b/tests/scripts/targets/NOTINTERMEDIATE
new file mode 100644
index 0000000..e4690b1
--- /dev/null
+++ b/tests/scripts/targets/NOTINTERMEDIATE
@@ -0,0 +1,119 @@
+# -*-perl-*-
+
+$description = "Test the behaviour of the .NOTINTERMEDIATE target.";
+
+$details = "\
+Test the behavior of the .NOTINTERMEDIATE special target.\n";
+
+touch('hello.z');
+unlink('hello.x');
+
+
+# Test 1. A file which matches a .NOTINTERMEDIATE pattern is not intermediate.
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q %.x
+!, '', "touch hello.z\n");
+
+# Test 2. .NOTINTERMEDIATE: %.q pattern has no effect on hello.x.
+touch('hello.z');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q
+!, '', "#MAKE#: 'hello.z' is up to date.\n");
+
+# Test 3. A file which is a prereq of .NOTINTERMEDIATE is not intermediate.
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q hello.x
+!, '', "touch hello.z\n");
+
+# Test 4. .NOTINTERMEDIATE without prerequisites makes everything
+# notintermediate.
+unlink('hello.z');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE:
+!, '', "touch hello.z\n");
+
+# Test 5. Same file cannot be intermediate and notintermediate.
+run_make_test(q!
+.INTERMEDIATE: hello.x
+.NOTINTERMEDIATE: hello.x
+!, '', "#MAKE#: *** hello.x cannot be both .NOTINTERMEDIATE and .INTERMEDIATE. Stop.\n", 512);
+
+# Test 6. Same file cannot be secondary and notintermediate.
+run_make_test(q!
+.SECONDARY: hello.x
+.NOTINTERMEDIATE: hello.x
+!, '', "#MAKE#: *** hello.x cannot be both .NOTINTERMEDIATE and .SECONDARY. Stop.\n", 512);
+
+# Test 7. All .SECONDARY and all .NOTINTERMEDIATE are mutually exclusive.
+run_make_test(q!
+.SECONDARY:
+.NOTINTERMEDIATE:
+!, '', "#MAKE#: *** .NOTINTERMEDIATE and .SECONDARY are mutually exclusive. Stop.\n", 512);
+
+# Test 8. .INTERMEDIATE file takes priority over a .NOTINTERMEDIATE pattern.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.INTERMEDIATE: hello.x
+.NOTINTERMEDIATE: %.q %.x
+!, '', "#MAKE#: 'hello.z' is up to date.\n");
+
+# Test 9. Everything is notintermediate, except hello.x.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.INTERMEDIATE: hello.x
+.NOTINTERMEDIATE:
+!, '', "#MAKE#: 'hello.z' is up to date.\n");
+
+# Test 10. Everything is notintermediate, except hello.x.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.SECONDARY: hello.x
+.NOTINTERMEDIATE:
+!, '', "#MAKE#: 'hello.z' is up to date.\n");
+
+# Test 11. Everything is secondary, except %.q, hello.x.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q hello.x
+.SECONDARY:
+!, '', "touch hello.z\n");
+
+# Test 12. Everything is secondary, except %.q %.x.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q %.x
+.SECONDARY:
+!, '', "touch hello.z\n");
+
+
+
+unlink('hello.z');
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/targets/ONESHELL b/tests/scripts/targets/ONESHELL
index 3876966..f9da14b 100644
--- a/tests/scripts/targets/ONESHELL
+++ b/tests/scripts/targets/ONESHELL
@@ -10,7 +10,7 @@ if ($port_type ne 'W32') {
# Some shells (*shakes fist at Solaris*) cannot handle multiple flags in
# separate arguments.
my $t = `$sh_name -e -c true 2>/dev/null`;
- my $multi_ok = $? == 0;
+ $multi_ok = $? == 0;
}
# Simple
@@ -89,6 +89,55 @@ all:
>print "a = $$a, y = (@y)\n";
!,
'', "a = 12, y = (a b c)\n");
+
+ # Simple .SHELLFLAGS, no quotes.
+ # sv 61805.
+ run_make_test(q!
+.ONESHELL:
+SHELL = #PERL#
+.SHELLFLAGS = -e
+all:; @print "it works\n"
+!, '', 'it works');
+
+ # Pass a quoted string with spaces to oneshell.
+ # sv 61805.
+ run_make_test(q!
+.ONESHELL:
+SHELL = #PERL#
+.SHELLFLAGS = -w -E 'use warnings FATAL => "all";' -E
+all:; @print "it works\n"
+!, '', 'it works');
+
+ # Empty .SHELLFLAGS.
+ # sv 61805.
+ run_make_test(q!
+.ONESHELL:
+SHELL = #PERL#
+.SHELLFLAGS =
+all:; @print "it works"
+!, '', "Can't open perl script \"print \"it works\"\": $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:5: all] Error 2", 512);
+
+ # No .SHELLFLAGS.
+ # sv 61805.
+ run_make_test(q!
+.ONESHELL:
+SHELL = #PERL#
+all:; @print "it works"
+!, '', "Can't open perl script \"print \"it works\"\": $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:4: all] Error 2", 512);
+
+ # Pass a quoted string with spaces to oneshell.
+ # sv 61805.
+ run_make_test(q!
+.ONESHELL:
+SHELL = #PERL#
+.SHELLFLAGS = -w -E 'use warnings FATAL => "all";' -E 'my $$foo = "bar";' -E
+all:; @print "it works: $$foo\n"
+!, '', 'it works: bar');
}
+# This tells the test driver that the perl test script executed properly.
1;
+
+### Local Variables:
+### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
+### End:
diff --git a/tests/scripts/targets/POSIX b/tests/scripts/targets/POSIX
index c44cc50..c40b8db 100644
--- a/tests/scripts/targets/POSIX
+++ b/tests/scripts/targets/POSIX
@@ -20,6 +20,8 @@ all: ; \@$script
'', "#MAKE#: *** [#MAKEFILE#:3: all] Error $err\n", 512);
# User settings must override .POSIX
+# In the standard .POSIX must be the first thing in the makefile
+# but we relax that rule in GNU make.
$flags = '-xc';
$out = `$sh_name $flags '$script' 2>&1`;
run_make_test(qq!
@@ -47,7 +49,7 @@ $make
'', $r);
# Make sure that local settings take precedence
-%extraENV = map { $_ => "xx-$_" } keys %POSIX;
+%ENV = (%ENV, map { $_ => "xx-$_" } keys %POSIX);
$r = join('', map { "$_=xx-$_\n"} sort keys %POSIX);
run_make_test(undef, '', $r);
diff --git a/tests/scripts/targets/WAIT b/tests/scripts/targets/WAIT
new file mode 100644
index 0000000..b981023
--- /dev/null
+++ b/tests/scripts/targets/WAIT
@@ -0,0 +1,193 @@
+# -*-perl-*-
+
+$description = "Test the behaviour of the .WAIT target.";
+
+$details = "";
+
+# Ensure .WAIT doesn't appear in any automatic variables
+
+run_make_test(q!
+all: .WAIT pre1 .WAIT pre2 | .WAIT pre3 ; @echo '<=$< ^=$^ ?=$? +=$+ |=$|'
+pre1 pre2 pre3:;
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '', '<=pre1 ^=pre1 pre2 ?=pre1 pre2 +=pre1 pre2 |=pre3');
+
+run_make_test(q!
+.SECONDEXPANSION:
+all: $$(pre) ; @echo '<=$< ^=$^ ?=$? +=$+ |=$|'
+pre1 pre2 pre3:;
+
+pre = .WAIT pre1 .WAIT pre2 | .WAIT pre3
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '', '<=pre1 ^=pre1 pre2 ?=pre1 pre2 +=pre1 pre2 |=pre3');
+
+run_make_test(q!
+all: pre
+p% : .WAIT p%1 .WAIT p%2 | .WAIT p%3; @echo '<=$< ^=$^ ?=$? +=$+ |=$|'
+pre1 pre2 pre3: ;
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '', "<=pre1 ^=pre1 pre2 ?=pre1 pre2 +=pre1 pre2 |=pre3\n");
+
+# Unfortunately I don't think we can get away from using sleep here; at least
+# I can't think of any way to make sure .WAIT works without it. Even with it,
+# it's not reliable (in that even if .WAIT is not working we MIGHT succeed the
+# test--it shouldn't ever be the case that we fail the test unexpectedly).
+# That makes this test suite slow to run :-/.
+
+run_make_test(q!
+all : pre1 .WAIT pre2
+pre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@
+pre2: ; @#HELPER# -q out $@
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '-j10', "start-pre1\nend-pre1\npre2\n");
+
+# Ensure .WAIT doesn't add extra a dependency between its targets
+
+run_make_test(undef, '-j10 pre2', "pre2\n");
+
+# Ensure .WAIT doesn't wait between all targets
+
+run_make_test(q!
+all : pre1 .WAIT pre2 pre3
+pre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@
+pre2: ; @#HELPER# -q out start-$@ file TWO wait THREE out end-$@
+pre3: ; @#HELPER# -q wait TWO out $@ file THREE
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '-j10', "start-pre1\nend-pre1\nstart-pre2\npre3\nend-pre2\n");
+
+unlink(qw(TWO THREE));
+
+# Ensure .WAIT waits for ALL targets on the left before ANY targets on the right
+
+run_make_test(q!
+all : pre1 pre2 .WAIT post1 post2
+pre1: ; @#HELPER# -q out start-$@ file PRE1 wait PRE2 sleep 1 out end-$@
+pre2: ; @#HELPER# -q wait PRE1 out $@ file PRE2
+
+post1: ; @#HELPER# -q wait POST2 out $@ file POST1
+post2: ; @#HELPER# -q file POST2 wait POST1 out $@
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '-j10', "start-pre1\npre2\nend-pre1\npost1\npost2\n");
+
+unlink(qw(PRE1 PRE2 POST1 POST2));
+
+# See if .WAIT takes effect between different lists of prereqs
+# In the current implementation, .WAIT waits only between two prerequisites
+# in a given target. These same two targets might be run in a different
+# order if they appear as prerequisites of another target. This is the way
+# other implementations of .WAIT work. I personally think it's gross and
+# makes .WAIT just a toy when it comes to ordering, but it's much simpler
+# to implement than creating an actual edge in the DAG to represent .WAIT
+# and since that's what users expect, we'll do the same for now.
+
+run_make_test(q!
+all : one two
+one: pre1 .WAIT pre2
+two: pre2 pre1
+pre1: ; @#HELPER# -q out start-$@ file PRE1 wait PRE2 out end-$@
+pre2: ; @#HELPER# -q wait PRE1 out $@ file PRE2
+
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '-j10', "start-pre1\npre2\nend-pre1\n");
+unlink(qw(PRE1 PRE2));
+
+# Check that .WAIT works with pattern rules
+
+run_make_test(q!
+all: pre
+p% : p%1 .WAIT p%2;
+pre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@
+pre2: ; @#HELPER# -q out $@
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '-j10', "start-pre1\nend-pre1\npre2\n");
+
+# Check that .WAIT works with secondarily expanded rules
+
+run_make_test(q!
+.SECONDEXPANSION:
+all: $$(pre)
+pre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@
+pre2: ; @#HELPER# -q out $@
+pre3: ; @#HELPER# -q out $@
+
+pre = .WAIT pre1 .WAIT pre2 | .WAIT pre3
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '-j10', "start-pre1\nend-pre1\npre2\npre3\n");
+
+# Verify NOTPARALLEL works
+
+run_make_test(q!
+all : pre1 pre2
+pre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@
+pre2: ; @#HELPER# -q out $@
+
+.NOTPARALLEL:
+!,
+ '-j10', "start-pre1\nend-pre1\npre2\n");
+
+run_make_test(q!
+all : p1 .WAIT np1
+
+p1: pre1 pre2
+pre1: ; @#HELPER# -q out start-$@ file PRE1 wait PRE2 out end-$@
+pre2: ; @#HELPER# -q wait PRE1 out $@ file PRE2
+
+
+np1: npre1 npre2
+npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@
+npre2: ; @#HELPER# -q out $@
+
+.NOTPARALLEL: np1
+!,
+ '-j10', "start-pre1\npre2\nend-pre1\nstart-npre1\nend-npre1\nnpre2\n");
+unlink(qw(PRE1 PRE2));
+
+# Ensure we don't shuffle if .WAIT is set
+
+run_make_test(q!
+all : pre1 .WAIT pre2
+pre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@
+pre2: ; @#HELPER# -q out $@
+
+# This is just here so we don't fail with older versions of make
+.WAIT:
+!,
+ '-j10 --shuffle=reverse', "start-pre1\nend-pre1\npre2\n");
+
+# Warn about invalid .WAIT definitions
+
+run_make_test(q!
+.WAIT: foo
+.WAIT: ; echo oops
+all:;@:
+!,
+ '', "#MAKEFILE#:2: .WAIT should not have prerequisites\n#MAKEFILE#:3: .WAIT should not have commands\n");
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/variables/GNUMAKEFLAGS b/tests/scripts/variables/GNUMAKEFLAGS
index 6e50794..6dc9fd8 100644
--- a/tests/scripts/variables/GNUMAKEFLAGS
+++ b/tests/scripts/variables/GNUMAKEFLAGS
@@ -5,7 +5,7 @@ $description = "Test proper behavior of GNUMAKEFLAGS";
# Accept flags from GNUMAKEFLAGS as well as MAKEFLAGS
# Results always go in MAKEFLAGS
-$extraENV{'GNUMAKEFLAGS'} = '-e -r -R';
+$ENV{'GNUMAKEFLAGS'} = '-e -r -R';
run_make_test(q!
all: ; @echo $(MAKEFLAGS)
@@ -14,12 +14,12 @@ all: ; @echo $(MAKEFLAGS)
# Long arguments mean everything is prefixed with "-"
-$extraENV{'GNUMAKEFLAGS'} = '--no-print-directory -e -r -R --trace';
+$ENV{'GNUMAKEFLAGS'} = '--no-print-directory -e -r -R --trace';
run_make_test(q!
all: ; @echo $(MAKEFLAGS)
!,
- '', "#MAKEFILE#:2: target 'all' does not exist
+ '', "#MAKEFILE#:2: update target 'all' due to: target does not exist
echo erR --trace --no-print-directory
erR --trace --no-print-directory");
@@ -27,7 +27,7 @@ erR --trace --no-print-directory");
unlink('x.mk');
-$extraENV{GNUMAKEFLAGS} = '-Itst/bad';
+$ENV{GNUMAKEFLAGS} = '-Itst/bad';
run_make_test(q!
recurse: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; #MAKEPATH# -f #MAKEFILE# all
@@ -35,8 +35,20 @@ all: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAG
-include x.mk
x.mk: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; echo > $@
!,
- "", "x.mk\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\nrecurse\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\n#MAKE#[1]: Entering directory '#PWD#'\nall\nMAKEFLAGS = w -Itst/bad\nGNUMAKEFLAGS =\n#MAKE#[1]: Leaving directory '#PWD#'\n");
+ "", "x.mk\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\nrecurse\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\n#MAKE#[1]: Entering directory '#PWD#'\nall\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\n#MAKE#[1]: Leaving directory '#PWD#'\n");
unlink('x.mk');
+# Ensure that we don't add GNUMAKEFLAGS to the environment if it's not there
+run_make_test(q!
+all: ; @env | grep GNUMAKEFLAGS; true
+!,
+ '', '');
+
+$ENV{GNUMAKEFLAGS} = '-Itst/bad';
+run_make_test(q!
+all: ; @env | grep GNUMAKEFLAGS; true
+!,
+ '', 'GNUMAKEFLAGS=');
+
1;
diff --git a/tests/scripts/variables/INCLUDE_DIRS b/tests/scripts/variables/INCLUDE_DIRS
index c9662e9..6881292 100644
--- a/tests/scripts/variables/INCLUDE_DIRS
+++ b/tests/scripts/variables/INCLUDE_DIRS
@@ -8,11 +8,12 @@ use Cwd;
$dir = cwd;
$dir =~ s,.*/([^/]+)$,../$1,;
-# Test #1: The content of .INCLUDE_DIRS depends on the platform for which
-# make was built. What we know for sure is that it shouldn't be
-# empty.
-#
-run_make_test('
+if (-d '/usr/include') {
+ # Test #1: The content of .INCLUDE_DIRS depends on the platform for which
+ # make was built. What we know for sure is that it shouldn't be
+ # empty.
+ #
+ run_make_test('
ifeq ($(.INCLUDE_DIRS),)
$(warning .INCLUDE_DIRS is empty)
endif
@@ -20,9 +21,8 @@ endif
.PHONY: all
all:;@:
',
-'',
-'');
-
+ '', '');
+}
# Test #2: Make sure -I paths end up in .INCLUDE_DIRS.
#
@@ -32,15 +32,63 @@ $(warning dir is empty)
endif
ifeq ($(filter $(dir),$(.INCLUDE_DIRS)),)
-$(warning .INCLUDE_DIRS does not contain $(dir))
+$(warning .INCLUDE_DIRS does not contain $(dir): $(.INCLUDE_DIRS))
endif
.PHONY: all
all:;@:
',
-"-I$dir dir=$dir",
-'');
+ "-I$dir dir=$dir", '');
+
+# Find the default .INCLUDE_DIRS
+create_file('defaultdirs.mk', "\$(info \$(.INCLUDE_DIRS))\nall:;\@:\n");
+my $cmd = subst_make_string("#MAKEPATH# -f defaultdirs.mk");
+my @dirs = `$cmd`;
+my $dirs = $dirs[0];
+chomp $dirs;
+unlink('defaultdirs.mk');
+
+run_make_test("
+ifneq (\$(.INCLUDE_DIRS),$dirs)
+\$(warning Mismatched \$(.INCLUDE_DIRS) != $dirs)
+endif
+all:;\@:
+",
+ '', '');
+
+# Verify that -I- disables content from .INCLUDE_DIRS
+
+run_make_test(q/
+ifneq ($(.INCLUDE_DIRS),)
+$(warning Mismatched $(.INCLUDE_DIRS) != )
+endif
+all:;@:
+/,
+ '-I-', '');
+
+# Prefix -I dirs to the front
+mkdir('somedir', 0777);
+
+my $xdirs = $dirs ? " $dirs" : '';
+run_make_test("
+ifneq (\$(.INCLUDE_DIRS),somedir$xdirs)
+\$(warning Mismatched '\$(.INCLUDE_DIRS)' != 'somedir$xdirs')
+endif
+all:;\@:
+",
+ '-I somedir', '');
+
+# Verify .INCLUDE_DIRS contains files after -I-
+
+run_make_test(q/
+ifneq ($(.INCLUDE_DIRS),somedir)
+$(warning Mismatched $(.INCLUDE_DIRS) != somedir)
+endif
+all:;@:
+/,
+ '-I - -I somedir', '');
+rmdir('somedir');
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/variables/MAKEFLAGS b/tests/scripts/variables/MAKEFLAGS
index 0fac74a..a41f1cf 100644
--- a/tests/scripts/variables/MAKEFLAGS
+++ b/tests/scripts/variables/MAKEFLAGS
@@ -6,31 +6,32 @@ $details = "DETAILS";
# Normal flags aren't prefixed with "-"
run_make_test(q!
-all: ; @echo $(MAKEFLAGS)
+all: ; @echo /$(MAKEFLAGS)/
!,
- '-e -r -R', 'erR');
+ '-e -r -R', '/erR/');
# Long arguments mean everything is prefixed with "-"
run_make_test(q!
-all: ; @echo $(MAKEFLAGS)
+all: ; @echo /$(MAKEFLAGS)/
!,
- '--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");
+ '--no-print-directory -e -r -R --trace', "#MAKEFILE#:2: update target 'all' due to: target does not exist
+echo /erR --trace --no-print-directory/
+/erR --trace --no-print-directory/");
# Recursive invocations of make should accumulate MAKEFLAGS values.
# Savannah bug #2216
run_make_test(q!
MSG = Fails
+.RECIPEPREFIX = >
all:
- @echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
- @MSG=Works $(MAKE) -e -f #MAKEFILE# jump
+> @echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
+> @MSG=Works $(MAKE) -e -f #MAKEFILE# jump
jump:
- @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'
- @$(MAKE) -f #MAKEFILE# print
+> @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'
+> @$(MAKE) -f #MAKEFILE# print
print:
- @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'
+> @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'
.PHONY: all jump print
!,
'--no-print-directory',
@@ -38,8 +39,120 @@ print:
jump Works: MAKEFLAGS=e --no-print-directory
print Works: MAKEFLAGS=e --no-print-directory');
-1;
+# Ensure MAKEFLAGS updates are handled immediately rather than later
+
+mkdir('foo', 0777);
+mkdir('bar', 0777);
+
+run_make_test(q!
+$(info MAKEFLAGS=$(MAKEFLAGS))
+$(info INCLUDE_DIRS=$(.INCLUDE_DIRS))
+MAKEFLAGS += -Ibar
+$(info MAKEFLAGS=$(MAKEFLAGS))
+$(info INCLUDE_DIRS=$(.INCLUDE_DIRS))
+.PHONY: all
+all: ; @echo 'MAKEFLAGS=$(MAKEFLAGS)' "\$$MAKEFLAGS=$$MAKEFLAGS"
+!,
+ '-I- -Ifoo', 'MAKEFLAGS= -I- -Ifoo
+INCLUDE_DIRS=foo
+MAKEFLAGS= -I- -Ifoo -Ibar
+INCLUDE_DIRS=foo bar
+MAKEFLAGS= -I- -Ifoo -Ibar $MAKEFLAGS= -I- -Ifoo -Ibar');
+
+rmdir('foo');
+rmdir('bar');
+
+# Test that command line switches are all present in MAKEFLAGS.
+# sv 62514.
+my @opts;
+
+# Simple flags.
+@opts = ('i', 'k', 'n', 'q', 'r', 's', 'w', 'd');
+exists $FEATURES{'check-symlink'} and push @opts, 'L';
+
+for my $opt (@opts) {
+ run_make_test(q!
+MAKEFLAGS:=B
+all:; $(info makeflags='$(MAKEFLAGS)')
+!, "-$opt", "/makeflags='B$opt'/");
+}
+
+# Switches which carry arguments.
+@opts = (' -I/tmp', ' -Onone', ' --debug=b', ' -l2.5');
+for my $opt (@opts) {
+ run_make_test(q!
+MAKEFLAGS:=B
+all:; $(info makeflags='$(MAKEFLAGS)')
+!, "$opt", "/makeflags='B$opt'/");
+}
+
+# Long options which take no arguments.
+# sv 62514.
+@opts = (' --no-print-directory', ' --warn-undefined-variables', ' --trace');
+for my $opt (@opts) {
+run_make_test(q!
+MAKEFLAGS:=B
+all:; $(info makeflags='$(MAKEFLAGS)')
+!, "$opt", "/makeflags='B$opt'/");
+}
+
+# Test that make filters out duplicates.
+# Each option is specified in the makefile, env and on the command line.
+@opts = (' -I/tmp', ' -Onone', ' --debug=b', ' -l2.5');
+$ENV{'MAKEFLAGS'} = $opt;
+for my $opt (@opts) {
+ run_make_test("
+MAKEFLAGS:=B $opt
+all:; \$(info makeflags='\$(MAKEFLAGS)')
+", "$opt", "/makeflags='B$opt'/");
+}
+
+# Test that make filters out duplicates.
+# Each option is specified in the makefile, env and on the command line.
+# decode_switches reallocates when the number of parameters in sl->list exceeds 5.
+# This test exercises the realloc branch.
+$ENV{'MAKEFLAGS'} = '-I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6 -I2 -I2';
+run_make_test(q!
+MAKEFLAGS:=B -I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6 -I2 -I2
+all:; $(info makeflags='$(MAKEFLAGS)')
+!,
+'-I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6',
+"/makeflags='B -I1 -I2 -I3 -I4 -I5 -I6 -l2.5 -Onone --debug=b'/");
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
+# A mix of multiple flags from env, the makefile and command line.
+# Skip -L since it's not available everywhere
+$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn-undefined-variables --trace';
+run_make_test(q!
+MAKEFLAGS:=iknqrswd -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5
+all:; $(info makeflags='$(MAKEFLAGS)')
+!,
+'-Onone -l2.5 -l2.5 -Onone -I/tmp -iknqrswd -i -n -s -k -I/tmp',
+"/makeflags='Bdiknqrsw -I/tmp -l2.5 -Onone --trace --warn-undefined-variables'/");
+
+# Verify MAKEFLAGS are all available to shell functions
+$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn-undefined-variables';
+run_make_test(q!
+MAKEFLAGS := iknqrsw -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5 --no-print-directory
+XX := $(shell echo "$$MAKEFLAGS")
+all:; $(info makeflags='$(XX)')
+!,
+ '-Onone -l2.5 -l2.5 -Onone -I/tmp -iknqrs -i -n -s -k -I/tmp',
+ "makeflags='iknqrsw -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5 --no-print-directory'");
+
+# Verify that command line arguments are included in MAKEFLAGS
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+ '-e FOO=bar -r -R', 'erR -- FOO=bar');
+
+# Long arguments mean everything is prefixed with "-"
+run_make_test(q!
+all: ; @echo /$(MAKEFLAGS)/
+!,
+ '--no-print-directory -e -r -R --trace FOO=bar',
+ "#MAKEFILE#:2: update target 'all' due to: target does not exist
+echo /erR --trace --no-print-directory -- FOO=bar/
+/erR --trace --no-print-directory -- FOO=bar/");
+
+
+1;
diff --git a/tests/scripts/variables/MAKE_RESTARTS b/tests/scripts/variables/MAKE_RESTARTS
index 01bf55e..e1683a3 100644
--- a/tests/scripts/variables/MAKE_RESTARTS
+++ b/tests/scripts/variables/MAKE_RESTARTS
@@ -33,11 +33,11 @@ rmfiles('foo.x', 'bar.x');
# Test multiple restarts and make sure the variable is cleaned up
run_make_test('
+.RECIPEPREFIX = >
recurse:
- @echo recurse MAKE_RESTARTS=$$MAKE_RESTARTS
- @$(MAKE) -f #MAKEFILE# all
-all:
- @echo all MAKE_RESTARTS=$$MAKE_RESTARTS
+> @echo recurse MAKE_RESTARTS=$$MAKE_RESTARTS
+> @$(MAKE) -f #MAKEFILE# all
+all: ; @echo all MAKE_RESTARTS=$$MAKE_RESTARTS
$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
include foo.x
foo.x: ; @echo "include bar.x" > $@
@@ -55,7 +55,3 @@ all MAKE_RESTARTS=
rmfiles('foo.x', 'bar.x');
1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End:
diff --git a/tests/scripts/variables/SHELL b/tests/scripts/variables/SHELL
index 4ff1ac2..78d887c 100644
--- a/tests/scripts/variables/SHELL
+++ b/tests/scripts/variables/SHELL
@@ -14,21 +14,19 @@ $mshell = $sh_name;
# According to POSIX, the value of SHELL in the environment has no impact on
# the value in the makefile.
-# Note %extraENV takes precedence over the default value for the shell.
-$extraENV{SHELL} = '/dev/null';
+$ENV{SHELL} = '/dev/null';
run_make_test('all:;@echo "$(SHELL)"', '', $mshell);
-# According to POSIX, any value of SHELL set in the makefile should _NOT_ be
-# exported to the subshell! I wanted to set SHELL to be $^X (perl) in the
-# makefile, but make runs $(SHELL) -c 'commandline' and that doesn't work at
-# all when $(SHELL) is perl :-/. So, we just add an extra initial /./ which
-# works well on UNIX and seems to work OK on at least some non-UNIX systems.
+# According to POSIX, any value of SHELL set in the makefile should not be
+# exported to the subshell. A more portable option might be to set SHELL to
+# be $^X (perl) in the makefile, and set .SHELLFLAGS to -e.
-$extraENV{SHELL} = $mshell;
+$ENV{SHELL} = $mshell;
my $altshell = "/./$mshell";
my $altshell2 = "/././$mshell";
+
if ($mshell =~ m,^([a-zA-Z]:)([\\/])(.*),) {
$altshell = "$1$2.$2$3";
$altshell2 = "$1$2.$2.$2$3";
@@ -41,7 +39,7 @@ all:;@echo "$(SHELL) $$SHELL"
# As a GNU make extension, if make's SHELL variable is explicitly exported,
# then we really _DO_ export it.
-$extraENV{SHELL} = $mshell;
+$ENV{SHELL} = $mshell;
run_make_test("export SHELL := $altshell\n".'
all:;@echo "$(SHELL) $$SHELL"
@@ -51,13 +49,13 @@ all:;@echo "$(SHELL) $$SHELL"
# Test out setting of SHELL, both exported and not, as a target-specific
# variable.
-$extraENV{SHELL} = $mshell;
+$ENV{SHELL} = $mshell;
run_make_test("all: SHELL := $altshell\n".'
all:;@echo "$(SHELL) $$SHELL"
', '', "$altshell $mshell");
-$extraENV{SHELL} = $mshell;
+$ENV{SHELL} = $mshell;
run_make_test("
SHELL := $altshell2
diff --git a/tests/scripts/variables/automatic b/tests/scripts/variables/automatic
index 0b2e451..771bbda 100644
--- a/tests/scripts/variables/automatic
+++ b/tests/scripts/variables/automatic
@@ -91,6 +91,30 @@ mbr.src: ; @:',
'',
'mbr');
+# Same as above with second expansion.
+#
+run_make_test('
+.SECONDEXPANSION:
+.SUFFIXES: .b .src
+
+p:=mbr.src
+mbr.b: $$p
+ @echo $*
+
+mbr.src: ; @:',
+ '',
+ 'mbr');
+
+# Test that $* is set to empty string for unknown suffixes.
+
+run_make_test('
+mbr.b: mbr.src
+ @echo star=$*
+
+mbr.src: ; @:',
+ '',
+ "star=\n");
+
# TEST #3 -- test for Savannah bug #8154
# Make sure that nonexistent prerequisites are listed in $?, since they are
# considered reasons for the target to be rebuilt.
@@ -107,7 +131,7 @@ bar: ;',
unlink('foo');
-# TEST #4: ensure prereq ordering is correct when the commmand target has none
+# TEST #4: ensure prereq ordering is correct when the command target has none
# See Savannah bug #21198
run_make_test('
diff --git a/tests/scripts/variables/define b/tests/scripts/variables/define
index 7324cbc..eecbd8f 100644
--- a/tests/scripts/variables/define
+++ b/tests/scripts/variables/define
@@ -61,7 +61,7 @@ all: ; $(multi)
# TEST 1a: Various new-style define/endef, with no spaces
-run_make_test('
+run_make_test(q!
FOO = foo
define multi=
@@ -77,6 +77,10 @@ define posix::=
@echo $(FOO)
endef
+define posixbsd:::=
+@echo '$(FOO)$$bar'
+endef
+
append = @echo a
define append+=
@@ -97,10 +101,11 @@ FOO = there
all: ; $(multi)
$(simple)
$(posix)
+ $(posixbsd)
$(append)
$(cond)
-',
- '', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n");
+!,
+ '', "echo hi\nhi\nthere\nfoo\nfoo\nfoo\$bar\na\nb\nfirst\n");
# TEST 2: define in true section of conditional (containing conditional)
@@ -279,4 +284,22 @@ hello
world
');
+# Ensure that define can be a target when not appearing in a variable
+# definition context. See SV 59870
+
+run_make_test(q!
+define = define
+
+$(define) : ;@echo $@
+
+%:define
+
+all: define foo
+
+%.x : define
+
+foo:;
+!,
+ '', "define\n");
+
1;
diff --git a/tests/scripts/variables/flavors b/tests/scripts/variables/flavors
index 831e5d8..627672f 100644
--- a/tests/scripts/variables/flavors
+++ b/tests/scripts/variables/flavors
@@ -153,4 +153,48 @@ dep: ; @: $(info recur=/$(recur)/ simple=/$(simple)/)
!,
'', "recur=/onetwothree/ simple=/fourfivesix/\n");
+# Test POSIX :::=
+# This creates a recursive variable, but it expands the RHS first. Any
+# variable escapes ('$$') are preserved so that this recursive variable can be
+# expanded again without changing its contents.
+run_make_test('
+bar = Goodbye
+foo :::= $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Goodbye");
+
+# POSIX :::= no spaces
+run_make_test(q!
+bar = Goodbye
+foo:::=$(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+!,
+ '', "Goodbye");
+
+# Variable escapes ('$$') are preserved.
+run_make_test(q!
+bar = Good$$bye
+foo :::= $(bar) $$what
+bar = ${ugh}
+ugh = Hello
+all: ; @echo '$(foo)'
+!,
+ '', 'Good$bye $what');
+
+# Append works as expected
+run_make_test(q!
+bar = Good$$bye
+foo :::= $(bar)
+foo += $$what $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo '$(foo)'
+!,
+ '', 'Good$bye $what Hello');
+
1;
diff --git a/tests/scripts/variables/negative b/tests/scripts/variables/negative
index 0f9abc8..5cb600a 100644
--- a/tests/scripts/variables/negative
+++ b/tests/scripts/variables/negative
@@ -43,4 +43,18 @@ run_make_test(undef,
'#MAKEFILE#:4: *** unterminated variable reference. Stop.',
512);
+# Whitespace not allowed in variable names
+run_make_test('x y =', '',
+ '#MAKEFILE#:1: *** missing separator. Stop.', 512);
+
+run_make_test('x y=', '',
+ '#MAKEFILE#:1: *** missing separator. Stop.', 512);
+
+# In theory an empty variable should be ignored, but during parsing it's a
+# real token and so this fails. I'm not 100% sure if this is right or not.
+
+run_make_test('x $X=', '',
+ '#MAKEFILE#:1: *** missing separator. Stop.', 512);
+
+
1;
diff --git a/tests/scripts/variables/undefine b/tests/scripts/variables/undefine
index 38707b8..1732351 100644
--- a/tests/scripts/variables/undefine
+++ b/tests/scripts/variables/undefine
@@ -70,4 +70,22 @@ all: ;@echo ouch
',
'', "#MAKEFILE#:3: *** empty variable name. Stop.\n", 512);
+# Ensure that define can be a target when not appearing in a variable
+# definition context. See SV 59870
+
+run_make_test(q!
+undefine = undefine
+
+$(undefine) : ;@echo $@
+
+%:undefine
+
+all: undefine foo
+
+%.x : undefine
+
+foo:;
+!,
+ '', "undefine\n");
+
1;
diff --git a/tests/test_driver.pl b/tests/test_driver.pl
index f18e785..b64fffb 100644
--- a/tests/test_driver.pl
+++ b/tests/test_driver.pl
@@ -5,7 +5,7 @@
# Written 91-12-02 through 92-01-01 by Stephen McGee.
# Modified 92-02-11 through 92-02-22 by Chris Arthur to further generalize.
#
-# Copyright (C) 1991-2020 Free Software Foundation, Inc.
+# Copyright (C) 1991-2022 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@@ -19,7 +19,7 @@
# details.
#
# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>.
+# this program. If not, see <https://www.gnu.org/licenses/>.
# Test driver routines used by a number of test suites, including
@@ -33,6 +33,7 @@
use Config;
use Cwd;
use File::Spec;
+use File::Temp;
# The number of test categories we've run
$categories_run = 0;
@@ -47,48 +48,61 @@ $tests_run = 0;
# The number of tests in this category that have passed
$tests_passed = 0;
+$port_type = undef;
+$osname = undef;
+$vos = undef;
+$pathsep = undef;
# Yeesh. This whole test environment is such a hack!
$test_passed = 1;
# Timeout in seconds. If the test takes longer than this we'll fail it.
-$test_timeout = 5;
-$test_timeout = 10 if $^O eq 'VMS';
+# This is to prevent hung tests.
+$test_timeout = 60;
+
+$diff_name = undef;
# Path to Perl
$perl_name = $^X;
if ($^O ne 'VMS') {
$perl_name .= $Config{_exe} unless $perl_name =~ m/$Config{_exe}$/i;
}
-# If it's a simple name, look it up on PATH
-{
- my ($v,$d,$f) = File::Spec->splitpath($perl_name);
- if (!$d) {
- my $perl = undef;
- foreach my $p (File::Spec->path()) {
- my $f = File::Spec->catfile($p, $f);
- if (-e $f) {
- $perl = $f;
- last;
- }
- }
- if ($perl) {
- $perl_name = $perl;
- } else {
- print "Cannot locate Perl interpreter $perl_name\n";
- }
+
+sub which {
+ my $cmd = $_[0];
+
+ # Poor man's File::Which
+ my ($v,$d,$f) = File::Spec->splitpath($cmd);
+ if ($d) {
+ # The command has a pathname so don't look for it in PATH.
+ # Use forward-slashes even on Windows, else it fails in recipes.
+ (-f $cmd and -x _) or return undef;
+ $cmd =~ tr,\\,/,;
+ return $cmd;
+ }
+
+ my @ext;
+ if ($port_type eq 'UNIX' || $port_type eq 'VMS-DCL') {
+ @ext = ('');
+ } else {
+ @ext = index($f, '.') == -1 ? () : ('');
+ push @ext, split /;/, $ENV{PATHEXT};
+ }
+
+ foreach my $dir (File::Spec->path()) {
+ foreach my $e (@ext) {
+ my $p = File::Spec->catfile($dir, "$cmd$e");
+ (-f $p and -x _) or next;
+ # Use forward-slashes even on Windows, else it fails in recipes.
+ $p =~ tr,\\,/,;
+ return $p;
}
+ }
+ return undef;
}
-# Make sure it uses forward-slashes even on Windows, else it won't work
-# in recipes
-$perl_name =~ tr,\\,/,;
-
-# %makeENV is the cleaned-out environment.
-%makeENV = ();
-# %extraENV are any extra environment variables the tests might want to set.
-# These are RESET AFTER EVERY TEST!
-%extraENV = ();
+# %makeENV is the cleaned-out environment. Tests must not modify it.
+my %makeENV = ();
sub vms_get_process_logicals {
# Sorry for the long note here, but to keep this test running on
@@ -150,27 +164,45 @@ sub resetENV
}
}
}
+}
- foreach $v (keys %extraENV) {
- $ENV{$v} = $extraENV{$v};
- delete $extraENV{$v};
- }
+# Returns a string-ified version of cmd which is a value provided to exec()
+# so it can either be a ref of a list or a string.
+sub cmd2str
+{
+ my $cmd = $_[0];
+ if (!ref($cmd)) {
+ return $cmd;
+ }
+
+ my @c;
+ foreach (@$cmd) {
+ if (/[][#;"*?&|<>(){}\$`^~!]/) {
+ s/\'/\'\\'\'/g;
+ push @c, "'$_'";
+ } else {
+ push @c, $_;
+ }
+ }
+ return join(' ', @c);
}
sub toplevel
{
+ %origENV = %ENV unless $^O eq 'VMS';
+
# Pull in benign variables from the user's environment
- foreach (# UNIX-specific things
+ foreach (# POSIX-specific things
'TZ', 'TMPDIR', 'HOME', 'USER', 'LOGNAME', 'PATH',
'LD_LIBRARY_PATH',
- # SAN things
- 'ASAN_OPTIONS', 'UBSAN_OPTIONS',
+ # *SAN things
+ 'ASAN_OPTIONS', 'UBSAN_OPTIONS', 'LSAN_OPTIONS',
# Purify things
'PURIFYOPTIONS',
- # Windows NT-specific stuff
- 'Path', 'SystemRoot',
- # DJGPP-specific stuff
+ # Windows-specific things
+ 'Path', 'SystemRoot', 'TEMP', 'TMP', 'USERPROFILE', 'PATHEXT',
+ # DJGPP-specific things
'DJDIR', 'DJGPP', 'SHELL', 'COMSPEC', 'HOSTNAME', 'LFN',
'FNCASE', '387', 'EMU387', 'GROUP'
) {
@@ -180,12 +212,8 @@ sub toplevel
# Make sure our compares are not foiled by locale differences
$makeENV{LC_ALL} = 'C';
-
- # Replace the environment with the new one
- #
- %origENV = %ENV unless $^O eq 'VMS';
-
- resetENV();
+ $makeENV{LANG} = 'C';
+ $makeENV{LANGUAGE} = 'C';
$| = 1; # unbuffered output
@@ -195,6 +223,7 @@ sub toplevel
$detail = 0; # detailed verbosity
$keep = 0; # keep temp files around
$workdir = "work"; # The directory where the test will start running
+ $tempdir = "_tmp"; # A temporary directory
$scriptdir = "scripts"; # The directory where we find the test scripts
$tmpfilesuffix = "t"; # the suffix used on tmpfiles
$default_output_stack_level = 0; # used by attach_default_output, etc.
@@ -204,12 +233,40 @@ sub toplevel
&get_osname; # sets $osname, $vos, $pathsep, and $short_filenames
+ $perl_name = which($perl_name);
+
+ # See if we have a diff
+ $diff_name = which('diff');
+ if (!$diff_name) {
+ print "No diff found; differences will not be shown\n";
+ }
+
&set_defaults; # suite-defined
&parse_command_line (@ARGV);
print "OS name = '$osname'\n" if $debug;
+ $temppath = File::Spec->rel2abs($tempdir);
+
+ if (-d $temppath) {
+ print "Clearing $temppath...\n";
+ &remove_directory_tree("$temppath/")
+ or &error ("Couldn't wipe out $temppath: $!\n");
+ } else {
+ mkdir ($temppath, 0777) or error ("Cannot mkdir $temppath: $!\n");
+ }
+
+ # This is used by POSIX systems
+ $makeENV{TMPDIR} = $temppath;
+
+ # These are used on Windows
+ $makeENV{TMP} = $temppath;
+ $makeENV{TEMP} = $temppath;
+
+ # Replace the environment with the new one
+ resetENV();
+
$workpath = "$cwdslash$workdir";
$scriptpath = "$cwdslash$scriptdir";
@@ -237,9 +294,9 @@ sub toplevel
if (-d $workpath) {
print "Clearing $workpath...\n";
&remove_directory_tree("$workpath/")
- or &error ("Couldn't wipe out $workpath: $!\n");
+ or &error ("Couldn't wipe out $workpath: $!\n");
} else {
- mkdir ($workpath, 0777) or &error ("Couldn't mkdir $workpath: $!\n");
+ mkdir ($workpath, 0777) or &error ("Cannot mkdir $workpath: $!\n");
}
if (!-d $scriptpath) {
@@ -253,8 +310,8 @@ sub toplevel
$dir = $1;
push (@rmdirs, $dir);
-d "$workpath/$dir"
- or mkdir ("$workpath/$dir", 0777)
- or &error ("Couldn't mkdir $workpath/$dir: $!\n");
+ or mkdir ("$workpath/$dir", 0777)
+ or &error ("Couldn't mkdir $workpath/$dir: $!\n");
}
}
} else {
@@ -266,7 +323,7 @@ sub toplevel
foreach my $dir (@dirs) {
next if ($dir =~ /^(\..*|CVS|RCS)$/ || ! -d "$scriptpath/$dir");
push (@rmdirs, $dir);
- # VMS can have overlayed file systems, so directories may repeat.
+ # VMS can have overlaid file systems, so directories may repeat.
next if -d "$workpath/$dir";
mkdir ("$workpath/$dir", 0777)
or &error ("Couldn't mkdir $workpath/$dir: $!\n");
@@ -293,6 +350,8 @@ sub toplevel
rmdir ("$workpath/$dir");
}
+ rmdir ($temppath);
+
$| = 1;
$categories_failed = $categories_run - $categories_passed;
@@ -319,6 +378,8 @@ sub get_osname
{
# Set up an initial value. In perl5 we can do it the easy way.
$osname = defined($^O) ? $^O : '';
+ $vos = 0;
+ $pathsep = "/";
# find the type of the port. We do this up front to have a single
# point of change if it needs to be tweaked.
@@ -354,10 +415,7 @@ sub get_osname
$port_type = 'UNIX';
}
- if ($osname eq 'VMS')
- {
- $vos = 0;
- $pathsep = "/";
+ if ($osname eq 'VMS') {
return;
}
@@ -387,7 +445,7 @@ sub get_osname
$vos = 1;
$pathsep = ">";
- } else {
+ } elsif ($osname eq '') {
# the following is regrettably gnarly, but it seems to be the only way
# to not get ugly error messages if uname can't be found.
# Hmmm, BSD/OS 2.0's uname -a is excessively verbose. Let's try it
@@ -402,8 +460,6 @@ sub get_osname
$osname = "(something posixy)";
}
}
- $vos = 0;
- $pathsep = "/";
}
if (! $short_filenames) {
@@ -497,12 +553,12 @@ sub print_centered
sub print_banner
{
# $testee is suite-defined
- my $info = "Running tests for $testee on $osname\n";
- my $len = &max (length($info), length($testee_version), 73) + 5;
+ my $info = "Running tests for $testee on $osname";
+ my $len = &max (length($info), length($testee_version), 77) + 2;
my $line = ("-" x $len) . "\n";
&print_centered ($len, $line);
- &print_centered ($len, $info);
+ &print_centered ($len, $info."\n");
&print_centered ($len, $testee_version);
&print_centered ($len, $line);
print "\n";
@@ -515,11 +571,31 @@ sub run_all_tests
$categories_run = 0;
+ # Make a copy of STDIN so we can reset it
+ open(INCOPY, "<&STDIN");
+
+ # Leave enough space in the extensions to append a number, even
+ # though it needs to fit into 8+3 limits.
+ if ($short_filenames) {
+ $logext = 'l';
+ $diffext = 'd';
+ $baseext = 'b';
+ $runext = 'r';
+ $extext = '';
+ } else {
+ $logext = 'log';
+ $diffext = 'diff';
+ $baseext = 'base';
+ $runext = 'run';
+ $extext = '.';
+ }
+
$lasttest = '';
# $testname is published
foreach $testname (sort @TESTS) {
# Skip duplicates on VMS caused by logical name search lists.
next if $testname eq $lasttest;
+
$lasttest = $testname;
$suite_passed = 1; # reset by test on failure
$num_of_logfiles = 0;
@@ -531,21 +607,6 @@ sub run_all_tests
$perl_testname = "$scriptpath$pathsep$testname";
$testname =~ s/(\.pl|\.perl)$//;
$testpath = "$workpath$pathsep$testname";
- # Leave enough space in the extensions to append a number, even
- # though it needs to fit into 8+3 limits.
- if ($short_filenames) {
- $logext = 'l';
- $diffext = 'd';
- $baseext = 'b';
- $runext = 'r';
- $extext = '';
- } else {
- $logext = 'log';
- $diffext = 'diff';
- $baseext = 'base';
- $runext = 'run';
- $extext = '.';
- }
$extext = '_' if $^O eq 'VMS';
$log_filename = "$testpath.$logext";
$diff_filename = "$testpath.$diffext";
@@ -559,7 +620,7 @@ sub run_all_tests
$output = "........................................................ ";
- substr($output,0,length($testname)) = "$testname ";
+ substr($output, 0, length($testname)) = "$testname ";
print $output;
@@ -569,6 +630,9 @@ sub run_all_tests
# Run the test!
$code = do $perl_testname;
+ # Reset STDIN from the copy in case it was changed
+ open(STDIN, "<&INCOPY");
+
++$categories_run;
$total_tests_run += $tests_run;
$total_tests_passed += $tests_passed;
@@ -641,6 +705,8 @@ sub run_all_tests
print "$status\n";
}
+
+ close(INCOPY);
}
# If the keep flag is not set, this subroutine deletes all filenames that
@@ -740,13 +806,29 @@ sub error
die "$caller: $message";
}
+my %old_tempfiles = ();
+
sub compare_output
{
- my ($answer,$logfile) = @_;
- my ($slurp, $answer_matched) = ('', 0);
+ my ($answer, $logfile) = @_;
+ my ($slurp, $answer_matched, $extra) = ('', 0, 0);
++$tests_run;
+ my @tf = ();
+ foreach my $file (glob(File::Spec->catfile($temppath, "*"))) {
+ if (!exists $old_tempfiles{$file}) {
+ push @tf, $file;
+ $old_tempfiles{$file} = 1;
+ }
+ }
+ if (@tf) {
+ open (LOGFILE, '>>', $logfile) or die "Cannot open log file $logfile: $!\n";
+ print LOGFILE "Leftover temporary files: @tf\n";
+ close (LOGFILE);
+ $extra = 1;
+ }
+
if (! defined $answer) {
print "Ignoring output ........ " if $debug;
$answer_matched = 1;
@@ -773,7 +855,8 @@ sub compare_output
$slurp_mod =~ s,\r\n,\n,gs;
$answer_matched = ($slurp_mod eq $answer_mod);
- if ($^O eq 'VMS') {
+
+ if (!$answer_matched && $^O eq 'VMS') {
# VMS has extra blank lines in output sometimes.
# Ticket #41760
@@ -899,7 +982,12 @@ sub compare_output
}
}
- if ($answer_matched && $test_passed) {
+ if ($keep || ! $answer_matched) {
+ &create_file(&get_basefile, $answer);
+ &create_file(&get_runfile, $command_string);
+ }
+
+ if ($answer_matched && $test_passed && !$extra) {
print "ok\n" if $debug;
++$tests_passed;
return 1;
@@ -908,15 +996,16 @@ sub compare_output
if (! $answer_matched) {
print "DIFFERENT OUTPUT\n" if $debug;
- &create_file (&get_basefile, $answer);
- &create_file (&get_runfile, $command_string);
-
print "\nCreating Difference File ...\n" if $debug;
# Create the difference file
-
- my $command = "diff -c " . &get_basefile . " " . $logfile;
- &run_command_with_output(&get_difffile,$command);
+ my $base = get_basefile();
+ if ($diff_name) {
+ my $command = "$diff_name -c $base $logfile";
+ &run_command_with_output(get_difffile(), $command);
+ } else {
+ create_file(get_difffile(), "Log file $logfile differs from base file $base\n");
+ }
}
return 0;
@@ -947,7 +1036,7 @@ sub attach_default_output
if ($vos)
{
my $code = system "++attach_default_output_hack $filename";
- $code == -2 or &error ("adoh death\n", 1);
+ $code == -2 or &error ("ado death\n", 1);
return 1;
}
@@ -1059,15 +1148,13 @@ sub _run_with_timeout
# This runs a command without any debugging info.
sub _run_command
{
- # We reset this before every invocation. On Windows I think there is only
- # one environment, not one per process, so I think that variables set in
- # test scripts might leak into subsequent tests if this isn't reset--???
- resetENV();
-
my $orig = $SIG{ALRM};
my $code = eval { _run_with_timeout(@_); };
$SIG{ALRM} = $orig;
+ # Reset then environment so that it's clean for the next test.
+ resetENV();
+
if ($@) {
# The eval failed. If it wasn't SIGALRM then die.
$@ eq "timeout\n" or die "Command failed: $@";
diff --git a/tests/thelp.pl b/tests/thelp.pl
index d8aaa66..993339c 100755
--- a/tests/thelp.pl
+++ b/tests/thelp.pl
@@ -8,7 +8,8 @@
# Each step consists of an operator and argument.
#
# It supports the following operators:
-# out <word> : echo <word> to stdout
+# out <word> : echo <word> to stdout with a newline
+# raw <word> : echo <word> to stdout without adding anything
# file <word> : echo <word> to stdout AND create the file <word>
# dir <word> : echo <word> to stdout AND create the directory <word>
# rm <word> : echo <word> to stdout AND delete the file/directory <word>
@@ -23,7 +24,7 @@
$| = 1;
my $quiet = 0;
-my $timeout = 4;
+my $timeout = 10;
sub op {
my ($op, $nm) = @_;
@@ -34,6 +35,10 @@ sub op {
print "$nm\n";
return 1;
}
+ if ($op eq 'raw') {
+ print "$nm";
+ return 1;
+ }
# Show the output before creating the file
if ($op eq 'file') {