make/tests/scripts/features/grouped_targets
Paul Smith fabb03eac4 [SV 12078, SV 62809] Rebuild grouped targets if any is missing
If any of a set of grouped targets is missing or out of date, even
if make is not trying to build that target, rebuild them all.
Ensure this is true for explicit grouped targets as well as pattern
rule grouped targets.

Original patch by Jonathan Gravel <jo@stashed.dev>

* src/remake.c (update_file_1): After matching any pattern rules,
go through the also_make targets and set noexist as needed.  Also
compute the oldest this_mtime.
* tests/scripts/features/grouped_targets: Add regression tests.
* tests/scripts/features/patternrules: Ditto.
* tests/features/vpath: Rewrite to use modern run_make_test().
Add a test that we check for VPATH before implicit rule search.
Move the tests in vpath2 and vpath3 into this suite.
* tests/features/vpathplus: Rewrite to use modern run_make_test().
2022-09-20 03:55:39 -04:00

207 lines
4.2 KiB
Perl

# -*-perl-*-
$description = "This test is about grouped multiple targets indicated by &:";
$details = "Here we test for requirements like\n"
."- if multiple such targets are updated, the recipe is run once\n"
."- parsing issues related to the &: syntax itself\n";
# Parsing: &: allowed without any targets.
run_make_test(q{
.PHONY: all
&:;
all: ;@printf ''
},
'', "");
# Parsing: &: works not preceded by whitespace.
run_make_test(q{
foo&:;@echo foo
},
'foo', "foo");
# Ordinary rule runs recipe four times for t1 t2 t3 t4.
# Grouped target rule runs recipe once; others are considered updated.
run_make_test(q{
.PHONY: t1 t2 t3 t4 g1 g2 g3 g4
t1 t2 t3 t4: ; @echo $@
g1 g2 g3 g4 &: ; @echo $@
},
't1 t2 t3 t4 g1 g2 g3 g4',
"t1\n"
."t2\n"
."t3\n"
."t4\n"
."g1\n"
."#MAKE#: Nothing to be done for 'g2'.\n"
."#MAKE#: Nothing to be done for 'g3'.\n"
."#MAKE#: Nothing to be done for 'g4'.");
# Similar to previous test, but targets come from m1 phony
# rather than from the command line. We don't see "Nothing to
# be done for" messages. Also, note reversed order g4 g3 ...
# Thus the auto variable $@ is "g4" when that rule fires.
run_make_test(q{
.PHONY: m1 t1 t2 t3 t4 g1 g2 g3 g4
m1: t1 t2 t3 t4 g4 g3 g2 g1
t1 t2 t3 t4: ; @echo $@
g1 g2 g3 g4&: ; @echo $@
},
'',
"t1\nt2\nt3\nt4\ng4");
# Set a grouped target recipe for existing targets
run_make_test(q{
.PHONY: M a b
M: a b
a:
a b&: ; @echo Y
b:
},
'',
"Y");
# grouped targets require a recipe
run_make_test(q{
.PHONY: M a b
M: a b
a b&:
},
'',
"#MAKEFILE#:4: *** grouped targets must provide a recipe. Stop.", 512);
# Pattern rules use grouped targets anyway so it's a no-op
run_make_test(q{
.PHONY: M
M: a.q b.q
a.% b.%&: ; @echo Y
},
'',
"Y");
# Double-colon grouped target rules.
run_make_test(q{
.PHONY: M a b c d e f g h
M: a b
a b c&:: ; @echo X
c d e&:: ; @echo Y
f g h&:: ; @echo Z
},
'',
"X");
run_make_test(q{
.PHONY: M a b c d e f g h
M: c
a b c&:: ; @echo X
c d e&:: ; @echo Y
f g h&:: ; @echo Z
},
'',
"X\nY");
run_make_test(q{
.PHONY: M a b c d e f g h
M: a b c d e
a b c&:: ; @echo X
c d e&:: ; @echo Y
f g h&:: ; @echo Z
},
'',
"X\nY");
run_make_test(q{
.PHONY: M a b c d e f g h
M: d e
a b c&:: ; @echo X
c d e&:: ; @echo Y
f g h&:: ; @echo Z
},
'',
"Y");
run_make_test(q{
.PHONY: M a b c d e f g h
M: f g h
a b c&:: ; @echo X
c d e&:: ; @echo Y
f g h&:: ; @echo Z
},
'',
"Z");
# sv 60188.
# Test that a file explicitly mentioned by the user and made by an implicit
# rule is not considered intermediate.
touch('hello.z');
touch('hello.q');
# subtest 1
# hello.x is not explicitly mentioned and thus is an intermediate file.
run_make_test(q!
all: hello.z
%.z %.q: %.x ; touch $*.z $*.q
%.x: ;
!, '', "#MAKE#: Nothing to be done for 'all'.\n");
# subtest 2
# test.x is explicitly mentioned and thus is not an intermediate file.
run_make_test(q!
all: hello.z
%.z %.q: %.x test.x ; @echo $*.z $*.q
%.x: ;
!, '', "hello.z hello.q\n");
# subtest 3
# hello.x is explicitly mentioned on an unrelated rule and thus is not an
# intermediate file.
run_make_test(q!
all: hello.z
%.z %.q: %.x; @echo $*.z $*.q
%.x: ;
unrelated: hello.x
!, '', "hello.z hello.q\n");
unlink('hello.z');
unlink('hello.q');
# SV 62809: Missing grouped target peer causes remake regardless of which
# target caused the rule to run.
touch(qw(gta)); # but not gtb
run_make_test(q!
gta gtb &: ; touch gta gtb
!,
'gta', "touch gta gtb\n");
unlink(qw(gta gtb));
# Ensure both goal targets are built if they depend on a grouped prereq
touch(qw(gta)); # but not gtb
run_make_test(q!
x1 x2: ; touch $@
x1: gta
x2: gtb
gta gtb &: ; touch gta gtb
!,
'x1 x2', "touch gta gtb\ntouch x1\ntouch x2\n");
# Now everything should be up to date
run_make_test(undef, 'x1 x2',
"#MAKE#: 'x1' is up to date.\n#MAKE#: 'x2' is up to date.");
unlink(qw(x1 x2 gta gtb));
# If an also-make file is older than a prerequisite build both
utouch(-20, 'gtb');
utouch(-10, 'pre');
touch(qw(gta));
run_make_test(q!
gta gtb &: pre ; touch gta gtb
!,
'gta', "touch gta gtb\n");
unlink(qw(pre gta gtb));
# This tells the test driver that the perl test script executed properly.
1;