mirror of
https://github.com/mirror/make.git
synced 2025-01-11 12:50:43 +08:00
9e4b3d3f4c
If multiple intermediate files are built together be sure all of them are removed after make is finished. Continue to ensure that targets that exist before make starts are not removed even if they appear to be intermediate. Add a number of tests to pattern rules to verify this behavior. * src/filedef.h (struct file): Add a new is_explicit bitfield. * src/file.c (rehash_file): Merge the is_explicit bit. (enter_prereqs): Set is_explicit if the file is explicitly mentioned. * src/implicit.c (pattern_search): Set intermediate on the file if it's not explicit. (record_files): Set is_explicit if a file is mentioned as a target. * src/remake.c (update_file_1): Set secondary on files that already exist so they won't be removed. * tests/scripts/features/double_colon: Add a test for double-colon pattern rules. * tests/scripts/features/patternrules: Update KGO for tests where more files are removed. Add new tests to verify handling removal of intermediate files in the context of grouped pattern targets.
449 lines
9.6 KiB
Perl
449 lines
9.6 KiB
Perl
# -*-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 case.4
|
|
|
|
# We can't have this, due to "Implicit Rule Search Algorithm" step 5c
|
|
#xxx: void
|
|
|
|
# 1 - existing file
|
|
%.1: void ; @exit 1
|
|
%.1: #MAKEFILE# ; @exit 0
|
|
|
|
# 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:
|
|
|
|
# 4 - explicitly mentioned file made by an implicit rule
|
|
%.4: void ; @exit 1
|
|
%.4: test.x ; @exit 0
|
|
%.x: ;
|
|
!,
|
|
'', '');
|
|
|
|
# TEST #1: make sure files that are built via implicit rules are marked
|
|
# as targets (Savannah bug #12202).
|
|
#
|
|
run_make_test('
|
|
TARGETS := foo foo.out
|
|
|
|
.PHONY: all foo.in
|
|
|
|
all: $(TARGETS)
|
|
|
|
%: %.in ; @echo $@
|
|
|
|
%.out: % ; @echo $@
|
|
|
|
foo.in: ; @:
|
|
|
|
',
|
|
'', "foo\nfoo.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\ntouch $dir/foo.c\n$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",
|
|
"#MAKE#: *** [#MAKEFILE#:6: $dir/foo.bar] Error 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 $@
|
|
|
|
',
|
|
'', "touch foo.in\ntouch foo.h ; touch foo.c\necho foo.c foo.h >foo.o\nrm foo.h");
|
|
|
|
unlink('foo.in', 'foo.h', 'foo.c', 'foo.o');
|
|
|
|
# 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(sprintf(q!
|
|
BIN = xyz
|
|
COPY = $(BIN).cp
|
|
SRC = $(BIN).c
|
|
allbroken: $(COPY) $(BIN) ; @echo ok
|
|
$(SRC): ; @echo 'main(){}' > $@
|
|
%%.cp: %% ; @cp $< $@
|
|
%% : %%.c ; @cp $< $@
|
|
clean: ; @%s $(SRC) $(COPY) $(BIN)
|
|
!, $CMD_rmfile),
|
|
'', "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");
|
|
|
|
# Test pattern rules building the same targets
|
|
# See SV 54233. Rely on our standard test timeout to break the loop
|
|
|
|
touch('a.c');
|
|
|
|
# a.lnk isn't listed as removed, because it's not actually created
|
|
run_make_test(q!
|
|
all: a.elf a.dbg
|
|
|
|
%.elf %.lnk: %.c ; : $*.elf $*.lnk
|
|
|
|
%.elf %.dbg: %.lnk ; : $*.elf $*.dbg
|
|
!,
|
|
'-j2', ": a.elf a.lnk\n: a.elf a.dbg\n");
|
|
|
|
# SV 60435 : a.lnk is removed, because it is intermediate.
|
|
run_make_test(q!
|
|
all: a.elf a.dbg
|
|
|
|
%.elf %.lnk: %.c ; touch $*.elf $*.lnk
|
|
|
|
%.elf %.dbg: %.lnk ; touch $*.elf $*.dbg
|
|
!,
|
|
'-j2', "touch a.elf a.lnk\ntouch a.elf a.dbg\nrm a.lnk\n");
|
|
|
|
unlink('a.elf', 'a.dbg');
|
|
|
|
# SV 60435 : a.lnk is not intermediate, because it is explicitly mentioned.
|
|
run_make_test(q!
|
|
all: a.elf a.dbg
|
|
|
|
%.elf %.lnk: %.c ; touch $*.elf $*.lnk
|
|
|
|
%.elf %.dbg: %.lnk ; touch $*.elf $*.dbg
|
|
|
|
install: a.lnk
|
|
.PHONY: install
|
|
!,
|
|
'-j2', "touch a.elf a.lnk\ntouch a.elf a.dbg\n");
|
|
|
|
unlink('a.c', 'a.elf', 'a.dbg', 'a.lnk');
|
|
|
|
# SV 56655: Test patterns matching files containing whitespace
|
|
touch('some file.yy');
|
|
run_make_test(q!
|
|
%.xx : %.yy ; @echo matched
|
|
!,
|
|
'"some file.xx"', "matched\n");
|
|
|
|
unlink('some file.xx', 'some file.yy');
|
|
|
|
|
|
# sv 60188.
|
|
# Test that a file explicitly mentioned by the user and made by an implicit
|
|
# rule is not considered intermediate.
|
|
|
|
touch('hello.z');
|
|
unlink('hello.x', 'test.x');
|
|
|
|
# subtest 1
|
|
# hello.x is not explicitly mentioned and thus is an intermediate file.
|
|
run_make_test(q!
|
|
all: hello.z
|
|
%.z: %.x ; touch $@
|
|
%.x: ;
|
|
!,
|
|
'', "#MAKE#: Nothing to be done for 'all'.\n");
|
|
|
|
# subtest 2
|
|
# test.x is explicitly mentioned and thus is not an intermediate file.
|
|
run_make_test(q!
|
|
all: hello.z
|
|
%.z: %.x test.x ; touch $@
|
|
%.x: ;
|
|
!,
|
|
'', "touch hello.z");
|
|
|
|
unlink('hello.z');
|
|
|
|
# sv 60188.
|
|
# Test that a file explicitly mentioned by the user and made by an implicit
|
|
# rule is not considered intermediate, even when the builtin rules are used.
|
|
|
|
touch('hello.x');
|
|
touch('test.x');
|
|
touch('hello.tsk');
|
|
|
|
# subtest 1
|
|
# hello.o is not explicitly mentioned and thus is an intermediate file.
|
|
run_make_test(q!
|
|
all: hello.tsk
|
|
%.tsk: %.z ; @echo $@
|
|
%.z : %.x ; @echo $@
|
|
!,
|
|
'', "#MAKE#: Nothing to be done for 'all'.\n");
|
|
|
|
# subtest 2
|
|
# test.z is explicitly mentioned and thus is not an intermediate file.
|
|
# test.z is built first because until it's built we don't know if we
|
|
# need to rebuild the intermediate hello.z
|
|
run_make_test(q!
|
|
all: hello.tsk
|
|
%.tsk: %.z test.z ; @echo $@
|
|
%.z : %.x ; @echo $@
|
|
!,
|
|
'', "test.z\nhello.z\nhello.tsk\n");
|
|
|
|
# subtest 3
|
|
# hello.o is not explicitly mentioned and thus is an intermediate file.
|
|
run_make_test(q!
|
|
all: hello.tsk
|
|
dep:=%.o
|
|
%.tsk: $(dep) ; @echo $@
|
|
!,
|
|
'', "#MAKE#: Nothing to be done for 'all'.\n");
|
|
|
|
# subtest 4
|
|
# Even when test.z is constructed from 2 variables it is still explicitly
|
|
# mentioned and thus is not an intermediate file.
|
|
# test.z is built first because until it's built we don't know if we
|
|
# need to rebuild the intermediate hello.z
|
|
run_make_test(q!
|
|
all: hello.tsk
|
|
name:=test
|
|
suf:=.z
|
|
%.tsk: %.z $(name)$(suf) ; @echo $@
|
|
%.z: %.x ; @echo $@
|
|
!,
|
|
'', "test.z\nhello.z\nhello.tsk\n");
|
|
|
|
unlink('hello.x', 'test.x', 'hello.tsk');
|
|
|
|
# Test that chained pattern rules with multiple targets remove all intermediate
|
|
# files.
|
|
# sv 60435.
|
|
|
|
# subtest 1.
|
|
# a.1 and a.2 are intermediate and should be removed.
|
|
run_make_test(q!
|
|
a.4:
|
|
%.4: %.1 %.2 ; cat $^ >$@
|
|
%.1 %.2: ; touch $*.1 $*.2
|
|
!,
|
|
'', "touch a.1 a.2\ncat a.1 a.2 >a.4\nrm a.1 a.2");
|
|
|
|
unlink('a.4');
|
|
|
|
# subtest 2.
|
|
# a.1 and a.2 are intermediate and should be removed.
|
|
# a.3 is explicit and should not be removed.
|
|
run_make_test(q!
|
|
a.4:
|
|
%.4: %.1 %.2 a.3 ; cat $^ >$@
|
|
%.1 %.2: ; touch $*.1 $*.2
|
|
%.3: ; touch $@
|
|
!,
|
|
'', "touch a.3\ntouch a.1 a.2\ncat a.1 a.2 a.3 >a.4\nrm a.1 a.2");
|
|
|
|
unlink('a.3', 'a.4');
|
|
|
|
# subtest 3.
|
|
# a.1 and a.2 are intermediate and should be removed.
|
|
# a.3 is explicit and should not be removed.
|
|
run_make_test(q!
|
|
a.4:
|
|
%.4: %.1 %.2 a.3 ; cat $^ >$@
|
|
%.1 %.2 %.3: ; touch $*.1 $*.2 $*.3
|
|
!,
|
|
'', "touch a.1 a.2 a.3\ncat a.1 a.2 a.3 >a.4\nrm a.1 a.2");
|
|
|
|
unlink('a.3', 'a.4');
|
|
|
|
# subtest 4.
|
|
# a.1 and a.2 are intermediate and should be removed.
|
|
# a.3 is explicit and should not be removed.
|
|
run_make_test(q!
|
|
a.4:
|
|
%.4: %.1 %.2 a.3 ; cat $^ >$@
|
|
%.3 %.1 %.2: ; touch $*.1 $*.2 $*.3
|
|
!,
|
|
'', "touch a.1 a.2 a.3\ncat a.1 a.2 a.3 >a.4\nrm a.1 a.2");
|
|
|
|
unlink('a.3', 'a.4');
|
|
|
|
# subtest 5.
|
|
# a.1 and a.2 are intermediate and should be removed.
|
|
# a.3 is explicit and should not be removed.
|
|
run_make_test(q!
|
|
a.4:
|
|
%.4: a.3 %.1 %.2 ; cat $^ >$@
|
|
%.1 %.2 %.3: ; touch $*.1 $*.2 $*.3
|
|
!,
|
|
'', "touch a.1 a.2 a.3\ncat a.3 a.1 a.2 >a.4\nrm a.1 a.2");
|
|
|
|
unlink('a.3', 'a.4');
|
|
|
|
# subtest 6.
|
|
# a.2 is intermediate and should be removed.
|
|
# a.1 is mentioned explicitly on an unrelated rule and should not be removed.
|
|
run_make_test(q!
|
|
a.3:
|
|
%.3: %.1 %.2 ; cat $^ >$@
|
|
%.1 %.2: ; touch $*.1 $*.2
|
|
install: a.1
|
|
.PHONY: install
|
|
!,
|
|
'', "touch a.1 a.2\ncat a.1 a.2 >a.3\nrm a.2");
|
|
|
|
unlink('a.1', 'a.3');
|
|
|
|
# Test removal of intermediate files.
|
|
|
|
# subtest 1.
|
|
# hello.x is removed, because it is intermediate.
|
|
run_make_test(q!
|
|
hello.tsk:
|
|
%.tsk: %.x; touch $@
|
|
%.x: ; touch $@
|
|
!,
|
|
'', "touch hello.x\ntouch hello.tsk\nrm hello.x");
|
|
|
|
unlink('hello.tsk');
|
|
|
|
# subtest 2.
|
|
# Even though hello.x is intermediate, it is not removed, because it is not
|
|
# created.
|
|
touch('hello.x');
|
|
|
|
run_make_test(q!
|
|
hello.tsk:
|
|
%.tsk: %.x; touch $@
|
|
%.x: ; touch $@
|
|
!,
|
|
'', "touch hello.tsk");
|
|
|
|
unlink('hello.x', 'hello.tsk');
|
|
|
|
# subtest 2.
|
|
# Even though hello.x is intermediate, it is not removed, because it is not
|
|
# created.
|
|
run_make_test(q!
|
|
hello.tsk:
|
|
%.tsk: %.x; touch $@
|
|
%.x: ; : $@
|
|
!,
|
|
'', ": hello.x\ntouch hello.tsk");
|
|
|
|
unlink('hello.tsk');
|
|
|
|
# This tells the test driver that the perl test script executed properly.
|
|
1;
|