my $reason; BEGIN { my $line = (split /\n/, `make -v`)[0]; if ($line) { warn $line, "\n"; if ($line =~ /GNU Make (\d+\.\d+)(\s+(?:alpha|beta))?/) { my ($make_ver, $modifier) = ($1, $2); if ($make_ver < 3.81 || ($make_ver == 3.81 && $modifier)) { $reason = 'GNU make too old (at least 3.81 final is required).'; } } else { $reason = 'No GNU make found.'; } } else { $reason = 'No make found in env.'; } } use Test::Base $reason ? (skip_all => $reason) : (); use File::Slurp; use IPC::Run3; use Cwd; use lib 't/lib'; use Test::Make::Util; plan tests => 3 * blocks(); my $makefile = 'makesimple.tmp.mk'; my $saved_cwd = cwd; run { my $block = shift; my $name = $block->name; chdir $saved_cwd; system('rm -rf t/tmp'); system('mkdir t/tmp'); chdir 't/tmp'; write_file($makefile, $block->in); my ($stdout, $stderr, @options); if ($block->options) { @options = split /\s+/, $block->options; } my $touch = $block->touch; if ($touch) { for my $file (split /\s+/, $touch) { touch($file); } } run3( [$^X, "$saved_cwd/script/makesimple", '-f', $makefile, @options], undef, \$stdout, \$stderr, ); is(($? >> 8), 0, "$name - process returned the 0 status"); is $stdout, $block->out, "$name - script/makesimple generated the right output"; is $stderr, $block->err, "$name - script/makesimple generated the right error"; }; __DATA__ === TEST 1: basics --- in FOO = world all: ; @ echo hello $(FOO) --- out all: @echo hello world --- err === TEST 2: canned sequence of commands --- in define FOO @echo -touch : endef all: @$(FOO) --- out all: @echo @-touch @: --- err === TEST 3: double-colon rules --- in all: foo foo:: bar @echo $@ $< foo:: blah blue -echo $^ --- out all: foo foo:: bar @echo foo bar foo:: blah blue -echo blah blue --- err makesimple: *** No rule to make target `bar', needed by `foo'. Ignored. makesimple: *** No rule to make target `blah', needed by `foo'. Ignored. makesimple: *** No rule to make target `blue', needed by `foo'. Ignored. === TEST 4: double-colon rules (no warnings) --- in all: foo foo:: bar @echo $@ $< foo:: blah blue -echo $^ --- out all: foo foo:: bar @echo foo bar foo:: blah blue -echo blah blue --- touch: bar blah blue --- err === TEST 5: .DEFAUL_GOAL --- in .DEFAULT_GOAL = foo all: foo @echo $< foo: bah ; : --- out foo: bah : all: foo @echo foo --- err makesimple: *** No rule to make target `bah', needed by `foo'. Ignored. === TEST 6: order-only prereqs --- in all : a b \ | c \ ; echo --- out all: a b | c echo --- err makesimple: *** No rule to make target `a', needed by `all'. Ignored. makesimple: *** No rule to make target `b', needed by `all'. Ignored. makesimple: *** No rule to make target `c', needed by `all'. Ignored. === TEST 7: multi-target rules --- in foo bar: a.h foo: blah ; echo $< > $@ --- out foo: blah a.h echo blah > foo bar: a.h --- err makesimple: *** No rule to make target `blah', needed by `foo'. Ignored. makesimple: *** No rule to make target `a.h', needed by `foo'. Ignored. === TEST 8: pattern rules (no match) --- in all: foo.x bar.w %.x: %.h touch $@ %.w: %.hpp ; $(CC) --- out all: foo.x bar.w --- err makesimple: *** No rule to make target `foo.x', needed by `all'. Ignored. makesimple: *** No rule to make target `bar.w', needed by `all'. Ignored. === TEST 9: pattern rules (no warnings) --- in all: foo.x bar.w %.x: %.h touch $@ %.w: %.hpp ; $(CC) --- touch: foo.x bar.w --- out all: foo.x bar.w --- err === TEST 10: pattern rules (with match) --- in all: foo.x bar.w %.x: %.h touch $@ %.w: %.hpp ; echo '$(CC)' --- touch: foo.h bar.hpp --- out all: foo.x bar.w foo.x: foo.h touch foo.x bar.w: bar.hpp echo '' --- err === TEST 11: chained implicit rules --- in all: foo.a bar.a baz.a %.a: %.b ; @touch $@ %.b: %.d ; @touch $@ --- touch: foo.d bar.d baz.d --- out all: foo.a bar.a baz.a foo.b: foo.d @touch foo.b foo.a: foo.b @touch foo.a bar.b: bar.d @touch bar.b bar.a: bar.b @touch bar.a baz.b: baz.d @touch baz.b baz.a: baz.b @touch baz.a --- err === TEST 12: extra goals given from the command line --- in all: foo.a %.a: %.b ; @touch $@ %.b: %.d ; @touch $@ --- options: bar.a --- touch: foo.d bar.d --- out all: foo.a bar.b: bar.d @touch bar.b bar.a: bar.b @touch bar.a foo.b: foo.d @touch foo.b foo.a: foo.b @touch foo.a --- err === TEST 13: target-specific variables --- in FOO = foo default: all any all: FOO += one all: FOO += two all: BAR = bar all: FOO += three all: BAR += baz all: ; @echo $(FOO); echo $(BAR) any: ; @echo $(FOO); echo $(BAR) end --- out default: all any all: @echo foo one two three; echo bar baz any: @echo foo; echo end --- err === TEST 14: ditto (override cmd line vars) --- in all: override FOO = foo all: ; @echo $(FOO) --- options: FOO=cmd --- out all: @echo foo --- err === TEST 15: ditto (cmd line vars) (2) --- in all: FOO = foo all: ; @echo $(FOO) --- options: FOO=cmd --- out all: @echo cmd --- err === TEST 16: static pattern rules --- in CC = gcc CFLAGS = objects = foo.o bar.o all: $(objects) $(objects): %.o: %.c $(CC) -c $(CFLAGS) $< -o $@ --- out all: foo.o bar.o foo.o: foo.c gcc -c foo.c -o foo.o bar.o: bar.c gcc -c bar.c -o bar.o --- err makesimple: *** No rule to make target `foo.c', needed by `foo.o'. Ignored. makesimple: *** No rule to make target `bar.c', needed by `bar.o'. Ignored. === TEST 17: static pattern rules (no warnings) --- in CC = gcc CFLAGS = -O objects = foo.o bar.o all: $(objects) $(objects): %.o: %.c $(CC) -c $(CFLAGS) $< -o $@ --- touch: foo.c bar.c --- out all: foo.o bar.o foo.o: foo.c gcc -c -O foo.c -o foo.o bar.o: bar.c gcc -c -O bar.c -o bar.o --- err === TEST 18: conditionals - ifdef $(foo) --- in bar = true foo = bar ifdef $(foo) all: ; @echo hello else foo: bar touch $@ endif -rm blahblah --- out all: @echo hello -rm blahblah --- err === TEST 19: conditionals - ifdef foo --- in foo = bar ifdef foo all: ; @echo hello else foo: bar touch $@ endif -rm blahblah --- out all: @echo hello -rm blahblah --- err === TEST 20: conditionals - override var foo via cmd line options --- in foo = bar ifdef foo all: ; @echo hello else foo: bar touch $@ endif -rm blahblah --- options: foo= --- out foo: bar touch foo -rm blahblah --- err makesimple: *** No rule to make target `bar', needed by `foo'. Ignored. === TEST 21: functions in the first pass --- in objects = foo.o bar.o baz.o all : $(objects:.o=.c) @ echo $^ --- out all: foo.c bar.c baz.c @echo foo.c bar.c baz.c --- err makesimple: *** No rule to make target `foo.c', needed by `all'. Ignored. makesimple: *** No rule to make target `bar.c', needed by `all'. Ignored. makesimple: *** No rule to make target `baz.c', needed by `all'. Ignored. === TEST 22: functions in the second pass --- in objects = foo.o bar.o baz.o all : echo $(patsubst %.o,%.c,${objects}) --- out all: echo foo.c bar.c baz.c --- err === TEST 23: functions in the both passes --- in objects = $(sort $(wildcard *.o)) all : ; echo $(patsubst %.o,%.c,${objects}) --- touch: foo.o bar.o baz.o --- out all: echo bar.c baz.c foo.c --- err === TEST 24: commands spanning multiple lines --- in foo=hello bar=my baz=world all: @echo $(foo) \ $(bar) \ $(baz) --- out all: @echo hello \ my \ world --- err === TEST 25: dynamics --- in head = all: $(head) @echo $@ --- out all: @echo all --- err === TEST 26: dynamics (2) --- in head = all: $(head) @echo $@ --- options: head=all:bar --- out all: bar @echo all --- err makesimple: *** No rule to make target `bar', needed by `all'. Ignored.