From 29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:21:29 +0200 Subject: Adding upstream version 1:0.1.9998svn3589+dfsg. Signed-off-by: Daniel Baumann --- src/kmk/tests/scripts/features/archives | 213 ++++++ src/kmk/tests/scripts/features/comments | 35 + src/kmk/tests/scripts/features/conditionals | 162 ++++ src/kmk/tests/scripts/features/default_names | 44 ++ src/kmk/tests/scripts/features/double_colon | 220 ++++++ src/kmk/tests/scripts/features/echoing | 64 ++ src/kmk/tests/scripts/features/errors | 107 +++ src/kmk/tests/scripts/features/escape | 74 ++ src/kmk/tests/scripts/features/export | 186 +++++ src/kmk/tests/scripts/features/ifcond | 950 ++++++++++++++++++++++++ src/kmk/tests/scripts/features/include | 243 ++++++ src/kmk/tests/scripts/features/jobserver | 107 +++ src/kmk/tests/scripts/features/load | 110 +++ src/kmk/tests/scripts/features/loadapi | 116 +++ src/kmk/tests/scripts/features/mult_rules | 78 ++ src/kmk/tests/scripts/features/mult_targets | 46 ++ src/kmk/tests/scripts/features/order_only | 118 +++ src/kmk/tests/scripts/features/output-sync | 349 +++++++++ src/kmk/tests/scripts/features/override | 45 ++ src/kmk/tests/scripts/features/parallelism | 231 ++++++ src/kmk/tests/scripts/features/patspecific_vars | 148 ++++ src/kmk/tests/scripts/features/patternrules | 232 ++++++ src/kmk/tests/scripts/features/quoting | 32 + src/kmk/tests/scripts/features/recursion | 55 ++ src/kmk/tests/scripts/features/reinvoke | 80 ++ src/kmk/tests/scripts/features/rule_glob | 37 + src/kmk/tests/scripts/features/se_explicit | 169 +++++ src/kmk/tests/scripts/features/se_implicit | 260 +++++++ src/kmk/tests/scripts/features/se_statpat | 109 +++ src/kmk/tests/scripts/features/shell_assignment | 65 ++ src/kmk/tests/scripts/features/statipattrules | 111 +++ src/kmk/tests/scripts/features/targetvars | 273 +++++++ src/kmk/tests/scripts/features/utf8 | 11 + src/kmk/tests/scripts/features/varnesting | 35 + src/kmk/tests/scripts/features/vpath | 82 ++ src/kmk/tests/scripts/features/vpath2 | 45 ++ src/kmk/tests/scripts/features/vpath3 | 41 + src/kmk/tests/scripts/features/vpathgpath | 66 ++ src/kmk/tests/scripts/features/vpathplus | 132 ++++ 39 files changed, 5481 insertions(+) create mode 100644 src/kmk/tests/scripts/features/archives create mode 100644 src/kmk/tests/scripts/features/comments create mode 100644 src/kmk/tests/scripts/features/conditionals create mode 100644 src/kmk/tests/scripts/features/default_names create mode 100644 src/kmk/tests/scripts/features/double_colon create mode 100644 src/kmk/tests/scripts/features/echoing create mode 100644 src/kmk/tests/scripts/features/errors create mode 100644 src/kmk/tests/scripts/features/escape create mode 100644 src/kmk/tests/scripts/features/export create mode 100644 src/kmk/tests/scripts/features/ifcond create mode 100644 src/kmk/tests/scripts/features/include create mode 100644 src/kmk/tests/scripts/features/jobserver create mode 100644 src/kmk/tests/scripts/features/load create mode 100644 src/kmk/tests/scripts/features/loadapi create mode 100644 src/kmk/tests/scripts/features/mult_rules create mode 100644 src/kmk/tests/scripts/features/mult_targets create mode 100644 src/kmk/tests/scripts/features/order_only create mode 100644 src/kmk/tests/scripts/features/output-sync create mode 100644 src/kmk/tests/scripts/features/override create mode 100644 src/kmk/tests/scripts/features/parallelism create mode 100644 src/kmk/tests/scripts/features/patspecific_vars create mode 100644 src/kmk/tests/scripts/features/patternrules create mode 100644 src/kmk/tests/scripts/features/quoting create mode 100644 src/kmk/tests/scripts/features/recursion create mode 100644 src/kmk/tests/scripts/features/reinvoke create mode 100644 src/kmk/tests/scripts/features/rule_glob create mode 100644 src/kmk/tests/scripts/features/se_explicit create mode 100644 src/kmk/tests/scripts/features/se_implicit create mode 100644 src/kmk/tests/scripts/features/se_statpat create mode 100644 src/kmk/tests/scripts/features/shell_assignment create mode 100644 src/kmk/tests/scripts/features/statipattrules create mode 100644 src/kmk/tests/scripts/features/targetvars create mode 100644 src/kmk/tests/scripts/features/utf8 create mode 100644 src/kmk/tests/scripts/features/varnesting create mode 100644 src/kmk/tests/scripts/features/vpath create mode 100644 src/kmk/tests/scripts/features/vpath2 create mode 100644 src/kmk/tests/scripts/features/vpath3 create mode 100644 src/kmk/tests/scripts/features/vpathgpath create mode 100644 src/kmk/tests/scripts/features/vpathplus (limited to 'src/kmk/tests/scripts/features') diff --git a/src/kmk/tests/scripts/features/archives b/src/kmk/tests/scripts/features/archives new file mode 100644 index 0000000..a064dd4 --- /dev/null +++ b/src/kmk/tests/scripts/features/archives @@ -0,0 +1,213 @@ +# -*-mode: perl-*- + +$description = "Test GNU make's archive management features."; + +$details = "\ +This only works on systems that support it."; + +# If this instance of make doesn't support archives, skip it +exists $FEATURES{archives} or return -1; + +# Create some .o files to work with +if ($osname eq 'VMS') { + use Cwd; + my $pwd = getcwd; + # VMS AR needs real object files at this time. + foreach $afile ('a1', 'a2', 'a3') { + # Use non-standard extension to prevent implicit rules from recreating + # objects when the test tampers with the timestamp. + 1 while unlink "$afile.c1"; + 1 while unlink "$afile.o"; + open (MYFILE, ">$afile.c1"); + print MYFILE "int $afile(void) {return 1;}\n"; + close MYFILE; + system("cc $afile.c1 /object=$afile.o"); + } +} else { + utouch(-60, qw(a1.o a2.o a3.o)); +} + +my $ar = $CONFIG_FLAGS{AR}; + +# Fallback if configure did not find AR, such as VMS +# which does not run configure. +$ar = 'ar' if $ar eq ''; + +my $redir = '2>&1'; +$redir = '' if $osname eq 'VMS'; + +my $arflags = '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`; +if ($? == 0) { + $arflags = 'Urv'; + $arvar = "$arvar ARFLAGS=$arflags"; +} + +# Some versions of ar print different things on creation. Find out. +unlink('libxx.a'); +my $created = `$ar $arflags libxx.a a1.o $redir`; + +# Some versions of ar print different things on add. Find out. +my $add = `$ar $arflags libxx.a a2.o $redir`; +$add =~ s/a2\.o/#OBJECT#/g; + +# Some versions of ar print different things on replacement. Find out. +my $repl = `$ar $arflags libxx.a a2.o $redir`; +$repl =~ s/a2\.o/#OBJECT#/g; + +unlink('libxx.a'); + +# Very simple +my $answer = "$ar $arflags libxx.a a1.o\n$created"; +if ($port_type eq 'VMS-DCL') { + $answer = 'library /replace libxx.a a1.o'; +} +run_make_test('all: libxx.a(a1.o)', $arvar, $answer); + +# Multiple .o's. Add a new one to the existing library +($_ = $add) =~ s/#OBJECT#/a2.o/g; + +$answer = "$ar $arflags libxx.a a2.o\n$_"; +if ($port_type eq 'VMS-DCL') { + $answer = 'library /replace libxx.a a2.o'; +} +run_make_test('all: libxx.a(a1.o a2.o)', $arvar, $answer); + +# Touch one of the .o's so it's rebuilt +if ($port_type eq 'VMS-DCL') { + # utouch is not changing what VMS library compare is testing for. + # So do a real change by regenerating the file. + 1 while unlink('a1.o'); + # Later time stamp than last insertion. + sleep(2); + system('cc a1.c1 /object=a1.o'); + # Next insertion will have a later timestamp. + sleep(2); +} else { + utouch(-40, 'a1.o'); +} + +($_ = $repl) =~ s/#OBJECT#/a1.o/g; +$answer = "$ar $arflags libxx.a a1.o\n$_"; +if ($port_type eq 'VMS-DCL') { + $answer = 'library /replace libxx.a a1.o'; +} +run_make_test(undef, $arvar, $answer); + +# Use wildcards +$answer = "#MAKE#: Nothing to be done for 'all'.\n"; +run_make_test('all: libxx.a(*.o)', $arvar, $answer); + +# Touch one of the .o's so it's rebuilt +if ($port_type eq 'VMS-DCL') { + # utouch is not changing what VMS library compare is testing for. + # So do a real change by regenerating the file. + 1 while unlink('a1.o'); + # Make timestamp later than last insertion. + sleep(2); + system('cc a1.c1 /object=a1.o'); +} else { + utouch(-30, 'a1.o'); +} +($_ = $repl) =~ s/#OBJECT#/a1.o/g; +$answer = "$ar $arflags libxx.a a1.o\n$_"; +if ($port_type eq 'VMS-DCL') { + $answer = 'library /replace libxx.a a1.o'; +} +run_make_test(undef, $arvar, $answer); + +# Use both wildcards and simple names +if ($port_type eq 'VMS-DCL') { + # utouch is not changing what VMS library compare is testing for. + # So do a real change by regenerating the file. + 1 while unlink('a2.o'); + sleep(2); + system('cc a2.c1 /object=a2.o'); +} else { + utouch(-50, 'a2.o'); +} +($_ = $add) =~ s/#OBJECT#/a3.o/g; +$_ .= "$ar $arflags libxx.a a2.o\n"; +($_ .= $repl) =~ s/#OBJECT#/a2.o/g; +$answer = "$ar $arflags libxx.a a3.o\n$_"; +if ($port_type eq 'VMS-DCL') { + $answer = 'library /replace libxx.a a3.o'; +} + +run_make_test('all: libxx.a(a3.o *.o)', $arvar, $answer); + +# Check whitespace handling +if ($port_type eq 'VMS-DCL') { + # utouch is not changing what VMS library compare is testing for. + # So do a real change by regenerating the file. + 1 while unlink('a2.o'); + sleep(2); + system('cc a2.c1 /object=a2.o'); +} else { + utouch(-40, 'a2.o'); +} +($_ = $repl) =~ s/#OBJECT#/a2.o/g; +$answer = "$ar $arflags libxx.a a2.o\n$_"; +if ($port_type eq 'VMS-DCL') { + $answer = 'library /replace libxx.a a2.o'; +} +run_make_test('all: libxx.a( a3.o *.o )', $arvar, $answer); + +rmfiles(qw(a1.c1 a2.c1 a3.c1 a1.o a2.o a3.o libxx.a)); + +# Check non-archive targets +# See Savannah bug #37878 +$mk_string = q! +all: foo(bar).baz +foo(bar).baz: ; @echo '$@' +!; + +if ($port_type eq 'VMS-DCL') { + $mk_string =~ s/echo/write sys\$\$output/; + $mk_string =~ s/\'/\"/g; +} +run_make_test($mk_string, $arvar, "foo(bar).baz\n"); + +# Check renaming of archive targets. +# See Savannah bug #38442 + +mkdir('artest', 0777); +touch('foo.vhd'); +$mk_string = q! +DIR = artest +vpath % $(DIR) +default: lib(foo) +(%): %.vhd ; @cd $(DIR) && touch $(*F) && $(AR) $(ARFLAGS) $@ $(*F) >/dev/null 2>&1 && rm $(*F) +.PHONY: default +!; +if ($port_type eq 'VMS-DCL') { + $mk_string =~ s#= artest#= sys\$\$disk:\[.artest\]#; + $mk_string =~ s#lib\(foo\)#lib.tlb\(foo\)#; + $mk_string =~ s#; \@cd#; pipe SET DEFAULT#; + $mk_string =~ + s#touch \$\(\*F\)#touch \$\(\*F\) && library/create/text sys\$\$disk:\$\@#; + $mk_string =~ + s#library#if f\$\$search(\"\$\@\") \.eqs\. \"\" then library#; + # VMS needs special handling for null extension + $mk_string =~ s#\@ \$\(\*F\)#\@ \$\(\*F\)\.#; + $mk_string =~ s#>/dev/null 2>&1 ##; +} +run_make_test($mk_string, $arvar, ""); + +run_make_test(undef, $arvar, "#MAKE#: Nothing to be done for 'default'.\n"); + +unlink('foo.vhd'); +if ($osname eq 'VMS') { + remove_directory_tree("$pwd/artest"); +} else { + remove_directory_tree('artest'); +} + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/comments b/src/kmk/tests/scripts/features/comments new file mode 100644 index 0000000..9257955 --- /dev/null +++ b/src/kmk/tests/scripts/features/comments @@ -0,0 +1,35 @@ +$description = "The following test creates a makefile to test comments\n" + ."and comment continuation to the next line using a \n" + ."backslash within makefiles."; + +$details = "To test comments within a makefile, a semi-colon was placed \n" + ."after a comment was started. This should not be reported as\n" + ."an error since it is within a comment. We then continue the \n" + ."comment to the next line using a backslash. To test whether\n" + ."the comment really continued, we place an echo command with some\n" + ."text on the line which should never execute since it should be \n" + ."within a comment\n"; + +open(MAKEFILE,"> $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE <<\EOF; +# Test comment vs semicolon parsing and line continuation +target: # this ; is just a comment \ + @echo This is within a comment. + @echo There should be no errors for this makefile. +EOF + +# 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 = "There should be no errors for this makefile.\n"; + +# COMPARE RESULTS + +&compare_output($answer,&get_logfile(1)) diff --git a/src/kmk/tests/scripts/features/conditionals b/src/kmk/tests/scripts/features/conditionals new file mode 100644 index 0000000..78344b9 --- /dev/null +++ b/src/kmk/tests/scripts/features/conditionals @@ -0,0 +1,162 @@ +# -*-perl-*- +$description = "Check GNU make conditionals."; + +$details = "Attempt various different flavors of GNU make conditionals."; + +run_make_test(' +arg1 = first +arg2 = second +arg3 = third +arg4 = cc +arg5 = second + +all: +ifeq ($(arg1),$(arg2)) + @echo arg1 equals arg2 +else + @echo arg1 NOT equal arg2 +endif + +ifeq \'$(arg2)\' "$(arg5)" + @echo arg2 equals arg5 +else + @echo arg2 NOT equal arg5 +endif + +ifneq \'$(arg3)\' \'$(arg4)\' + @echo arg3 NOT equal arg4 +else + @echo arg3 equal arg4 +endif + +ifndef undefined + @echo variable is undefined +else + @echo variable undefined is defined +endif +ifdef arg4 + @echo arg4 is defined +else + @echo arg4 is NOT defined +endif', + '', + 'arg1 NOT equal arg2 +arg2 equals arg5 +arg3 NOT equal arg4 +variable is undefined +arg4 is defined'); + + +# Test expansion of variables inside ifdef. + +run_make_test(' +foo = 1 + +FOO = foo +F = f + +DEF = no +DEF2 = no + +ifdef $(FOO) +DEF = yes +endif + +ifdef $(F)oo +DEF2 = yes +endif + + +DEF3 = no +FUNC = $1 +ifdef $(call FUNC,DEF)3 + DEF3 = yes +endif + +all:; @echo DEF=$(DEF) DEF2=$(DEF2) DEF3=$(DEF3)', + '', + 'DEF=yes DEF2=yes DEF3=yes'); + + +# Test all the different "else if..." constructs + +run_make_test(' +arg1 = first +arg2 = second +arg3 = third +arg4 = cc +arg5 = fifth + +result = + +ifeq ($(arg1),$(arg2)) + result += arg1 equals arg2 +else ifeq \'$(arg2)\' "$(arg5)" + result += arg2 equals arg5 +else ifneq \'$(arg3)\' \'$(arg3)\' + result += arg3 NOT equal arg4 +else ifndef arg5 + result += variable is undefined +else ifdef undefined + result += arg4 is defined +else + result += success +endif + + +all: ; @echo $(result)', + '', + 'success'); + + +# Test some random "else if..." construct nesting + +run_make_test(' +arg1 = first +arg2 = second +arg3 = third +arg4 = cc +arg5 = second + +ifeq ($(arg1),$(arg2)) + $(info failed 1) +else ifeq \'$(arg2)\' "$(arg2)" + ifdef undefined + $(info failed 2) + else + $(info success) + endif +else ifneq \'$(arg3)\' \'$(arg3)\' + $(info failed 3) +else ifdef arg5 + $(info failed 4) +else ifdef undefined + $(info failed 5) +else + $(info failed 6) +endif + +.PHONY: all +all: ; @:', + '', + 'success'); + +# SV 47960 : ensure variable assignments in non-taken legs don't cause problems +run_make_test(' +ifneq ($(FOO),yes) +target: +else +BAR = bar +target: +endif + @echo one +', + '', "one\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/src/kmk/tests/scripts/features/default_names b/src/kmk/tests/scripts/features/default_names new file mode 100644 index 0000000..2e83880 --- /dev/null +++ b/src/kmk/tests/scripts/features/default_names @@ -0,0 +1,44 @@ +# -*-perl-*- + +$description = "This script tests to make sure that Make looks for +default makefiles in the correct order (GNUmakefile,makefile,Makefile)"; + +# Create a makefile called "GNUmakefile" +$makefile = "GNUmakefile"; + +open(MAKEFILE,"> $makefile"); +print MAKEFILE "FIRST: ; \@echo It chose GNUmakefile\n"; +close(MAKEFILE); + +# Create another makefile called "makefile" +open(MAKEFILE,"> makefile"); +print MAKEFILE "SECOND: ; \@echo It chose makefile\n"; +close(MAKEFILE); + +# DOS/WIN32/MacOSX platforms are case-insensitive / case-preserving, so +# Makefile is the same file as makefile. Just test what we can here. + +my $case_sensitive = 0; +if (! -f 'Makefile') { + # Create another makefile called "Makefile" + $case_sensitive = 1; + open(MAKEFILE,"> Makefile"); + print MAKEFILE "THIRD: ; \@echo It chose Makefile\n"; + close(MAKEFILE); +} + +run_make_with_options("","",&get_logfile); +compare_output("It chose GNUmakefile\n",&get_logfile(1)); +unlink($makefile); + +run_make_with_options("","",&get_logfile); +compare_output("It chose makefile\n",&get_logfile(1)); +unlink("makefile"); + +if ($case_sensitive) { + run_make_with_options("","",&get_logfile); + compare_output("It chose Makefile\n",&get_logfile(1)); + unlink("Makefile"); +} + +1; diff --git a/src/kmk/tests/scripts/features/double_colon b/src/kmk/tests/scripts/features/double_colon new file mode 100644 index 0000000..58f126f --- /dev/null +++ b/src/kmk/tests/scripts/features/double_colon @@ -0,0 +1,220 @@ +# -*-perl-*- +$description = "Test handling of double-colon rules."; + +$details = "\ +We test these features: + + - Multiple commands for the same (double-colon) target + - Different prerequisites for targets: only out-of-date + ones are rebuilt. + - Double-colon targets that aren't the goal target. + +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'; + +all: baz + +foo:: f1.h ; @echo foo FIRST +foo:: f2.h ; @echo foo SECOND + +bar:: ; @echo aaa; sleep 1; echo aaa done +bar:: ; @echo bbb + +baz:: ; @echo aaa +baz:: ; @echo bbb + +biz:: ; @echo aaa +biz:: two ; @echo bbb + +two: ; @echo two + +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)); + +# 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)); +} + +# 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)); + +# 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)); +} + +# TEST 4: Each double-colon rule is supposed to be run individually + +&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)); + +# 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)); +} + +# TEST 6: Each double-colon rule is supposed to be run individually + +&utouch(-5, 'f1.h'); +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)); + +# 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)); +} + +# 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)); + +# 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)); +#} + +unlink('foo','f1.h','f2.h'); + + +# TEST 9: make sure all rules in s double colon family get executed +# (Savannah bug #14334). +# + +&touch('one'); +&touch('two'); + +run_make_test(' +.PHONY: all +all: result + +result:: one + @echo $^ >>$@ + @echo $^ + +result:: two + @echo $^ >>$@ + @echo $^ + +', +'', +'one +two'); + +unlink('result','one','two'); + +# TEST 10: SV 33399 : check for proper backslash handling + +run_make_test(' +a\ xb :: ; @echo one +a\ xb :: ; @echo two +', + '', "one\ntwo\n"); + +# Test 11: SV 44742 : All double-colon rules should be run in parallel build. + +run_make_test('result :: 01 + @echo update + @touch $@ +result :: 02 + @echo update + @touch $@ +result :: 03 + @echo update + @touch $@ +result :: 04 + @echo update + @touch $@ +result :: 05 + @echo update + @touch $@ +01 02 03 04 05: + @touch 01 02 03 04 05 +', + '-j10 result', "update\nupdate\nupdate\nupdate\nupdate\n"); + +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 $* +', + '-rs -j2 1 2 root', "all_one\nall_two\nroot\n"); + +# SV 47995 : Parallel double-colon rules with FORCE + +run_make_test(' +all:: ; @echo one + +all:: joe ; @echo four + +joe: FORCE ; touch joe-is-forced + +FORCE: +', + '-j5', "one\ntouch joe-is-forced\nfour\n"); + +unlink('joe-is-forced'); + +# 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/src/kmk/tests/scripts/features/echoing b/src/kmk/tests/scripts/features/echoing new file mode 100644 index 0000000..40debf5 --- /dev/null +++ b/src/kmk/tests/scripts/features/echoing @@ -0,0 +1,64 @@ +# -*-perl-*- +$description = "The following test creates a makefile to test command +echoing. It tests that when a command line starts with +a '\@', the echoing of that line is suppressed. It also +tests the -n option which tells make to ONLY echo the +commands and no execution happens. In this case, even +the commands with '\@' are printed. Lastly, it tests the +-s flag which tells make to prevent all echoing, as if +all commands started with a '\@'."; + +$details = "This test is similar to the 'clean' test except that a '\@' has +been placed in front of the delete command line. Four tests +are run here. First, make is run normally and the first echo +command should be executed. In this case there is no '\@' so +we should expect make to display the command AND display the +echoed message. Secondly, make is run with the clean target, +but since there is a '\@' at the beginning of the command, we +expect no output; just the deletion of a file which we check +for. Third, we give the clean target again except this time +we give make the -n option. We now expect the command to be +displayed but not to be executed. In this case we need only +to check the output since an error message would be displayed +if it actually tried to run the delete command again and the +file didn't exist. Lastly, we run the first test again with +the -s option and check that make did not echo the echo +command before printing the message.\n"; + +$example = "EXAMPLE_FILE"; + +touch($example); + +# TEST #1 +# ------- + +run_make_test(" +all: +\techo This makefile did not clean the dir... good +clean: +\t\@$delete_command $example\n", + '', 'echo This makefile did not clean the dir... good +This makefile did not clean the dir... good'); + +# TEST #2 +# ------- + +run_make_test(undef, 'clean', ''); +if (-f $example) { + $test_passed = 0; + unlink($example); +} + +# TEST #3 +# ------- + +run_make_test(undef, '-n clean', "$delete_command $example\n"); + + +# TEST #4 +# ------- + +run_make_test(undef, '-s', "This makefile did not clean the dir... good\n"); + + +1; diff --git a/src/kmk/tests/scripts/features/errors b/src/kmk/tests/scripts/features/errors new file mode 100644 index 0000000..ebd4383 --- /dev/null +++ b/src/kmk/tests/scripts/features/errors @@ -0,0 +1,107 @@ +# -*-perl-*- + +$description = "The following tests the -i option and the '-' in front of \n" + ."commands to test that make ignores errors in these commands\n" + ."and continues processing."; + +$details = "This test runs two makes. The first runs on a target with a \n" + ."command that has a '-' in front of it (and a command that is \n" + ."intended to fail) and then a delete command after that is \n" + ."intended to succeed. If make ignores the failure of the first\n" + ."command as it is supposed to, then the second command should \n" + ."delete a file and this is what we check for. The second make\n" + ."that is run in this test is identical except that the make \n" + ."command is given with the -i option instead of the '-' in \n" + ."front of the command. They should run the same. "; + +if ($vos) +{ + $rm_command = "delete_file"; +} +else +{ + $rm_command = "rm"; +} + +open(MAKEFILE,"> $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE "clean:\n" + ."\t-$rm_command cleanit\n" + ."\t$rm_command foo\n" + ."clean2: \n" + ."\t$rm_command cleanit\n" + ."\t$rm_command foo\n"; + +# END of Contents of MAKEFILE + +close(MAKEFILE); + +&touch("foo"); + +unlink("cleanit"); +$cleanit_error = `sh -c "$rm_command cleanit 2>&1"`; +chomp $cleanit_error; +$delete_error_code = $? >> 8; + +# TEST #1 +# ------- + +$answer = "$rm_command cleanit +$cleanit_error +$make_name: [$makefile:2: clean] Error $delete_error_code (ignored) +$rm_command foo\n"; + +&run_make_with_options($makefile,"",&get_logfile); + +# If make acted as planned, it should ignore the error from the first +# command in the target and execute the second which deletes the file "foo" +# This file, therefore, should not exist if the test PASSES. +if (-f "foo") { + $test_passed = 0; +} + +# The output for this on VOS is too hard to replicate, so we only check it +# on unix. +if (!$vos) +{ + &compare_output($answer,&get_logfile(1)); +} + + +&touch("foo"); + +# TEST #2 +# ------- + +$answer = "$rm_command cleanit +$cleanit_error +$make_name: [$makefile:5: clean2] Error $delete_error_code (ignored) +$rm_command foo\n"; + +&run_make_with_options($makefile,"clean2 -i",&get_logfile); + +if (-f "foo") { + $test_passed = 0; +} + +if (!$vos) { + &compare_output($answer,&get_logfile(1)); +} + +# Test that error line offset works + +run_make_test(q! +all: + @echo hi + @echo there + @exit 1 +!, + '', "hi\nthere\n#MAKE#: *** [#MAKEFILE#:5: all] Error 1", 512); + +1; + +### Local Variables: +### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) +### End: diff --git a/src/kmk/tests/scripts/features/escape b/src/kmk/tests/scripts/features/escape new file mode 100644 index 0000000..5fcb023 --- /dev/null +++ b/src/kmk/tests/scripts/features/escape @@ -0,0 +1,74 @@ +# -*-perl-*- +$description = "Test various types of escaping in makefiles."; + +$details = "\ +Make sure that escaping of ':' works in target names. +Make sure escaping of whitespace works in target names. +Make sure that escaping of '#' works. +Make sure that backslash before non-special characters are kept."; + + +# TEST 1 + +run_make_test(' +$(path)foo : ; @echo "touch ($@)" + +foo\ bar: ; @echo "touch ($@)" + +sharp: foo\#bar.ext +foo\#bar.ext: ; @echo "foo#bar.ext = ($@)"', + '', + 'touch (foo)'); + +# TEST 2: This one should fail, since the ":" is unquoted. + +run_make_test(undef, + 'path=pre:', + "#MAKEFILE#:2: *** target pattern contains no '%' (target 'foo'). Stop.", + 512); + +# TEST 3: This one should work, since we escape the ":". + +run_make_test(undef, + "'path=pre\\:'", + 'touch (pre:foo)'); + +# TEST 4: This one should fail, since the escape char is escaped. + +run_make_test(undef, + "'path=pre\\\\:'", + "#MAKEFILE#:2: *** target pattern contains no '%' (target 'foo'). Stop.", + 512); + +# TEST 5: This one should work + +run_make_test(undef, + "'foo bar'", + 'touch (foo bar)'); + +# TEST 6: Test escaped comments + +run_make_test(undef, + 'sharp', + 'foo#bar.ext = (foo#bar.ext)'); + +# Test escaped colons in prerequisites +# Quoting of backslashes in q!! is kind of messy. +# Solaris sh does not properly handle backslashes even in '' so just +# check the output make prints, not what the shell interprets. +run_make_test(q! +foo: foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar +foo foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar: ; : '$@' +!, + '', ": 'foo:bar'\n: 'foo\\:bar'\n: 'foo\\\\:bar'\n: 'foo'\n"); + +# Test backslash before non-special chars: should be kept as-is + +run_make_test(q! +all: ..\foo +.DEFAULT: ; : '$@' +!, + '', ": '..\\foo'\n"); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/export b/src/kmk/tests/scripts/features/export new file mode 100644 index 0000000..81bff0c --- /dev/null +++ b/src/kmk/tests/scripts/features/export @@ -0,0 +1,186 @@ +# -*-perl-*- +$description = "Check GNU make export/unexport commands."; + +$details = ""; + +# The test driver cleans out our environment for us so we don't have to worry +# about that here. + +&run_make_test(' +FOO = foo +BAR = bar +BOZ = boz + +export BAZ = baz +export BOZ + +BITZ = bitz +BOTZ = botz + +export BITZ BOTZ +unexport BOTZ + +ifdef EXPORT_ALL +export +endif + +ifdef UNEXPORT_ALL +unexport +endif + +ifdef EXPORT_ALL_PSEUDO +.EXPORT_ALL_VARIABLES: +endif + +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" +', + '', "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; + +&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"); + +# TEST 2: global export. Explicit unexport takes precedence. + +run_make_test(undef, "EXPORT_ALL=1" , + "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); + +# TEST 3: global unexport. Explicit export takes precedence. + +&run_make_test(undef, "UNEXPORT_ALL=1", + "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); + +# TEST 4: both: in the above makefile the unexport comes last so that rules. + +&run_make_test(undef, "EXPORT_ALL=1 UNEXPORT_ALL=1", + "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); + +# TEST 5: test the pseudo target. + +&run_make_test(undef, "EXPORT_ALL_PSEUDO=1", + "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); + +# TEST 6: Test the expansion of variables inside export + +&run_make_test(' +foo = f-ok +bar = b-ok + +FOO = foo +F = f + +BAR = bar +B = b + +export $(FOO) +export $(B)ar + +all: + @echo foo=$(foo) bar=$(bar) + @echo foo=$$foo bar=$$bar +', + "", "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n"); + +# TEST 7: Test the expansion of variables inside unexport + +&run_make_test(' +foo = f-ok +bar = b-ok + +FOO = foo +F = f + +BAR = bar +B = b + +export foo bar + +unexport $(FOO) +unexport $(B)ar + +all: + @echo foo=$(foo) bar=$(bar) + @echo foo=$$foo bar=$$bar +', + '', "foo=f-ok bar=b-ok\nfoo= bar=\n"); + +# TEST 7: Test exporting multiple variables on the same line + +&run_make_test(' +A = a +B = b +C = c +D = d +E = e +F = f +G = g +H = h +I = i +J = j + +SOME = A B C + +export F G H I J + +export D E $(SOME) + +all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J +', + '', "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n"); + +# 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); + +&run_make_test(' +A = a +B = b +C = c +D = d +E = e +F = f +G = g +H = h +I = i +J = j + +SOME = A B C + +unexport F G H I J + +unexport D E $(SOME) + +all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J +', + '', "A= B= C= D= E= F= G= H= I= J=\n"); + +# TEST 9: Check setting a variable named "export" + +&run_make_test(' +export = 123 +export export +export export = 456 +a: ; @echo "\$$(export)=$(export) / \$$export=$$export" +', + '', "\$(export)=456 / \$export=456\n"); + +# TEST 9: Check "export" as a target + +&run_make_test(' +a: export +export: ; @echo "$@" +', + '', "export\n"); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/ifcond b/src/kmk/tests/scripts/features/ifcond new file mode 100644 index 0000000..b492e77 --- /dev/null +++ b/src/kmk/tests/scripts/features/ifcond @@ -0,0 +1,950 @@ +# $Id: ifcond 2413 2010-09-11 17:43:04Z bird $ -*-perl-*- +## @file +# if conditionals. +# + +# +# Copyright (c) 2008-2010 knut st. osmundsen +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS 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 kBuild. If not, see +# +# + +$description = "Tests the if conditionals"; + +$details = "..."; + +if ($is_kmk) { + + # TEST #0 - check that the feature is present. + # -------------------------------------------- + run_make_test(' +ifneq ($(if-expr 1+1,1,0),1) +$(error sub-test 0 failed) +endif +.PHONY: all +all: ; @: +', +'', +''); + + # TEST #1 - A more comprehensive, yet a bit large, test. + # ------------------------------------------------------ + run_make_test(' + +# +# Note! The testcase are ordered by ascending operator precedence +# with the exception of equal and not-equal because these +# are kind of useful for performing tests on non-logical ops. +# + +.PHONY: all +all: ; @: + +# +# Parenthesis +# +$(info unary operators: ( and )) +if (1) +else +$(error ) +endif + +if ((((1)))) +else +$(error ) +endif + + +# +# Equal and Not Equal w/ some fundamental bits thrown in. +# +$(info binary operators: == and !=) + +if 1 == 1 +else +$(error ) +endif + +if 2 == 3 +$(error ) +else +endif + +if 2 != 3 +else +$(error ) +endif + +if a != b +else +$(error ) +endif + +if asdf == asdf +else +$(error ) +endif + +if "asdf" == asdf +else +$(error ) +endif + +if \'asdf\' == asdf +else +$(error ) +endif + +if \'asdf\' == "asdf" +else +$(error ) +endif + +if \'asdf\' == \'asdf\' +else +$(error ) +endif + +if "asdf" == "asdf" +else +$(error ) +endif + +if 0x1 == 1 +else +$(error ) +endif + +if 0xfff == 4095 +else +$(error ) +endif + +if 0xfff == 4095 +else +$(error ) +endif + +if 0d10 == 10 +else +$(error ) +endif + +if 0d10 == 10 +else +$(error ) +endif + +if 0xa == 012 +else +$(error ) +endif + +if 0b1110 == 016 +else +$(error ) +endif + + +# +# Logical OR +# +$(info binary operator: ||) +if 1 +else +$(error busted) +endif + +if 1 || 1 +else +$(error ) +endif + +if 0 || 0 +$(error ) +else +endif + +if 1 || 0 +else +$(error ) +endif + +if 0 || 1 +else +$(error ) +endif + +if 0 || 0 || 0 || 0 || 0 || 0 || 0 +$(error ) +else +endif + +if 0 || 0 || 0 || 1 || 0 || 0 || 0 +else +$(error ) +endif + +if "asdf" || 0 +else +$(error ) +endif + +if 0 || "asdf" +else +$(error ) +endif + +if \'asdf\' || 0 +else +$(error ) +endif + +if "" || 0 +$(error ) +endif +if "" || 1 +else +$(error ) +endif +if \'\' || 0 +$(error ) +endif +if \'\' || 1 +else +$(error ) +endif + +if "" || \'\' +$(error ) +endif +if "1" || \'\' +else +$(error ) +endif +if "1" || \'1\' +else +$(error ) +endif +if "" || \'1\' +else +$(error ) +endif + + +# +# Logical AND +# +$(info binary operator: &&) +if 1 && 1 +else +$(error ) +endif +if 1 && 0 +$(error ) +endif +if 1234 && 0 +$(error ) +endif +if 123434 && 0 && 123435 && 1 +$(error ) +endif + +if "" && 1 +$(error ) +endif +if ("asdf" && 1) != 1 +$(error ) +endif +if "1" && \'asdf\' +else +$(error ) +endif +if "1" && \'asdf\' && 0 +$(error ) +endif + +if 0 || 1 && 0 +$(error ) +endif + + +# +# Bitwise OR +# +$(info binary operator: |) +if 1 | 0 +else +$(error ) +endif +if 1 | 1 +else +$(error ) +endif +if 11234 | 343423 +else +$(error ) +endif +if (1|2)!=3 +$(error ) +endif +if 1|2 != 3 +else +$(error ) +endif +if (1|2|4|8)!=0xf +$(error ) +endif + + +# +# Bitwise XOR +# +$(info binary operator: ^) +if 1 ^ 1 +$(error ) +endif + +if (2 ^ 1) != 3 +$(error ) +endif + +if 7 != (2 ^ 1 ^ 4) +$(error ) +endif + +if (2 ^ 1 | 2) != 3 +$(error ) +endif + + +# +# Bitwise AND +# +$(info binary operator: &) +if (4097 & 1) != 1 +$(error ) +endif +if (0xfff & 0x0f0) != 0xf0 +$(error ) +endif +if (0x1e3 & 0x100 | 3) != 0x103 +$(error ) +endif + + +# +# Greater than +# +$(info binary operator: >) +if 1 > 0 +else +$(error ) +endif + +if 1024 > 1023 +else +$(error ) +endif + +if 999 > 1023 +$(error ) +endif + +if (5 > 4 | 2) != 3 +$(error ) +endif + +if (1 & 8 > 4) != 1 +$(error ) +endif + +if (8 > 4 ^ 16) != 17 +$(error ) +endif + +if "b" > \'a\' +else +$(error ) +endif +if "abcdef" > \'ffdas\' +$(error ) +endif +if abcdef > ffdas +$(error ) +endif + + +# +# Greater or equal than +# +$(info binary operator: >=) +if 20 > 0 +else +$(error ) +endif + +if 20 >= 20 +else +$(error ) +endif + +if 19 >= 20 +$(error ) +endif + +if (1 & 8 >= 4) != 1 +$(error ) +endif + +if "x" >= \'x\' +else +$(error ) +endif +if "abdc" >= \'abcd\' +else +$(error ) +endif +if "ffdaaa" >= \'ffdasd\' +$(error ) +endif +if asdf >= asdf +else +$(error ) +endif + + +# +# Less than +# +if 1 < 1 +$(error ) +endif +if -123 < -134 +$(error ) +endif +if 123 <= 7777 +else +$(error ) +endif + +if "b" < \'a\' +$(error ) +endif +if b < a +$(error ) +endif +if \'foobar\' < \'a$\' +$(error ) +endif +if hhhh < ggggg +$(error ) +endif +if qwerty < qwerty0 +else +$(error ) +endif + + +# +# Less or equal than +# +$(info binary operator: >>) +if 1 <= 0 +$(error ) +endif +if 1 <= 1 +else +$(error ) +endif +if 123 <= 123 != 1 +$(error ) +endif +if 560 <= 456 +$(error ) +endif + +if "a" <= \'a\' +else +$(error ) +endif +if "abcdef" <= \'abcdef\' +else +$(error ) +endif +if q12345z6 <= q12345z +$(error ) +endif +if QWERTY <= ABCDE +$(error ) +endif + + +# +# Shift right +# +$(info binary operator: >>) +if 1 >> 0 != 1 +$(error ) +endif +if 1024 >> 2 != 256 +$(error ) +endif +if 102435 >> 4 > 1234 != 1 +$(error ) +endif + + +# +# Shift left +# +$(info binary operator: <<) +if 1 << 0 != 1 +$(error ) +endif +if 1 << 1 != 2 +$(error ) +endif +if 1 << 4 != 16 +$(error ) +endif +if 1 << 10 != 1024 +$(error ) +endif +if 34 << 10 != 0x8800 +$(error ) +endif +if 1099511627776 << 21 != 2305843009213693952 +$(error ) +endif +if 1 << 61 != 2305843009213693952 +$(error ) +endif + +if 2 << 60 > 123434323 != 1 +$(error ) +endif + + +# +# Subtraction +# +$(info binary operator: -) +if 1-1 != 0 +$(error ) +endif +if 1023-511 != 512 +$(error ) +endif +if 4 - 3 << 3 != 8 +$(error ) +endif + + +# +# Addition +# +$(info binary operator: +) +if 1+1 != 2 +$(error ) +endif +if 1234+1000 != 2234 +$(error ) +endif +if 2 + 2 << 4 != 64 +$(error ) +endif + + +# +# Modulus +# +$(info binary operator: %) +if 0%2 != 0 +$(error ) +endif +if 10%7 != 3 +$(error ) +endif +if 10 + 100%70 - 3 != 37 +$(error ) +endif + + +# +# Division +# +$(info binary operator: /) +if 0/1 != 0 +$(error ) +endif +if 1000/2 != 500 +$(error ) +endif +if 1000/2 + 4 != 504 +$(error ) +endif +if 5 + 1000/4 != 255 +$(error ) +endif + + +# +# Multiplication +# +$(info binary operator: *) +if 1*1 != 1 +$(error ) +endif +if 10*10 != 100 +$(error ) +endif +if 1024*64 != 65536 +$(error ) +endif +if 10*10 - 10 != 90 +$(error ) +endif +if 1000 - 10*10 != 900 +$(error ) +endif + + +# +# Logical NOT +# +$(info unary operator: !) +if !1 +$(error ) +endif + +if !42 == 0 +else +$(error ) +endif + +if !0 == 1 +else +$(error ) +endif + +if !!0 == 0 +else +$(error ) +endif + +if !0 * 123 != 123 +$(error ) +endif +if !!!0 * 512 != 512 +$(error ) +endif + + +# +# Bitwise NOT +# +$(info unary operator: ~) +if ~0xfff != 0xfffffffffffff000 +$(error ) +endif + + +# +# Pluss +# +$(info unary operator: +) +if +2 != 2 +$(error ) +endif +if 1++++++++++++2134 != 2135 +$(error ) +endif + + +# +# Minus (negation) +# +$(info unary operator: -) +if --2 != 2 +$(error ) +endif + +if 1 - -2 != 3 +$(error ) +endif + + +# +# target +# +trg_deps_only: foobar +trg_with_cmds: foobar + echo $@ + +$(info unary operator: target) # This flushes stuff in read.c + +if target trg_with_cmds +else +$(error target trg_with_cmds) +endif +if target(trg_deps_only) +$(error target trg_deps_only) +endif +if target ( foobar ) +$(error target foobar) +endif + + +# +# defined +# +$(info unary operator: defined) +var_defined := 1 +var_not_defined := + +if defined var_defined +else +$(error ) +endif +if defined(var_defined) +else +$(error ) +endif +if defined (var_defined) +else +$(error ) +endif +if !defined(var_defined) +$(error ) +endif +if defined (var_not_defined) +$(error ) +endif + + +# +# bool +# +$(info unary operator: bool) +if bool("Asdf") != 1 +$(error ) +endif +if bool("") != 0 +$(error ) +endif + + +# +# bool +# +$(info unary operator: num) +if num("1234") != 1235 - 1 +$(error ) +endif +if num(\'1234\') != 1233 + 1 +$(error ) +endif + + +# +# str +# +$(info unary operator: str) +if str(a < b) != 1 +$(error ) +endif +if str(a < b) != \'1\' +$(error ) +endif +if str( 1 ) != "1" +$(error ) +endif +if str( 1 ) != "1" +$(error ) +endif +if str( num(0x1000) ) != "4096" +$(error ) +endif +if str(0x1000) != 0x1000 +$(error ) +endif + + + +# +# Quick check of $(if-expr ) and $(expr ). +# +$(info $$(if-expr ,,)) +ifeq ($(if-expr 0 || 2,42,500),42) +else +$(error ) +endif +ifeq ($(if-expr 5+3 == 231,42,500),42) +$(error ) +endif + +$(info $$(expr )) +ifeq ($(expr 5+3),8) +else +$(error expr:$(expr 5+3) expected 8) +endif +ifeq ($(expr 25*25),625) +else +$(error expr:$(expr 25*25) expected 625) +endif +ifeq ($(expr 100/3),3) +$(error ) +endif +', +'', +'unary operators: ( and ) +binary operators: == and != +binary operator: || +binary operator: && +binary operator: | +binary operator: ^ +binary operator: & +binary operator: > +binary operator: >= +binary operator: >> +binary operator: >> +binary operator: << +binary operator: - +binary operator: + +binary operator: % +binary operator: / +binary operator: * +unary operator: ! +unary operator: ~ +unary operator: + +unary operator: - +unary operator: target +unary operator: defined +unary operator: bool +unary operator: num +unary operator: str +$(if-expr ,,) +$(expr ) +'); + +} + + + # TEST #2 - A bug. + # ------------------------------------------------------ + run_make_test(' +.PHONY: all +all: ; @: + +# +# Assert sanity first on simple strings. +# +if abcd != "abcd" +$(error ) +endif + +if \'abcd\' != abcd +$(error ) +endif + +if abcd != abcd +$(error ) +endif + + +# +# String by reference, start with a few simple cases. +# +STR1 = abcd + +if "$(STR1)" != "abcd" +$(error ) +endif + +if \'$(STR1)\' == "abcd" # not expanded. +$(error ) +endif + +if \'$(STR1)\' != \'$(STR1)\' +$(error ) +endif + +if "$(STR1)" != "$(STR1)" +$(error ) +endif + +# +# Now for the kmk 0.1.4 bug... +# +if $(STR1) != "$(STR1)" +$(error ) +endif + +if "$(STR1)" != $(STR1) +$(error ) +endif + +if $(STR1) != $(STR1) +$(error ) +endif + +# +# And some extra for good measure. +# +STR2 = STR +NUM1 = 1 + +if $($(STR2)$(NUM1)) != "abcd" +$(error ) +endif + +if "abcd" != $($(STR2)$(NUM1)) +$(error ) +endif + +if "abcd" != $(${STR2}$(NUM1)) +$(error ) +endif + +if "abcd" != ${$(STR2)$(NUM1)} +$(error ) +endif + +if "abcd" != ${${STR2}${NUM1}} +$(error ) +endif + +if ${${STR2}${NUM1}} != \'abcd\' +$(error ) +endif + +if "${${STR2}${NUM1}}" != \'abcd\' +$(error ) +endif + + +', +'', +''); + + + +# Indicate that we're done. +1; + + diff --git a/src/kmk/tests/scripts/features/include b/src/kmk/tests/scripts/features/include new file mode 100644 index 0000000..f78563f --- /dev/null +++ b/src/kmk/tests/scripts/features/include @@ -0,0 +1,243 @@ +# -*-mode: perl; rm-trailing-spaces: nil-*- + +$description = "Test various forms of the GNU make 'include' command."; + +$details = "\ +Test include, -include, sinclude and various regressions involving them. +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; + +open(MAKEFILE,"> $makefile"); + +# The contents of the Makefile ... + +print 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)); + +&run_make_with_options($makefile, "ANOTHER", &get_logfile); +$answer = "This is another included makefile\n"; +&compare_output($answer, &get_logfile(1)); + +$makefile = undef; + +# 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 +# the -include suppressed it during the makefile read phase, we should +# see one during the makefile run phase). + +run_make_test + (' +-include foo.mk +error: foo.mk ; @echo $@ +', + '', + "#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'. Stop.\n", + 512 + ); + +# 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. + +run_make_test + (' +bar.mk: foo := baz +-include bar.mk +hello: ; @echo hello +', + '', + "hello\n" + ); + + +# Test inheritance of dontcare flag when rebuilding makefiles. +# +run_make_test(' +.PHONY: all +all: ; @: + +-include foo + +foo: bar; @: +', '', ''); + + +# Make sure that we don't die when the command fails but we dontcare. +# (Savannah bug #13216). +# +run_make_test(' +.PHONY: all +all:; @: + +-include foo + +foo: bar; @: + +bar:; @exit 1 +', '', ''); + +# Check include, sinclude, -include with no filenames. +# (Savannah bug #1761). + +run_make_test(' +.PHONY: all +all:; @: +include +-include +sinclude', '', ''); + + +# Test that the diagnostics is issued even if the target has been +# tried before with the dontcare flag (direct dependency case). +# +run_make_test(' +-include foo + +all: bar + +foo: baz +bar: baz +', +'', +"#MAKE#: *** No rule to make target 'baz', needed by 'bar'. Stop.\n", +512); + +# Test that the diagnostics is issued even if the target has been +# tried before with the dontcare flag (indirect dependency case). +# +run_make_test(' +-include foo + +all: bar + +foo: baz +bar: baz +baz: end +', +'', +"#MAKE#: *** No rule to make target 'end', needed by 'baz'. Stop.\n", +512); + +# Test that the diagnostics is issued even if the target has been +# tried before with the dontcare flag (include/-include case). +# +run_make_test(' +include bar +-include foo + +all: + +foo: baz +bar: baz +baz: end +', +'', +"#MAKEFILE#:2: bar: No such file or directory +#MAKE#: *** No rule to make target 'end', needed by 'baz'. Stop.\n", +512); + +# Test include of make-able file doesn't show an error (Savannah #102) +run_make_test(q! +.PHONY: default +default:; @echo DONE + +inc1:; echo > $@ +include inc1 +include inc2 +inc2:; echo > $@ +!, + '', "echo > inc2\necho > inc1\nDONE\n"); + +rmfiles('inc1', 'inc2'); + +# Test include of non-make-able file does show an error (Savannah #102) +run_make_test(q! +.PHONY: default +default:; @echo DONE + +inc1:; echo > $@ +include inc1 +include inc2 +!, + '', "#MAKEFILE#:7: inc2: No such file or directory\n#MAKE#: *** No rule to make target 'inc2'. Stop.\n", 512); + +rmfiles('inc1'); + +# Include same file multiple times + +run_make_test(q! +default:; @echo DEFAULT +include inc1 +inc1:; echo > $@ +include inc1 +!, + '', "echo > inc1\nDEFAULT\n"); + +rmfiles('inc1'); + +# Included file has a prerequisite that fails to build + +run_make_test(q! +default:; @echo DEFAULT +include inc1 +inc1: foo; echo > $@ +foo:; exit 1 +!, + '', "exit 1\n#MAKEFILE#:3: inc1: No such file or directory\n#MAKE#: *** [#MAKEFILE#:5: foo] Error 1\n", 512); + +rmfiles('inc1'); + +# Included file has a prerequisite we don't know how to build + +run_make_test(q! +default:; @echo DEFAULT +include inc1 +inc1: foo; echo > $@ +!, + '', "#MAKEFILE#:3: inc1: No such file or directory\n#MAKE#: *** No rule to make target 'foo', needed by 'inc1'. Stop.\n", 512); + +rmfiles('inc1'); + +# include a directory + +if ($all_tests) { + # Test that include of a rebuild-able file doesn't show a warning + # Savannah bug #102 + run_make_test(q! +include foo +foo: ; @echo foo = bar > $@ +!, + '', "#MAKE#: 'foo' is up to date.\n"); + rmfiles('foo'); +} + +1; diff --git a/src/kmk/tests/scripts/features/jobserver b/src/kmk/tests/scripts/features/jobserver new file mode 100644 index 0000000..7da4a65 --- /dev/null +++ b/src/kmk/tests/scripts/features/jobserver @@ -0,0 +1,107 @@ +# -*-perl-*- + +$description = "Test jobserver."; + +$details = "These tests are ones that specifically are different when the +jobserver feature is available. Most -j tests are the same whether or not +jobserver is available, and those appear in the 'parallelism' test suite."; + +exists $FEATURES{'jobserver'} or return -1; + +if (!$parallel_jobs) { + return -1; +} + +# Shorthand +my $np = '--no-print-directory'; + +# Simple test of MAKEFLAGS settings +run_make_test(q! +SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=,$(MAKEFLAGS)) +recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all +all:;@echo $@: "/$(SHOW)/" +!, + "-j2 $np", "recurse: /-j2 --jobserver-auth= $np/\nall: /-j2 --jobserver-auth= $np/\n"); + +# Setting parallelism with the environment +# Command line should take precedence over the environment +$extraENV{MAKEFLAGS} = "-j2 $np"; +run_make_test(q! +SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=,$(MAKEFLAGS)) +recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all +all:;@echo $@: "/$(SHOW)/" +!, + '', "recurse: /-j2 --jobserver-auth= $np/\nall: /-j2 --jobserver-auth= $np/\n"); +delete $extraENV{MAKEFLAGS}; + +# Test override of -jN +$extraENV{MAKEFLAGS} = "-j9 $np"; +run_make_test(q! +SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=,$(MAKEFLAGS)) +recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -j3 -f #MAKEFILE# recurse2 +recurse2: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all +all:;@echo $@: "/$(SHOW)/" +!, + "-j2 $np", "recurse: /-j2 --jobserver-auth= $np/\n#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nrecurse2: /-j3 --jobserver-auth= $np/\nall: /-j3 --jobserver-auth= $np/\n"); +delete $extraENV{MAKEFLAGS}; + +# Test override of -jN with -j +run_make_test(q! +SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=,$(MAKEFLAGS)) +recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -j -f #MAKEFILE# recurse2 +recurse2: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all +all:;@echo $@: "/$(SHOW)/" +!, + "-j2 $np", "recurse: /-j2 --jobserver-auth= $np/\n#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nrecurse2: /-j $np/\nall: /-j $np/\n"); + +# Don't put --jobserver-auth into a re-exec'd MAKEFLAGS. +# We can't test this directly because there's no way a makefile can +# show the value of MAKEFLAGS we were re-exec'd with. We can intuit it +# by looking for "disabling jobserver mode" warnings; we should only +# get one from the original invocation and none from the re-exec. +# See Savannah bug #18124 + +unlink('inc.mk'); + +run_make_test(q! +-include inc.mk +recur: +# @echo 'MAKEFLAGS = $(MAKEFLAGS)' + @rm -f inc.mk + @$(MAKE) -j2 -f #MAKEFILE# all +all: +# @echo 'MAKEFLAGS = $(MAKEFLAGS)' + @echo $@ +inc.mk: +# @echo 'MAKEFLAGS = $(MAKEFLAGS)' + @echo 'FOO = bar' > $@ +!, + "$np -j2", "#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nall\n"); + +unlink('inc.mk'); + +# Test recursion when make doesn't think it exists. +# See Savannah bug #39934 +# Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474 + +open(MAKEFILE,"> Makefile2"); +print MAKEFILE ' +vpath %.c ../ +foo: +'; +close(MAKEFILE); + +run_make_test(q! +default: ; @ #MAKEPATH# -f Makefile2 +!, + "-j2 $np", +"#MAKE#[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule. +#MAKE#[1]: Nothing to be done for 'foo'."); + +rmfiles('Makefile2'); + +1; + +### Local Variables: +### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) +### End: diff --git a/src/kmk/tests/scripts/features/load b/src/kmk/tests/scripts/features/load new file mode 100644 index 0000000..2e9318d --- /dev/null +++ b/src/kmk/tests/scripts/features/load @@ -0,0 +1,110 @@ +# -*-perl-*- +$description = "Test the load operator."; + +$details = "Test dynamic loading of modules."; + +# Don't do anything if this system doesn't support "load" +exists $FEATURES{load} or return -1; + +# First build a shared object +# Provide both a default and non-default load symbol + +unlink(qw(testload.c testload.so)); + +open(my $F, '> testload.c') or die "open: testload.c: $!\n"; +print $F <<'EOF' ; +#include +#include + +#include "gnumake.h" + +int plugin_is_GPL_compatible; + +int +testload_gmk_setup (gmk_floc *pos) +{ + (void)pos; + gmk_eval ("TESTLOAD = implicit", 0); + return 1; +} + +int +explicit_setup (gmk_floc *pos) +{ + (void)pos; + gmk_eval ("TESTLOAD = explicit", 0); + return 1; +} +EOF +close($F) or die "close: testload.c: $!\n"; + +# Make sure we can compile +# CONFIG_FLAGS are loaded from config-flags.pm and set by configure + +my $sobuild = "$CONFIG_FLAGS{CC} ".($srcdir? "-I$srcdir":'')." $CONFIG_FLAGS{CPPFLAGS} $CONFIG_FLAGS{CFLAGS} -shared -fPIC $CONFIG_FLAGS{LDFLAGS} -o testload.so testload.c"; + +my $clog = `$sobuild 2>&1`; +if ($? != 0) { + $verbose and print "Failed to build testload.so:\n$sobuild\n$_"; + return -1; +} + +# TEST 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"); + +# TEST 2 +# Load using an explicit function +run_make_test(q! +PRE := $(.LOADED) +load ./testload.so(explicit_setup) +POST := $(.LOADED) +all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) +!, + '', "pre= post=testload.so explicit\n"); + +# TEST 4 +# Check multiple loads +run_make_test(q! +PRE := $(.LOADED) +load ./testload.so +load testload.so(explicit_setup) +POST := $(.LOADED) +all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) +!, + '', "pre= post=testload.so implicit\n"); + +# TEST 5 +# Check auto-rebuild of loaded file that's out of date +utouch(-10, 'testload.so'); +touch('testload.c'); + +run_make_test(q! +PRE := $(.LOADED) +load ./testload.so +POST := $(.LOADED) +all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) +testload.so: testload.c ; @echo "rebuilding $@"; !.$sobuild, + '', "rebuilding testload.so\npre= post=testload.so implicit\n"); + +# TEST 5 +# Check auto-rebuild of loaded file when it doesn't exist +unlink('testload.so'); + +run_make_test(q! +PRE := $(.LOADED) +-load ./testload.so(explicit_setup) +POST := $(.LOADED) +all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) +%.so: %.c ; @echo "rebuilding $@"; !.$sobuild, + '', "rebuilding testload.so\npre= post=testload.so explicit\n"); + +unlink(qw(testload.c testload.so)) unless $keep; + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/loadapi b/src/kmk/tests/scripts/features/loadapi new file mode 100644 index 0000000..8c824c0 --- /dev/null +++ b/src/kmk/tests/scripts/features/loadapi @@ -0,0 +1,116 @@ +# -*-perl-*- +$description = "Test the shared object load API."; + +$details = "Verify the different aspects of the shared object API."; + +# Don't do anything if this system doesn't support "load" +exists $FEATURES{load} or return -1; + +# First build a shared object +# Provide both a default and non-default load symbol + +unlink(qw(testapi.c testapi.so)); + +open(my $F, '> testapi.c') or die "open: testapi.c: $!\n"; +print $F <<'EOF' ; +#include +#include + +#include "gnumake.h" + +int plugin_is_GPL_compatible; + +static char * +test_eval (const char *buf) +{ + gmk_eval (buf, 0); + return NULL; +} + +static char * +test_expand (const char *val) +{ + return gmk_expand (val); +} + +static char * +test_noexpand (const char *val) +{ + char *str = gmk_alloc (strlen (val) + 1); + strcpy (str, val); + return str; +} + +static char * +func_test (const char *funcname, unsigned int argc, char **argv) +{ + char *mem; + + if (strcmp (funcname, "test-expand") == 0) + return test_expand (argv[0]); + + if (strcmp (funcname, "test-eval") == 0) + return test_eval (argv[0]); + + if (strcmp (funcname, "test-noexpand") == 0) + return test_noexpand (argv[0]); + + mem = gmk_alloc (sizeof ("unknown")); + strcpy (mem, "unknown"); + return mem; +} + +int +testapi_gmk_setup () +{ + gmk_add_function ("test-expand", func_test, 1, 1, GMK_FUNC_DEFAULT); + gmk_add_function ("test-noexpand", func_test, 1, 1, GMK_FUNC_NOEXPAND); + gmk_add_function ("test-eval", func_test, 1, 1, GMK_FUNC_DEFAULT); + gmk_add_function ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.", func_test, 0, 0, 0); + return 1; +} +EOF +close($F) or die "close: testapi.c: $!\n"; + +my $sobuild = "$CONFIG_FLAGS{CC} ".($srcdir? "-I$srcdir":'')." $CONFIG_FLAGS{CPPFLAGS} $CONFIG_FLAGS{CFLAGS} -shared -fPIC $CONFIG_FLAGS{LDFLAGS} -o testapi.so testapi.c"; + +my $clog = `$sobuild 2>&1`; +if ($? != 0) { + $verbose and print "Failed to build testapi.so:\n$sobuild\n$_"; + return -1; +} + +# TEST 1 +# Check the gmk_expand() function +run_make_test(q! +EXPAND = expansion +all: ; @echo $(test-expand $$(EXPAND)) +load testapi.so +!, + '', "expansion\n"); + +# TEST 2 +# Check the eval operation. Prove that the argument is expanded only once +run_make_test(q! +load testapi.so +TEST = bye +ASSIGN = VAR = $(TEST) $(shell echo there) +$(test-eval $(value ASSIGN)) +TEST = hi +all:;@echo '$(VAR)' +!, + '', "hi there\n"); + +# TEST 2 +# Check the no-expand capability +run_make_test(q! +load testapi.so +TEST = hi +all:;@echo '$(test-noexpand $(TEST))' +!, + '', "\$(TEST)\n"); + +unlink(qw(testapi.c testapi.so)) unless $keep; + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/mult_rules b/src/kmk/tests/scripts/features/mult_rules new file mode 100644 index 0000000..e706e17 --- /dev/null +++ b/src/kmk/tests/scripts/features/mult_rules @@ -0,0 +1,78 @@ +$description = "\ +The following test creates a makefile to test the presence +of multiple rules for one target. One file can be the +target of several rules if at most one rule has commands; +the other rules can only have dependencies."; + +$details = "\ +The makefile created in this test contains two hardcoded rules +for foo.o and bar.o. It then gives another multiple target rule +with the same names as above but adding more dependencies. +Additionally, another variable extradeps is listed as a +dependency but is defined to be null. It can however be defined +on the make command line as extradeps=extra.h which adds yet +another dependency to the targets."; + +open(MAKEFILE,"> $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE < $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE "bigoutput littleoutput: test.h\n"; +print MAKEFILE "\t\@echo I am \$(subst output,,\$@)\n"; + +# END of Contents of MAKEFILE + +close(MAKEFILE); + +&touch("test.h"); + +&run_make_with_options($makefile,"bigoutput",&get_logfile); + + +# Create the answer to what should be produced by this Makefile +$answer = "I am big\n"; + +&compare_output($answer,&get_logfile(1)); + +&run_make_with_options($makefile,"littleoutput",&get_logfile); +$answer = "I am little\n"; +&compare_output($answer,&get_logfile(1)); + +unlink "test.h"; + +1; + + + + + + diff --git a/src/kmk/tests/scripts/features/order_only b/src/kmk/tests/scripts/features/order_only new file mode 100644 index 0000000..4ebdc2b --- /dev/null +++ b/src/kmk/tests/scripts/features/order_only @@ -0,0 +1,118 @@ +# -*-perl-*- +$description = "Test order-only prerequisites."; + +$details = "\ +Create makefiles with various combinations of normal and order-only +prerequisites and ensure they behave properly. Test the \$| variable."; + +# TEST #0 -- Basics + +run_make_test(' +%r: | baz ; @echo $< $^ $| +bar: foo +foo:;@: +baz:;@:', + '', "foo foo baz\n"); + +# TEST #1 -- First try: the order-only prereqs need to be built. + +run_make_test(q! +foo: bar | baz + @echo '$$^ = $^' + @echo '$$| = $|' + touch $@ + +.PHONY: baz + +bar baz: + touch $@!, + '', "touch bar\ntouch baz\n\$^ = bar\n\$| = baz\ntouch foo\n"); + + +# TEST #2 -- now we do it again: baz is PHONY but foo should _NOT_ be updated + +run_make_test(undef, '', "touch baz\n"); + +unlink(qw(foo bar baz)); + +# TEST #3 -- Make sure the order-only prereq was promoted to normal. + +run_make_test(q! +foo: bar | baz + @echo '$$^ = $^' + @echo '$$| = $|' + touch $@ + +foo: baz + +.PHONY: baz + +bar baz: + touch $@!, + '', "touch bar\ntouch baz\n\$^ = bar baz\n\$| = \ntouch foo\n"); + + +# TEST #4 -- now we do it again + +run_make_test(undef, '', "touch baz\n\$^ = bar baz\n\$| = \ntouch foo\n"); + +unlink(qw(foo bar baz)); + +# Test empty normal prereqs + +# TEST #5 -- make sure the parser was correct. + +run_make_test(q! +foo:| baz + @echo '$$^ = $^' + @echo '$$| = $|' + touch $@ + +.PHONY: baz + +baz: + touch $@!, + '', "touch baz\n\$^ = \n\$| = baz\ntouch foo\n"); + +# TEST #6 -- now we do it again: this time foo won't be built + +run_make_test(undef, '', "touch baz\n"); + +unlink(qw(foo baz)); + +# Test order-only in pattern rules + +# TEST #7 -- make sure the parser was correct. + +run_make_test(q! +%.w : %.x | baz + @echo '$$^ = $^' + @echo '$$| = $|' + touch $@ + +all: foo.w + +.PHONY: baz +foo.x baz: + touch $@!, + '', + "touch foo.x\ntouch baz\n\$^ = foo.x\n\$| = baz\ntouch foo.w\n"); + +# TEST #8 -- now we do it again: this time foo.w won't be built + +run_make_test(undef, '', "touch baz\n"); + +unlink(qw(foo.w foo.x baz)); + +# TEST #9 -- make sure that $< is set correctly in the face of order-only +# prerequisites in pattern rules. + +run_make_test(' +%r: | baz ; @echo $< $^ $| +bar: foo +foo:;@: +baz:;@:', + '', "foo foo baz\n"); + + +1; diff --git a/src/kmk/tests/scripts/features/output-sync b/src/kmk/tests/scripts/features/output-sync new file mode 100644 index 0000000..7237e65 --- /dev/null +++ b/src/kmk/tests/scripts/features/output-sync @@ -0,0 +1,349 @@ +# -*-perl-*- + +$description = "Test --output-sync (-O) option."; + +$details = "Test the synchronization of output from parallel jobs."; + +# If we don't have output sync support, never mind. +exists $FEATURES{'output-sync'} or return -1; + +# Output sync can't be tested without parallelization +$parallel_jobs or return -1; + + +if ($vos) { + $sleep_command = "sleep -seconds"; +} +else { + $sleep_command = "sleep"; +} + +# The following subdirectories with Makefiles are used in several +# of the following tests. The model is: +# foo/Makefile - has a "foo" target that waits for the bar target +# bar/Makefile - has a "bar" target that runs immediately +# - has a "baz" target that waits for the foo target +# +# So, you start the two sub-makes in parallel and first the "bar" target is +# built, followed by "foo", followed by "baz". The trick is that first each +# target prints a "start" statement, then waits (if appropriate), then prints +# an end statement. Thus we can tell if the -O flag is working, since +# otherwise these statements would be mixed together. + +@syncfiles = (); + +sub output_sync_clean { + rmfiles('foo/Makefile', 'bar/Makefile', @syncfiles); + rmdir('foo'); + rmdir('bar'); +} + +# We synchronize the different jobs by having them wait for a sentinel file to +# be created, instead of relying on a certain amount of time passing. +# Unfortunately in this test we have to sleep after we see the sync file, +# since we also want to make the obtaining of the write synchronization lock +# reliable. If things are too fast, then sometimes a different job will steal +# the output sync lock and the output is mis-ordered from what we expect. +sub output_sync_wait { + return "while [ ! -f ../mksync.$_[0] ]; do :; done; rm -f ../mksync.$_[0].wait; $sleep_command 1"; +} +sub output_sync_set { + return "date > ../mksync.$_[0]"; +} + +@syncfiles = qw(mksync.foo mksync.foo_start mksync.bar mksync.bar_start); + +$tmout = 30; + +output_sync_clean(); +mkdir('foo', 0777); +mkdir('bar', 0777); + +$set_foo = output_sync_set('foo'); +$set_bar = output_sync_set('bar'); +$set_foo_start = output_sync_set('foo_start'); +$set_bar_start = output_sync_set('bar_start'); + +$wait_foo = output_sync_wait('foo'); +$wait_bar = output_sync_wait('bar'); +$wait_foo_start = output_sync_set('foo_start'); +$wait_bar_start = output_sync_set('bar_start'); + +open(MAKEFILE,"> foo/Makefile"); +print MAKEFILE < bar/Makefile"); +print MAKEFILE <&2) +!, + '-w -Oline', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n"); + +# Ensure that output generated while parsing makefiles is synced +# when appropriate. +run_make_test(q! +$(shell echo foo 1>&2) +all: ; echo bar +!, + '-s -w -Otarget', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n#MAKE#: Entering directory '#PWD#'\nbar\n#MAKE#: Leaving directory '#PWD#'\n"); + +# Test recursion +$m1 = get_tmpfile(); +$m2 = get_tmpfile(); + +open(M1, "> $m1"); +print M1 <<'EOF'; +$(shell echo d1 stderr 1>&2) +$(info d1 stdout) +all:; @: +EOF +close(M1); + +open(M2, "> $m2"); +print M2 <<'EOF'; +$(shell echo d2 stderr 1>&2) +$(info d2 stdout) +all:; @: +# Force an ordering on the output +$(shell sleep 1) +EOF +close(M2); + +run_make_test(qq! +all: t1 t2 +t1: ; \@\$(MAKE) -f $m1 +t2: ; \@\$(MAKE) -f $m2 +!, + "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#[1]: Entering directory '#PWD#'\nd2 stderr\nd2 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n"); + +rmfiles($m1, $m2); + +# Ensure that output generated while parsing makefiles is synced +# when appropriate. +$m1 = get_tmpfile(); + +open(M1, "> $m1"); +print M1 <<'EOF'; +$(shell echo d1 stderr 1>&2) +$(info d1 stdout) +$(error d1 failed) +all:; @: +EOF +close(M1); + +run_make_test(qq! +all: t1 +t1: ; -\@\$(MAKE) -f $m1 +!, + "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n$m1:3: *** d1 failed. Stop.\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#: [#MAKEFILE#:3: t1] Error 2 (ignored)\n"); + +rmfiles($m1); + +# Test $(error ...) functions in recipes + +run_make_test(q! +foo: $(OBJS) ; echo $(or $(filter %.o,$^),$(error fail)) +!, + '-O', "#MAKEFILE#:2: *** fail. Stop.\n", 512); + +# SV 47365: Make sure exec failure error messages are shown +# Is "127" not always the same everywhere? We may have to detect it? + +run_make_test(q! +all:: ; @./foo bar baz +!, + '-O', "#MAKE#: ./foo: Command not found\n#MAKE#: *** [#MAKEFILE#:2: all] Error 127\n", 512); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/override b/src/kmk/tests/scripts/features/override new file mode 100644 index 0000000..fff6c4e --- /dev/null +++ b/src/kmk/tests/scripts/features/override @@ -0,0 +1,45 @@ +# -*-perl-*- + +$description = "Test the override directive on variable assignments."; + +$details = ""; + +# TEST 0: Basic override + +run_make_test(' +X = start +override recur = $(X) +override simple := $(X) +X = end +all: ; @echo "$(recur) $(simple)" +', + 'recur=I simple=J', "end start\n"); + +# TEST 1: Override with append + +run_make_test(' +X += X1 +override X += X2 +override Y += Y1 +Y += Y2 +all: ; @echo "$(X) $(Y)" +', + '', "X1 X2 Y1\n"); + +# TEST 2: Override with append to the command line + +run_make_test(undef, 'X=C Y=C', "C X2 C Y1\n"); + +# Test override of define/endef + +run_make_test(' +override define foo +@echo First comes the definition. +@echo Then comes the override. +endef +all: ; $(foo) +', + 'foo=Hello', "First comes the definition.\nThen comes the override.\n"); + + +1; diff --git a/src/kmk/tests/scripts/features/parallelism b/src/kmk/tests/scripts/features/parallelism new file mode 100644 index 0000000..ee3846d --- /dev/null +++ b/src/kmk/tests/scripts/features/parallelism @@ -0,0 +1,231 @@ +# -*-perl-*- + +$description = "Test parallelism (-j) option."; + + +$details = "This test creates a makefile with two double-colon default +rules. The first rule has a series of sleep and echo commands +intended to run in series. The second and third have just an +echo statement. When make is called in this test, it is given +the -j option with a value of 4. This tells make that it may +start up to four jobs simultaneously. In this case, since the +first command is a sleep command, the output of the second +and third commands will appear before the first if indeed +make is running all of these commands in parallel."; + +if (!$parallel_jobs) { + return -1; +} + +if ($vos) { + $sleep_command = "sleep -seconds"; +} +else { + $sleep_command = "sleep"; +} + + +run_make_test(" +all : def_1 def_2 def_3 +def_1 : ; \@echo ONE; $sleep_command 3 ; echo TWO +def_2 : ; \@$sleep_command 2 ; echo THREE +def_3 : ; \@$sleep_command 1 ; echo FOUR", + '-j4', "ONE\nFOUR\nTHREE\nTWO"); + +# 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; \@echo success +-include 1.inc 2.inc +1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@ +2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@", + "-j4", + "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n", 0, 7); + +rmfiles(qw(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; \@echo success + +INC = no +ifeq (\$(INC),yes) +-include 1.inc 2.inc +endif + +1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@ +2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@", + "-j4", + "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n", 0, 7); + +rmfiles(qw(1.inc 2.inc)); + +# Grant Taylor reports a problem where tokens can be lost (not written back +# to the pipe when they should be): this happened when there is a $(shell ...) +# 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)) +first.CMD = echo hi +second.CMD = $sleep_command 4; echo hi + +.PHONY: all first second +all: first second + +first second: ; \@echo \$\@; $sleep_command 1; echo \$\@", + '-j2', "first\nfirst\nsecond\nsecond", 0, 7); + +# Michael Matz 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(" +.PHONY: all fail.1 fail.2 fail.3 ok +all: fail.1 ok fail.2 fail.3 + +fail.1 fail.2 fail.3: + \@$sleep_command \$(patsubst fail.%,%,\$\@) + \@echo Fail + \@exit 1 + +ok: + \@$sleep_command 4 + \@echo Ok done", + '-rR -j5', (!$is_kmk) ? "Fail +#MAKE#: *** [#MAKEFILE#:8: fail.1] Error 1 +#MAKE#: *** Waiting for unfinished jobs.... +Fail +#MAKE#: *** [#MAKEFILE#:8: fail.2] Error 1 +Fail +#MAKE#: *** [#MAKEFILE#:8: fail.3] Error 1 +Ok done" : 'Fail +#MAKE#: *** [fail.1] Error 1 +The failing command: +@exit 1 +#MAKE#: *** Waiting for unfinished jobs.... +Fail +#MAKE#: *** [fail.2] Error 1 +The failing command: +@exit 1 +Fail +#MAKE#: *** [fail.3] Error 1 +The failing command: +@exit 1 +Ok done +#MAKE#: *** Exiting with status 2', + 512); + + +# Test for Savannah bug #15641. +# +run_make_test(' +.PHONY: all +all:; @: + +-include foo.d + +foo.d: comp + @echo building $@ + +comp: mod_a.o mod_b.o; @: + +mod_a.o mod_b.o: + @exit 1 +', '-j2', ''); + + +# TEST #9 -- Savannah bugs 3330 and 15919 +# In earlier versions of make this will either give the wrong answer, or hang. + +utouch(-10, 'target'); +run_make_test('target: intermed ; touch $@ + +.INTERMEDIATE: intermed +intermed: | phony ; touch $@ + +.PHONY: phony +phony: ; : phony', '-rR -j', ': phony'); +rmfiles('target'); + +# TEST #11: Make sure -jN from MAKEFLAGS is processed even when we re-exec +# See Savannah bug #33873 + +$extraENV{MAKEFLAGS} = '-j4'; + +run_make_test(q! +things = thing1 thing2 +all: $(things) +thing1:; @sleep 1; echo '$@ start'; sleep 2; echo '$@ end' +thing2:; @echo '$@ start'; sleep 2; echo '$@ end' +-include inc.mk +inc.mk: ; @touch $@ +!, + '', "thing2 start\nthing1 start\nthing2 end\nthing1 end\n"); + +delete $extraENV{MAKEFLAGS}; +rmfiles('inc.mk'); + +# Ensure intermediate/secondary files are not pruned incorrectly. +# See Savannah bug #30653 + +utouch(-15, 'file2'); +utouch(-10, 'file4'); +utouch(-5, 'file1'); + +run_make_test(q! +.INTERMEDIATE: file3 +file4: file3 ; @mv -f $< $@ +file3: file2 ; touch $@ +file2: file1 ; @touch $@ +!, + '--no-print-directory -j2', "touch file3"); + +rmfiles('file1', 'file2', 'file3', 'file4'); + +# Make sure that all jobserver FDs are closed if we need to re-exec the +# master copy. +# +# First, find the "default" file descriptors we normally use +# Then make sure they're still used. +# +# Right now we don't have a way to run a makefile and capture the output +# without checking it, so we can't really write this test. + +# run_make_test(' +# submake: ; @$(MAKE) --no-print-directory -f #MAKEFILE# fdprint 5>output + +# dependfile: ; @echo FOO=bar > $@ + +# INCL := true + +# FOO=foo +# ifeq ($(INCL),true) +# -include dependfile +# endif + +# fdprint: ; @echo $(filter --jobserver%,$(MAKEFLAGS)) + +# recurse: ; @$(MAKE) --no-print-directory -f #MAKEFILE# submake INCL=true', +# '-j2 INCL=false fdprint', +# 'bar'); + +# rmfiles(qw(dependfile output)); + + +# # Do it again, this time where the include is done by the non-master make. +# run_make_test(undef, '-j2 recurse INCL=false', 'bar'); + +# rmfiles(qw(dependfile output)); + +1; + +### Local Variables: +### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) +### End: diff --git a/src/kmk/tests/scripts/features/patspecific_vars b/src/kmk/tests/scripts/features/patspecific_vars new file mode 100644 index 0000000..bbeda64 --- /dev/null +++ b/src/kmk/tests/scripts/features/patspecific_vars @@ -0,0 +1,148 @@ +# -*-perl-*- +$description = "Test pattern-specific variable settings."; + +$details = "\ +Create a makefile containing various flavors of pattern-specific variable +settings, override and non-override, and using various variable expansion +rules, semicolon interference, etc."; + +open(MAKEFILE,"> $makefile"); + +print MAKEFILE <<'EOF'; +all: one.x two.x three.x +FOO = foo +BAR = bar +BAZ = baz +one.x: override FOO = one +%.x: BAR = two +t%.x: BAR = four +thr% : override BAZ = three +one.x two.x three.x: ; @echo $@: $(FOO) $(BAR) $(BAZ) +four.x: baz ; @echo $@: $(FOO) $(BAR) $(BAZ) +baz: ; @echo $@: $(FOO) $(BAR) $(BAZ) + +# test matching multiple patterns +a%: AAA = aaa +%b: BBB = ccc +a%: BBB += ddd +%b: AAA ?= xxx +%b: AAA += bbb +.PHONY: ab +ab: ; @echo $(AAA); echo $(BBB) +EOF + +close(MAKEFILE); + + +# TEST #1 -- basics + +&run_make_with_options($makefile, "-j1", &get_logfile); +$answer = "one.x: one two baz\ntwo.x: foo four baz\nthree.x: foo four three\n"; +&compare_output($answer,&get_logfile(1)); + + +# TEST #2 -- try the override feature + +&run_make_with_options($makefile, "-j1 BAZ=five", &get_logfile); +$answer = "one.x: one two five\ntwo.x: foo four five\nthree.x: foo four three\n"; +&compare_output($answer,&get_logfile(1)); + + +# TEST #3 -- make sure patterns are inherited properly + +&run_make_with_options($makefile, "-j1 four.x", &get_logfile); +$answer = "baz: foo two baz\nfour.x: foo two baz\n"; +&compare_output($answer,&get_logfile(1)); + + +# TEST #4 -- test multiple patterns matching the same target + +&run_make_with_options($makefile, "-j1 ab", &get_logfile); +$answer = "aaa bbb\nccc ddd\n"; +&compare_output($answer,&get_logfile(1)); + +# TEST #5 -- test pattern-specific exported variables +# +run_make_test(' +/%: export foo := foo + +/bar: + @echo $(foo) $$foo +', '-j1', 'foo foo'); + + +# TEST #6 -- test expansion of pattern-specific simple variables +# +run_make_test(' +.PHONY: all + +all: inherit := good $$t +all: bar baz + +b%: pattern := good $$t + +global := original $$t + + +# normal target +# +ifdef rec +bar: a = global: $(global) pattern: $(pattern) inherit: $(inherit) +else +bar: a := global: $(global) pattern: $(pattern) inherit: $(inherit) +endif + +bar: ; @echo \'normal: $a;\' + + +# pattern target +# +ifdef rec +%z: a = global: $(global) pattern: $(pattern) inherit: $(inherit) +else +%z: a := global: $(global) pattern: $(pattern) inherit: $(inherit) +endif + +%z: ; @echo \'pattern: $a;\' + + +global := new $$t +', +'-j1', +'normal: global: original $t pattern: inherit: ; +pattern: global: original $t pattern: inherit: ;'); + + +# TEST #7 -- test expansion of pattern-specific recursive variables +# +run_make_test(undef, # reuse previous makefile +'-j1 rec=1', +'normal: global: new $t pattern: good $t inherit: good $t; +pattern: global: new $t pattern: good $t inherit: good $t;'); + +# TEST #8: override in pattern-specific variables + +run_make_test(' +a%: override FOO += f1 +a%: FOO += f2 +ab: ; @echo "$(FOO)" +', + '', "f1\n"); + +run_make_test(undef, 'FOO=C', "C f1\n"); + +# TEST #9: Test shortest stem selection in pattern-specific variables. + +run_make_test(' +%-mt.x: x := two +%.x: x := one + +all: foo.x foo-mt.x + +foo.x: ;@echo $x +foo-mt.x: ;@echo $x +', +'', +"one\ntwo"); + +1; diff --git a/src/kmk/tests/scripts/features/patternrules b/src/kmk/tests/scripts/features/patternrules new file mode 100644 index 0000000..9aa4f62 --- /dev/null +++ b/src/kmk/tests/scripts/features/patternrules @@ -0,0 +1,232 @@ +# -*-perl-*- + +$description = "Test pattern rules."; + +$details = ""; + +use Cwd; + +$dir = cwd; +$dir =~ s,.*/([^/]+)$,../$1,; + + +# TEST #0: Make sure that multiple patterns where the same target +# can be built are searched even if the first one fails +# to match properly. +# + +run_make_test(q! +.PHONY: all + +all: case.1 case.2 case.3 + +# 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 + +# 2 - phony +%.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.implicit-phony: +!, '', ''); + +# TEST #1: make sure files that are built via implicit rules are marked +# as targets (Savannah bug #12202). +# +run_make_test(' +TARGETS := foo foo.out + +.PHONY: all foo.in + +all: $(TARGETS) + +%: %.in + @echo $@ + +%.out: % + @echo $@ + +foo.in: ; @: + +', +'', +'foo +foo.out'); + + +# TEST #2: make sure intermediate files that also happened to be +# prerequisites are not removed (Savannah bug #12267). +# +run_make_test(' +$(dir)/foo.o: + +$(dir)/foo.y: + @echo $@ + +%.c: %.y + touch $@ + +%.o: %.c + @echo $@ + +.PHONY: install +install: $(dir)/foo.c + +', +"dir=$dir", +"$dir/foo.y +touch $dir/foo.c +$dir/foo.o"); + +unlink("$dir/foo.c"); + + +# TEST #3: make sure precious flag is set properly for targets +# that are built via implicit rules (Savannah bug #13218). +# +run_make_test(' +.DELETE_ON_ERROR: + +.PRECIOUS: %.bar + +%.bar:; @touch $@ && exit 1 + +$(dir)/foo.bar: + +', +"dir=$dir", +(!$is_kmk) ? +"#MAKE#: *** [#MAKEFILE#:6: $dir/foo.bar] Error 1": +"#MAKE#: *** [$dir/foo.bar] Error 1" . ' +The failing command: + @touch $@ && exit 1', +512); + +unlink("$dir/foo.bar"); + + +# TEST #4: make sure targets of a matched implicit pattern rule are +# never considered intermediate (Savannah bug #13022). +# +run_make_test(' +.PHONY: all +all: foo.c foo.o + +%.h %.c: %.in + touch $*.h + touch $*.c + +%.o: %.c %.h + echo $+ >$@ + +%.o: %.c + @echo wrong rule + +foo.in: + touch $@ + +', +'-j1', +'touch foo.in +touch foo.h +touch foo.c +echo foo.c foo.h >foo.o'); + +unlink('foo.in', 'foo.h', 'foo.c', 'foo.o'); + +# TEST #5: make sure both prefix and suffix patterns work with multiple +# target patterns (Savannah bug #26593). +# +run_make_test(' +all: foo.s1 foo.s2 p1.foo p2.foo + +p1.% p2.%: %.orig + @echo $@ +%.s1 %.s2: %.orig + @echo $@ + +.PHONY: foo.orig +', + '', "foo.s1\np1.foo\n"); + +# TEST 6: Make sure that non-target files are still eligible to be created +# as part of implicit rule chaining. Savannah bug #17752. + +run_make_test(q! +BIN = xyz +COPY = $(BIN).cp +SRC = $(BIN).c +allbroken: $(COPY) $(BIN) ; @echo ok +$(SRC): ; @echo 'main(){}' > $@ +%.cp: % ; @cp $< $@ +% : %.c ; @cp $< $@ +clean: ; @rm -rf $(SRC) $(COPY) $(BIN) +!, + '', "ok\n"); + +unlink(qw(xyz xyz.cp xyz.c)); + +# TEST 7: Make sure that all prereqs of all "also_make" targets get created +# before any of the things that depend on any of them. Savannah bug #19108. + +run_make_test(q! +final: x ; @echo $@ +x: x.t1 x.t2 ; @echo $@ +x.t2: dep +dep: ; @echo $@ +%.t1 %.t2: ; @echo $*.t1 ; echo $*.t2 +!, + '', "dep\nx.t1\nx.t2\nx\nfinal\n"); + + +# TEST 8: Verify we can remove pattern rules. Savannah bug #18622. + +my @f = (qw(foo.w foo.ch)); +touch(@f); + +run_make_test(q! +CWEAVE := : + +# Disable builtin rules +%.tex : %.w +%.tex : %.w %.ch +!, + 'foo.tex', + "#MAKE#: *** No rule to make target 'foo.tex'. Stop.", 512); + +unlink(@f); + +# TEST #9: Test shortest stem selection in pattern rules. + +run_make_test(' +%.x: ;@echo one +%-mt.x: ;@echo two + +all: foo.x foo-mt.x +', +'', +"one\ntwo"); + +1; + +# 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/src/kmk/tests/scripts/features/quoting b/src/kmk/tests/scripts/features/quoting new file mode 100644 index 0000000..916681c --- /dev/null +++ b/src/kmk/tests/scripts/features/quoting @@ -0,0 +1,32 @@ +# -*-perl-*- + +$description = "The following test creates a makefile to test using \n" . + "quotes within makefiles."; + +open(MAKEFILE,"> $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE <<'EOM'; +SHELL = /bin/sh +TEXFONTS = NICEFONT +DEFINES = -DDEFAULT_TFM_PATH=\".:$(TEXFONTS)\" +test: ; @"echo" 'DEFINES = $(DEFINES)' +EOM + +# 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 = 'DEFINES = -DDEFAULT_TFM_PATH=\".:NICEFONT\"' . "\n"; + +# COMPARE RESULTS + +&compare_output($answer,&get_logfile(1)); + +1; diff --git a/src/kmk/tests/scripts/features/recursion b/src/kmk/tests/scripts/features/recursion new file mode 100644 index 0000000..862b6c4 --- /dev/null +++ b/src/kmk/tests/scripts/features/recursion @@ -0,0 +1,55 @@ +# -*-perl-*- +$description = "Test recursion."; + +$details = "DETAILS"; + +# Test some basic recursion. +run_make_test(' +all: + $(MAKE) -f #MAKEFILE# foo +foo: + @echo $(MAKE) + @echo MAKELEVEL = $('. (!$is_kmk ? 'MAKELEVEL' : 'KMK_LEVEL') .') + $(MAKE) -f #MAKEFILE# last +last: + @echo $(MAKE) + @echo MAKELEVEL = $('. (!$is_kmk ? 'MAKELEVEL' : 'KMK_LEVEL') .') + @echo THE END +', + ('CFLAGS=-O -w' . ($parallel_jobs ? ' -j 2' : '')), + ($vos + ? "#MAKE#: Entering directory '#PWD#' +make 'CFLAGS=-O' -f #MAKEFILE# foo +make CFLAGS=-O +MAKELEVEL = 0 +make 'CFLAGS=-O' -f #MAKEFILE# last +make CFLAGS=-O +MAKELEVEL = 0 +THE END +#MAKE#: Leaving directory '#PWD#'" + : "#MAKE#: Entering directory '#PWD#' +#MAKEPATH# -f #MAKEFILE# foo +#MAKE#[1]: Entering directory '#PWD#' +#MAKEPATH# +MAKELEVEL = 1 +#MAKEPATH# -f #MAKEFILE# last +#MAKE#[2]: Entering directory '#PWD#' +#MAKEPATH# +MAKELEVEL = 2 +THE END +#MAKE#[2]: Leaving directory '#PWD#' +#MAKE#[1]: Leaving directory '#PWD#' +#MAKE#: Leaving directory '#PWD#'")); + + +# Test command line overrides. +run_make_test(' +recur: all ; @$(MAKE) --no-print-directory -f #MAKEFILE# a=AA all +all: ; @echo "MAKEOVERRIDES = $('. (!$is_kmk ? 'MAKEOVERRIDES' : 'KMK_OVERRIDES') .')" +', + 'a=ZZ', + 'MAKEOVERRIDES = a=ZZ +MAKEOVERRIDES = a=AA +'); + +1; diff --git a/src/kmk/tests/scripts/features/reinvoke b/src/kmk/tests/scripts/features/reinvoke new file mode 100644 index 0000000..eb1a349 --- /dev/null +++ b/src/kmk/tests/scripts/features/reinvoke @@ -0,0 +1,80 @@ +# -*-mode: perl-*- + +$description = "Test GNU make's auto-reinvocation feature."; + +$details = "\ +If the makefile or one it includes can be rebuilt then it is, and make +is reinvoked. We create a rule to rebuild the makefile from a temp +file, then touch the temp file to make it newer than the makefile."; + +$omkfile = $makefile; + +&utouch(-600, 'incl.mk'); +# For some reason if we don't do this then the test fails for systems +# with sub-second timestamps, maybe + NFS? Not sure. +&utouch(-1, 'incl-1.mk'); + +run_make_test(' +all: ; @echo running rules. + +#MAKEFILE# incl.mk: incl-1.mk + @echo rebuilding $@ + @echo >> $@ + +include incl.mk', + '', "rebuilding incl.mk\nrunning rules.\n"); + +# Make sure updating the makefile itself also works + +&utouch(-600, $omkfile); + +run_make_test(undef, '', "rebuilding #MAKEFILE#\nrunning rules.\n"); + +&rmfiles('incl.mk', 'incl-1.mk'); + + +# In this test we create an included file that's out-of-date, but then +# the rule doesn't update it. Make shouldn't re-exec. + +&utouch(-600, 'b','a'); +#&utouch(-10, 'a'); +&touch('c'); + +run_make_test(' +SHELL = /bin/sh + +all: ; @echo hello + +a : b ; echo >> $@ + +b : c ; [ -f $@ ] || echo >> $@ + +c: ; echo >> $@ + +include $(F)', + 'F=a', "[ -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") + +&rmfiles('a','b','c'); + +# Ensure command line variables are preserved properly across re-exec +# Tests for Savannah bug #30723 + +run_make_test(' +ifdef RECURSE +-include foo30723 +endif +recurse: ; @$(MAKE) -f $(MAKEFILE_LIST) RECURSE=1 test +test: ; @echo F.O=$(F.O) +foo30723: ; @touch $@ +', + '--no-print-directory F.O=bar', "F.O=bar\n"); + +unlink('foo30723'); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/rule_glob b/src/kmk/tests/scripts/features/rule_glob new file mode 100644 index 0000000..2d377e7 --- /dev/null +++ b/src/kmk/tests/scripts/features/rule_glob @@ -0,0 +1,37 @@ +# -*-perl-*- + +$description = "Test globbing in targets and prerequisites."; + +$details = ""; + +touch(qw(a.one a.two a.three)); + +# Test wildcards in regular targets and prerequisites +run_make_test(q{ +.PHONY: all a.one a.two a.three +all: a.one* a.t[a-z0-9]o a.th[!q]ee +a.o[Nn][Ee] a.t*: ; @echo $@ +}, + '', "a.one\na.two\na.three"); + +# Test wildcards in pattern targets and prerequisites +run_make_test(q{ +.PHONY: all +all: a.four +%.four : %.t* ; @echo $@: $(sort $^) +}, + '', "a.four: a.three a.two"); + +# Test wildcards in second expansion targets and prerequisites +run_make_test(q{ +.PHONY: all +all: a.four +.SECONDEXPANSION: +%.four : $$(sort %.t*) ; @echo $@: $(sort $^) +}, + '', "a.four: a.three a.two"); + +unlink(qw(a.one a.two a.three)); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/se_explicit b/src/kmk/tests/scripts/features/se_explicit new file mode 100644 index 0000000..ab7c26f --- /dev/null +++ b/src/kmk/tests/scripts/features/se_explicit @@ -0,0 +1,169 @@ +# -*-perl-*- +$description = "Test second expansion in ordinary rules."; + +$details = ""; + +# TEST #0: Test handing of '$' in prerequisites with and without second +# expansion. +# bird: Modified this test to use ${PRE} instead of $(PRE) as it failes +# when make is built with NO_ARCHIVES defined. + +# If we don't support archives then the prerequisite is different +my $prereq = exists $FEATURES{'archives'} ? '$' : '$(PRE)'; + +run_make_test(q! +ifdef SE + .SECONDEXPANSION: +endif +foo$$bar: bar$$baz bar$$biz ; @echo '$@ : $^' +PRE = one two +bar$$baz: $${PRE} +baraz: $${PRE} +PRE = three four +.DEFAULT: ; @echo '$@' +!, + '', + "$prereq\nbar\$biz\nfoo\$bar : bar\$baz bar\$biz"); + +run_make_test(undef, 'SE=1', "three\nfour\nbariz\nfoo\$bar : baraz bariz"); + +# TEST #1: automatic variables. +# +run_make_test(q! +.SECONDEXPANSION: +.DEFAULT: ; @echo '$@' + +foo: bar baz + +foo: biz | buz + +foo: $$@.1 \ + $$<.2 \ + $$(addsuffix .3,$$^) \ + $$(addsuffix .4,$$+) \ + $$|.5 \ + $$*.6 + +!, +'-j1', +'bar +baz +biz +buz +foo.1 +bar.2 +bar.3 +baz.3 +biz.3 +bar.4 +baz.4 +biz.4 +buz.5 +.6 +'); + + +# Test #2: target/pattern -specific variables. +# +run_make_test(q! +.SECONDEXPANSION: +.DEFAULT: ; @echo '$@' + +foo.x: $$a $$b + +foo.x: a := bar + +%.x: b := baz +!, +'', +'bar +baz +'); + + +# Test #3: order of prerequisites. +# +run_make_test(q! +.SECONDEXPANSION: +.DEFAULT: ; @echo '$@' + +all: foo bar baz + +# Subtest #1 +foo: foo.1; @: +foo: foo.2 +foo: foo.3 + +# Subtest #2 +bar: bar.2 +bar: bar.1; @: +bar: bar.3 + +# Subtest #3 +baz: baz.1 +baz: baz.2 +baz: ; @: +!, +'-j1', +'foo.1 +foo.2 +foo.3 +bar.1 +bar.2 +bar.3 +baz.1 +baz.2 +'); + +# TEST #4: eval in a context where there is no reading_file +run_make_test(q! +.SECONDEXPANSION: +all : $$(eval $$(info test)) +!, + '', "test\n#MAKE#: Nothing to be done for 'all'.\n"); + +# TEST #5: (NEGATIVE) catch eval in a prereq list trying to create new +# target/prereq relationships. + +run_make_test(q! +.SECONDEXPANSION: +proj1.exe : proj1.o $$(eval $$(test)) +define test +proj1.o : proj1.c +proj1.c: proj1.h +endef +!, + '', "#MAKE#: *** prerequisites cannot be defined in recipes. Stop.\n", 512); + + +# Automatic $$+ variable expansion issue. Savannah bug #25780 +run_make_test(q! +all : foo foo +.SECONDEXPANSION: +all : $$+ ; @echo '$+' +foo : ; +!, + '', "foo foo foo foo\n"); + + +# Automatic $$+ variable expansion issue. Savannah bug #25780 +run_make_test(q! +all : bar bar +bar : ; +q%x : ; +.SECONDEXPANSION: +a%l: q1x $$+ q2x ; @echo '$+' +!, + '', "q1x bar bar q2x bar bar\n"); + + +# Allow patsubst shorthand in second expansion context. +# Requires the colon to be quoted. Savannah bug #16545 +run_make_test(q! +.PHONY: foo.bar +.SECONDEXPANSION: +foo: $$(@\\:%=%.bar); @echo '$^' +!, + '', "foo.bar\n"); + +1; diff --git a/src/kmk/tests/scripts/features/se_implicit b/src/kmk/tests/scripts/features/se_implicit new file mode 100644 index 0000000..e40270f --- /dev/null +++ b/src/kmk/tests/scripts/features/se_implicit @@ -0,0 +1,260 @@ +# -*-perl-*- +$description = "Test second expansion in ordinary rules."; + +$details = ""; + +use Cwd; + +$dir = cwd; +$dir =~ s,.*/([^/]+)$,../$1,; + + +# Test #1: automatic variables. +# +run_make_test(q! +.SECONDEXPANSION: +.DEFAULT: ; @echo '$@' + +foo.a: bar baz + +foo.a: biz | buz + +foo.%: 1.$$@ \ + 2.$$< \ + $$(addprefix 3.,$$^) \ + $$(addprefix 4.,$$+) \ + 5.$$| \ + 6.$$* + @: + +1.foo.a \ +2.bar \ +3.bar \ +3.baz \ +3.biz \ +4.bar \ +4.baz \ +4.biz \ +5.buz \ +6.a: + @echo '$@' + +!, +'-j1', +'1.foo.a +2.bar +3.bar +3.baz +3.biz +4.bar +4.baz +4.biz +5.buz +6.a +bar +baz +biz +buz +'); + + +# Test #2: target/pattern -specific variables. +# +run_make_test(q! +.SECONDEXPANSION: +foo.x: + +foo.%: $$(%_a) $$(%_b) bar + @: + +foo.x: x_a := bar + +%.x: x_b := baz + +bar baz: ; @echo '$@' +!, + '', "bar\nbaz\n"); + + +# Test #3: order of prerequisites. +# +run_make_test(q! +.SECONDEXPANSION: +.DEFAULT: ; @echo '$@' + +all: foo bar baz + + +# Subtest #1 +# +%oo: %oo.1; @: + +foo: foo.2 + +foo: foo.3 + +foo.1: ; @echo '$@' + + +# Subtest #2 +# +bar: bar.2 + +%ar: %ar.1; @: + +bar: bar.3 + +bar.1: ; @echo '$@' + + +# Subtest #3 +# +baz: baz.1 + +baz: baz.2 + +%az: ; @: +!, + '-j1', +'foo.1 +foo.2 +foo.3 +bar.1 +bar.2 +bar.3 +baz.1 +baz.2 +'); + + +# Test #4: stem splitting logic. +# +run_make_test(q! +.SECONDEXPANSION: +$(dir)/tmp/bar.o: + +$(dir)/tmp/foo/bar.c: ; @echo '$@' +$(dir)/tmp/bar/bar.c: ; @echo '$@' +foo.h: ; @echo '$@' + +%.o: $$(addsuffix /%.c,foo bar) foo.h + @echo '$@: {$<} $^' +!, + "dir=$dir", "$dir/tmp/foo/bar.c +$dir/tmp/bar/bar.c +foo.h +$dir/tmp/bar.o: {$dir/tmp/foo/bar.c} $dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h +"); + + +# Test #5: stem splitting logic and order-only prerequisites. +# +run_make_test(q! +.SECONDEXPANSION: +$(dir)/tmp/foo.o: $(dir)/tmp/foo.c +$(dir)/tmp/foo.c: ; @echo '$@' +bar.h: ; @echo '$@' + +%.o: %.c|bar.h + @echo '$@: {$<} {$|} $^' + +!, + "dir=$dir", "$dir/tmp/foo.c +bar.h +$dir/tmp/foo.o: {$dir/tmp/foo.c} {bar.h} $dir/tmp/foo.c +"); + + +# Test #6: lack of implicit prerequisites. +# +run_make_test(q! +.SECONDEXPANSION: +foo.o: foo.c +foo.c: ; @echo '$@' + +%.o: + @echo '$@: {$<} $^' +!, + '', "foo.c\nfoo.o: {foo.c} foo.c\n"); + + +# Test #7: Test stem from the middle of the name. +# +run_make_test(q! +.SECONDEXPANSION: +foobarbaz: + +foo%baz: % $$*.1 + @echo '$*' + +bar bar.1: + @echo '$@' +!, + '', "bar\nbar.1\nbar\n"); + + +# Test #8: Make sure stem triple-expansion does not happen. +# +run_make_test(q! +.SECONDEXPANSION: +foo$$bar: + +f%r: % $$*.1 + @echo '$*' + +oo$$ba oo$$ba.1: + @echo '$@' +!, + '', 'oo$ba +oo$ba.1 +oo$ba +'); + +# Test #9: Check the value of $^ +run_make_test(q! +.SECONDEXPANSION: + +%.so: | $$(extra) ; @echo $^ + +foo.so: extra := foo.o +foo.so: +foo.o: +!, + '', "\n"); + +# Test #10: Test second expansion with second expansion prerequisites +# Ensures pattern_search() recurses with SE prereqs. +touch('a'); +run_make_test(q! +.SECONDEXPANSION: +sim_base_rgg := just_a_name +sim_base_src := a +sim_base_f := a a a +sim_%.f: $${sim_$$*_f} + echo $@ +sim_%.src: $${sim_$$*_src} + echo $@ +sim_%: \ + $$(if $$(sim_$$*_src),sim_%.src) \ + $$(if $$(sim_$$*_f),sim_%.f) \ + $$(if $$(sim_$$*_rgg),$$(sim_$$*_rgg).s) + echo $@ +!, + '-s sim_base', "#MAKE#: *** No rule to make target 'sim_base'. Stop.", 512); + +unlink('a'); + +# Ensure that order-only tokens embedded in second expansions are parsed +run_make_test(q! +.SECONDEXPANSION: +PREREQS=p1|p2 +P2=p2 +all : foo bar +f%o: $$(PREREQS) ; @echo '$@' from '$^' and '$|' +b%r: p1|$$(P2) ; @echo '$@' from '$^' and '$|' +p% : ; : $@ +!, + "", ": p1\n: p2\nfoo from p1 and p2\nbar from p1 and p2\n"); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/se_statpat b/src/kmk/tests/scripts/features/se_statpat new file mode 100644 index 0000000..828afa2 --- /dev/null +++ b/src/kmk/tests/scripts/features/se_statpat @@ -0,0 +1,109 @@ +# -*-perl-*- +$description = "Test second expansion in static pattern rules."; + +$details = ""; + +# Test #1: automatic variables. +# +# bird: Had to add -j1 here earlier... +run_make_test(q! +.SECONDEXPANSION: +.DEFAULT: ; @echo '$@' + +foo.a foo.b: foo.%: bar.% baz.% +foo.a foo.b: foo.%: biz.% | buz.% + +foo.a foo.b: foo.%: $$@.1 \ + $$<.2 \ + $$(addsuffix .3,$$^) \ + $$(addsuffix .4,$$+) \ + $$|.5 \ + $$*.6 +!, + '', 'bar.a +baz.a +biz.a +buz.a +foo.a.1 +bar.a.2 +bar.a.3 +baz.a.3 +biz.a.3 +bar.a.4 +baz.a.4 +biz.a.4 +buz.a.5 +a.6 +'); + + +# Test #2: target/pattern -specific variables. +# +run_make_test(q! +.SECONDEXPANSION: +.DEFAULT: ; @echo '$@' + +foo.x foo.y: foo.%: $$(%_a) $$($$*_b) + +foo.x: x_a := bar + +%.x: x_b := baz +!, + '', "bar\nbaz\n"); + + +# Test #3: order of prerequisites. +# +# bird: Had to add -j1 here earlier... +run_make_test(q! +.SECONDEXPANSION: +.DEFAULT: ; @echo '$@' + +all: foo.a bar.a baz.a + +# Subtest #1 +foo.a foo.b: foo.%: foo.%.1; @: +foo.a foo.b: foo.%: foo.%.2 +foo.a foo.b: foo.%: foo.%.3 + + +# Subtest #2 +bar.a bar.b: bar.%: bar.%.2 +bar.a bar.b: bar.%: bar.%.1; @: +bar.a bar.b: bar.%: bar.%.3 + + +# Subtest #3 +baz.a baz.b: baz.%: baz.%.1 +baz.a baz.b: baz.%: baz.%.2 +baz.a baz.b: ; @: +!, + '', 'foo.a.1 +foo.a.2 +foo.a.3 +bar.a.1 +bar.a.2 +bar.a.3 +baz.a.1 +baz.a.2 +'); + + +# Test #4: Make sure stem triple-expansion does not happen. +# +run_make_test(q! +.SECONDEXPANSION: +foo$$bar: f%r: % $$*.1 + @echo '$*' + +oo$$ba oo$$ba.1: + @echo '$@' +!, + '', 'oo$ba +oo$ba.1 +oo$ba +'); + + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/shell_assignment b/src/kmk/tests/scripts/features/shell_assignment new file mode 100644 index 0000000..686e4bd --- /dev/null +++ b/src/kmk/tests/scripts/features/shell_assignment @@ -0,0 +1,65 @@ +# -*-perl-*- + +$description = "Test BSD-style shell assignments (VAR != VAL) for variables."; + +$details = ""; + +# TEST 0: Basic shell assignment (!=). + +run_make_test(' +.POSIX: + +demo1!=printf \' 1 2 3\n4\n\n5 \n \n 6\n\n\n\n\' +demo2 != printf \'7 8\n \' +demo3 != printf \'$$(demo2)\' +demo4 != printf \' 2 3 \n\' +demo5 != printf \' 2 3 \n\n\' +all: ; @echo "<$(demo1)> <$(demo2)> <$(demo3)> <$(demo4)> <${demo5}>" +', + '', "< 1 2 3 4 5 6 > <7 8 > <7 8 > < 2 3 > < 2 3 >\n"); + +# TEST 1: Handle '#' the same way as BSD make + +run_make_test(' +foo1!=echo bar#baz +hash != printf \'\043\' +foo2!= echo "bar$(hash)baz" + +all: ; @echo "<$(foo1)> <$(hash)> <$(foo2)>" +', + '', " <#> \n"); + +# TEST 2: shell assignment variables (from !=) should be recursive. +# Note that variables are re-evaluated later, so the shell can output +# a value like $(XYZZY) as part of !=. The $(XYZZY) will be EVALUATED +# when the value containing it is evaluated. On the negative side, this +# means if you don't want this, you need to escape dollar signs as $$. +# On the positive side, it means that shell programs can output macros +# that are then evaluated as they are traditionally evaluated.. and that +# you can use traditional macro evaluation semantics to implement !=. + +run_make_test(' +XYZZY = fiddle-dee-dee +dollar = $$ +VAR3 != printf \'%s\' \'$(dollar)(XYZZY)\' + +all: ; @echo "<$(VAR3)>" +', + '', "\n"); + + +# TEST 3: Overrides invoke shell anyway; they just don't store the result +# in a way that is visible. + +run_make_test(' + +override != echo abc > ,abc ; cat ,abc + +all: ; @echo "<$(override)>" ; cat ,abc +', + 'override=xyz', "\nabc\n"); + +unlink(',abc'); + + +1; diff --git a/src/kmk/tests/scripts/features/statipattrules b/src/kmk/tests/scripts/features/statipattrules new file mode 100644 index 0000000..6b3c565 --- /dev/null +++ b/src/kmk/tests/scripts/features/statipattrules @@ -0,0 +1,111 @@ +# -*-perl-*- +$description = "Test handling of static pattern rules."; + +$details = "\ +The makefile created in this test has three targets. The +filter command is used to get those target names ending in +.o and statically creates a compile command with the target +name and the target name with .c. It also does the same thing +for another target filtered with .elc and creates a command +to emacs a .el file"; + +&touch('bar.c', 'lose.c'); + +# TEST #0 +# ------- + +run_make_test(' +files = foo.elc bar.o lose.o + +$(filter %.o,$(files)): %.o: %.c ; @echo CC -c $(CFLAGS) $< -o $@ + +$(filter %.elc,$(files)): %.elc: %.el ; @echo emacs $< +', + '', + 'CC -c bar.c -o bar.o'); + +# TEST #1 +# ------- + +run_make_test(undef, 'lose.o', 'CC -c lose.c -o lose.o'); + + +# TEST #2 +# ------- +&touch("foo.el"); + +run_make_test(undef, 'foo.elc', 'emacs foo.el'); + +# Clean up after the first tests. +unlink('foo.el', 'bar.c', 'lose.c'); + + +# TEST #3 -- PR/1670: don't core dump on invalid static pattern rules +# ------- + +run_make_test(' +.DEFAULT: ; @echo $@ +foo: foo%: % %.x % % % y.% % ; @echo $@ +', + '-j1', ".x\ny.\nfoo"); + + +# TEST #4 -- bug #12180: core dump on a stat pattern rule with an empty +# prerequisite list. +run_make_test(' +foo.x bar.x: %.x : ; @echo $@ + +', + '', 'foo.x'); + + +# TEST #5 -- bug #13881: double colon static pattern rule does not +# substitute %. +run_make_test(' +foo.bar:: %.bar: %.baz +foo.baz: ;@: +', + '', ''); + + +# TEST #6: make sure the second stem does not overwrite the first +# perprerequisite's stem (Savannah bug #16053). +# +run_make_test(' +all.foo.bar: %.foo.bar: %.one + +all.foo.bar: %.bar: %.two + +all.foo.bar: + @echo $* + @echo $^ + +.DEFAULT:;@: +', +'', +'all.foo +all.one all.foo.two'); + + +# TEST #7: make sure the second stem does not overwrite the first +# perprerequisite's stem when second expansion is enabled +# (Savannah bug #16053). +# +run_make_test(' +.SECONDEXPANSION: + +all.foo.bar: %.foo.bar: %.one $$*-one + +all.foo.bar: %.bar: %.two $$*-two + +all.foo.bar: + @echo $* + @echo $^ + +.DEFAULT:;@: +', +'', +'all.foo +all.one all-one all.foo.two all.foo-two'); + +1; diff --git a/src/kmk/tests/scripts/features/targetvars b/src/kmk/tests/scripts/features/targetvars new file mode 100644 index 0000000..a9b8dbe --- /dev/null +++ b/src/kmk/tests/scripts/features/targetvars @@ -0,0 +1,273 @@ +# -*-perl-*- +$description = "Test target-specific variable settings."; + +$details = "\ +Create a makefile containing various flavors of target-specific variable +values, override and non-override, and using various variable expansion +rules, semicolon interference, etc."; + +run_make_test(' +SHELL = /bin/sh +export FOO = foo +export BAR = bar +one: override FOO = one +one two: ; @echo $(FOO) $(BAR) +two: BAR = two +three: ; BAR=1000 + @echo $(FOO) $(BAR) +# Some things that shouldn not be target vars +funk : override +funk : override adelic +adelic override : ; echo $@ +# Test per-target recursive variables +four:FOO=x +four:VAR$(FOO)=ok +four: ; @echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)" +five:FOO=x +five six : VAR$(FOO)=good +five six: ;@echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)" +# Test per-target variable inheritance +seven: eight +seven eight: ; @echo $@: $(FOO) $(BAR) +seven: BAR = seven +seven: FOO = seven +eight: BAR = eight +# Test the export keyword with per-target variables +nine: ; @echo $(FOO) $(BAR) $$FOO $$BAR +nine: FOO = wallace +nine-a: export BAZ = baz +nine-a: ; @echo $$BAZ +# Test = escaping +EQ = = +ten: one$(EQ)two +ten: one $(EQ) two +ten one$(EQ)two $(EQ):;@echo $@ +.PHONY: one two three four five six seven eight nine ten $(EQ) one$(EQ)two +# Test target-specific vars with pattern/suffix rules +QVAR = qvar +RVAR = = +%.q : ; @echo $(QVAR) $(RVAR) +foo.q : RVAR += rvar +# Target-specific vars with multiple LHS pattern rules +%.r %.s %.t: ; @echo $(QVAR) $(RVAR) $(SVAR) $(TVAR) +foo.r : RVAR += rvar +foo.t : TVAR := $(QVAR) +', + "one two three", "one bar\nfoo two\nBAR=1000\nfoo bar\n"); + +# TEST #2 + +run_make_test(undef, "one two FOO=1 BAR=2", "one 2\n1 2\n"); + +# TEST #3 + +run_make_test(undef, "four", "x ok ok\n"); + +# TEST #4 + +run_make_test(undef, "seven", "eight: seven eight\nseven: seven seven\n"); + +# TEST #5 + +run_make_test(undef, "nine", "wallace bar wallace bar\n"); + +# TEST #5-a + +run_make_test(undef, "nine-a", "baz\n"); + +# TEST #6 + +run_make_test(undef, "ten", "one=two\none bar\n=\nfoo two\nten\n"); + +# TEST #6 + +run_make_test(undef, "foo.q bar.q", "qvar = rvar\nqvar =\n"); + +# TEST #7 + +run_make_test(undef, "foo.t bar.s", "qvar = qvar\nqvar =\n"); + + +# TEST #8 +# For PR/1378: Target-specific vars don't inherit correctly + +run_make_test(' +foo: FOO = foo +bar: BAR = bar +foo: bar +bar: baz +baz: ; @echo $(FOO) $(BAR) +', "", "foo bar\n"); + +# TEST #9 +# For PR/1380: Using += assignment in target-specific variables sometimes fails +# Also PR/1831 + +run_make_test(' +.PHONY: all one +all: FOO += baz +all: one; @echo $(FOO) + +FOO = bar + +one: FOO += biz +one: FOO += boz +one: ; @echo $(FOO) +', + '', "bar baz biz boz\nbar baz\n"); + +# Test #10 + +run_make_test(undef, 'one', "bar biz boz\n"); + +# Test #11 +# PR/1709: Test semicolons in target-specific variable values + +run_make_test(' +foo : FOO = ; ok +foo : ; @echo "$(FOO)" +', + '', "; ok\n"); + +# Test #12 +# PR/2020: More hassles with += target-specific vars. I _really_ think +# I nailed it this time :-/. + +run_make_test(' +.PHONY: a + +BLAH := foo +COMMAND = echo $(BLAH) + +a: ; @$(COMMAND) + +a: BLAH := bar +a: COMMAND += snafu $(BLAH) +', + '', "bar snafu bar\n"); + +# Test #13 +# Test double-colon rules with target-specific variable values + +run_make_test(' +W = bad +X = bad +foo: W = ok +foo:: ; @echo $(W) $(X) $(Y) $(Z) +foo:: ; @echo $(W) $(X) $(Y) $(Z) +foo: X = ok + +Y = foo +bar: foo +bar: Y = bar + +Z = nopat +ifdef PATTERN + fo% : Z = pat +endif +', + 'foo', "ok ok foo nopat\nok ok foo nopat\n"); + +# Test #14 +# Test double-colon rules with target-specific variable values and +# inheritance + +run_make_test(undef, 'bar', "ok ok bar nopat\nok ok bar nopat\n"); + +# Test #15 +# Test double-colon rules with pattern-specific variable values + +run_make_test(undef, 'foo PATTERN=yes', "ok ok foo pat\nok ok foo pat\n"); + +# Test #16 +# Test target-specific variables with very long command line +# (> 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 ) + +deals_changed_since: ; @echo $(BUILD_OBJ) +', + '', "no build information\n"); + +# TEST #17 + +# Test a merge of set_lists for files, where one list is much longer +# than the other. See Savannah bug #15757. + +mkdir('t1', 0777); +touch('t1/rules.mk'); + +run_make_test(' +VPATH = t1 +include rules.mk +.PHONY: all +all: foo.x +foo.x : rules.mk ; @echo MYVAR=$(MYVAR) FOOVAR=$(FOOVAR) ALLVAR=$(ALLVAR) +all: ALLVAR = xxx +foo.x: FOOVAR = bar +rules.mk : MYVAR = foo +.INTERMEDIATE: foo.x rules.mk +', + '-I t1', 'MYVAR= FOOVAR=bar ALLVAR=xxx'); + +rmfiles('t1/rules.mk'); +rmdir('t1'); + +# TEST #18 + +# Test appending to a simple variable containing a "$": avoid a +# double-expansion. See Savannah bug #15913. + +run_make_test(' +VAR := $$FOO +foo: VAR += BAR +foo: ; @echo '."'".'$(VAR)'."'".' +', + '', '$FOO BAR'); + +# TEST #19: Override with append variables + +run_make_test(' +a: override FOO += f1 +a: FOO += f2 +a: ; @echo "$(FOO)" +', + '', "f1\n"); + +run_make_test(undef, 'FOO=C', "C f1\n"); + +# TEST #19: Conditional variables with command-line settings + +run_make_test(' +a: FOO ?= f1 +a: ; @echo "$(FOO)" +', + '', "f1\n"); + +run_make_test(undef, 'FOO=C', "C\n"); + +# TEST #20: Check for continuation after semicolons + +run_make_test(q! +a: A = 'hello;\ +world' +a: ; @echo $(A) +!, + '', "hello; world\n"); + +# TEST #19: Test define/endef variables as target-specific vars + +# run_make_test(' +# define b +# @echo global +# endef +# a: define b +# @echo local +# endef + +# a: ; $(b) +# ', +# '', "local\n"); + +1; diff --git a/src/kmk/tests/scripts/features/utf8 b/src/kmk/tests/scripts/features/utf8 new file mode 100644 index 0000000..54bc471 --- /dev/null +++ b/src/kmk/tests/scripts/features/utf8 @@ -0,0 +1,11 @@ +# -*-perl-*- + +$description = "Test support for UTF-8."; + +$details = ""; + +# Verify that the UTF-8 BOM is ignored. +run_make_test("\xEF\xBB\xBFall: ; \@echo \$\@\n", '', "all"); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/features/varnesting b/src/kmk/tests/scripts/features/varnesting new file mode 100644 index 0000000..d8f3ffb --- /dev/null +++ b/src/kmk/tests/scripts/features/varnesting @@ -0,0 +1,35 @@ +# -*-perl-*- +$description = "Test recursive variables"; + +$details = ""; + +run_make_test(' +x = variable1 +variable2 := Hello +y = $(subst 1,2,$(x)) +z = y +a := $($($(z))) +all: + @echo $(a) +', + '', "Hello\n"); + +# This tests resetting the value of a variable while expanding it. +# You may only see problems with this if you're using valgrind or +# some other memory checker that poisons freed memory. +# See Savannah patch #7534 + +run_make_test(' +VARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE) +wololo: + @$(VARIABLE) +', + '', "hi\n"); + +1; + + + + + + diff --git a/src/kmk/tests/scripts/features/vpath b/src/kmk/tests/scripts/features/vpath new file mode 100644 index 0000000..530d9e5 --- /dev/null +++ b/src/kmk/tests/scripts/features/vpath @@ -0,0 +1,82 @@ +# -*-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); + + +@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"); + +&touch(@files_to_touch); + +# kmk: this requires -j1 because of ordering. +&run_make_with_options($makefile,"-j1",&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"; + +if (&compare_output($answer,&get_logfile(1))) +{ + 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. + +mkdir('vpath-d', 0777); + +run_make_test(q! +vpath %.te vpath-d/ +.SECONDARY: +default: vpath-d/a vpath-d/b +vpath-d/a: fail.te +vpath-d/b : fail.te +vpath-d/fail.te: +!, + '', "#MAKE#: Nothing to be done for 'default'.\n"); + +rmdir('vpath-d'); + +1; diff --git a/src/kmk/tests/scripts/features/vpath2 b/src/kmk/tests/scripts/features/vpath2 new file mode 100644 index 0000000..7e970a7 --- /dev/null +++ b/src/kmk/tests/scripts/features/vpath2 @@ -0,0 +1,45 @@ +$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:$sourcedir\n"; +print MAKEFILE "vpath %.c foo\n"; +print MAKEFILE "vpath %.c $workdir\n"; +print MAKEFILE "vpath %.c $sourcedir\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/src/kmk/tests/scripts/features/vpath3 b/src/kmk/tests/scripts/features/vpath3 new file mode 100644 index 0000000..839fb72 --- /dev/null +++ b/src/kmk/tests/scripts/features/vpath3 @@ -0,0 +1,41 @@ +# -*-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/src/kmk/tests/scripts/features/vpathgpath b/src/kmk/tests/scripts/features/vpathgpath new file mode 100644 index 0000000..5e6217b --- /dev/null +++ b/src/kmk/tests/scripts/features/vpathgpath @@ -0,0 +1,66 @@ +# -*-perl-*- +$description = "Tests VPATH+/GPATH functionality."; + +$details = ""; + +$VP = "$workdir$pathsep"; + +open(MAKEFILE,"> $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE "VPATH = $VP\n"; + +print MAKEFILE <<'EOMAKE'; + +GPATH = $(VPATH) + +.SUFFIXES: .a .b .c .d +.PHONY: general rename notarget intermediate + +%.a: +%.b: +%.c: +%.d: + +%.a : %.b ; cat $^ > $@ +%.b : %.c ; cat $^ > $@ +%.c :: %.d ; cat $^ > $@ + +# General testing info: + +general: foo.b +foo.b: foo.c bar.c + +EOMAKE + +close(MAKEFILE); + +@touchedfiles = (); + +$off = -500; + +sub touchfiles { + foreach (@_) { + ($f = $_) =~ s,VP/,$VP,g; + &utouch($off, $f); + $off += 10; + push(@touchedfiles, $f); + } +} + +# 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()); + +push(@touchedfiles, "bar.c"); + +$answer = "$make_name: Nothing to be done for 'general'.\n"; + +&compare_output($answer,&get_logfile(1)); + +unlink(@touchedfiles) unless $keep; + +1; diff --git a/src/kmk/tests/scripts/features/vpathplus b/src/kmk/tests/scripts/features/vpathplus new file mode 100644 index 0000000..9ade3f0 --- /dev/null +++ b/src/kmk/tests/scripts/features/vpathplus @@ -0,0 +1,132 @@ +# -*-perl-*- +$description = "Tests the new VPATH+ functionality added in 3.76."; + +$details = ""; + +$VP = "$workdir$pathsep"; + +open(MAKEFILE,"> $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE "VPATH = $VP\n"; + +print MAKEFILE <<'EOMAKE'; + +SHELL = /bin/sh + +.SUFFIXES: .a .b .c .d +.PHONY: general rename notarget intermediate + +%.a: +%.b: +%.c: +%.d: + +%.a : %.b + cat $^ > $@ +%.b : %.c + cat $^ > $@ 2>/dev/null || exit 1 +%.c :: %.d + cat $^ > $@ + +# General testing info: + +general: foo.b +foo.b: foo.c bar.c + +# Rename testing info: + +rename: $(VPATH)/foo.c foo.d + +# Target not made testing info: + +notarget: notarget.b +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); + +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:16: notarget.b] Error 1 +"; + +&compare_output($answer,&get_logfile(1)); + +# Test intermediate file handling (part 1) + +&touchfiles("$VP/inter.d"); + +&run_make_with_options($makefile,"intermediate",&get_logfile); + +push(@touchedfiles, "inter.a", "inter.b"); + +$answer = "cat ${VP}inter.d > inter.c +cat inter.c > inter.b 2>/dev/null || exit 1 +cat inter.b > inter.a +rm inter.b inter.c +"; +&compare_output($answer,&get_logfile(1)); + +# Test intermediate file handling (part 2) + +&utouch(-20, "inter.a"); +&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); + +$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)); + +unlink @touchedfiles unless $keep; + +1; + +### Local Variables: +### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) +### End: -- cgit v1.2.3