summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDmitry Goncharov <dgoncharov@users.sf.net>2022-07-24 18:16:50 -0400
committerPaul Smith <psmith@gnu.org>2022-07-30 18:40:28 -0400
commit07eea3aa496184bb763b7306e9de6a40a94605c9 (patch)
treef0b5e2b330b6ef40627b7050738c603aec4cd79b /tests
parent16e14b4114c0c9cc14d15e818bf22588a79e39da (diff)
downloadmake-git-07eea3aa496184bb763b7306e9de6a40a94605c9.tar.gz
[SV 62706] Only second-expand targets that might be built
Second-expand only the prerequisites of the targets being built. Defer second-expanding the prerequisites of targets until we need to decide if they should be built. * NEWS: Mention the change in behavior. * doc/make.texi (Secondary Expansion): Document the new behavior. * src/filedef.h (struct file): Add flag snapped. (expand_deps): Declare a function to second expand the prerequisites of a target. * src/file.c (rehash_file): Merge flag snapped. (expand_deps): Remove qualifier static. Check flag snapped. (snap_deps): Remove the loop which performed second expansion for all targets. * src/remake.c (update_file_1): Second expand the prerequisites of the considered target. * tests/scripts/features/se_explicit: Add tests. * tests/scripts/features/se_implicit: Ditto. * tests/scripts/features/se_statpat: Ditto.
Diffstat (limited to 'tests')
-rw-r--r--tests/scripts/features/se_explicit203
-rw-r--r--tests/scripts/features/se_implicit67
-rw-r--r--tests/scripts/features/se_statpat127
3 files changed, 390 insertions, 7 deletions
diff --git a/tests/scripts/features/se_explicit b/tests/scripts/features/se_explicit
index 35418274..ee5a89de 100644
--- a/tests/scripts/features/se_explicit
+++ b/tests/scripts/features/se_explicit
@@ -299,4 +299,207 @@ all: bye.x
bye.x: $$(firstword bye.1;
!, '', "#MAKEFILE#:4: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+unlink('hello.tsk', 'test.o', 'bye.tsk', 'hello.o', 'hello.h', 'hello.q', 'bye.c', 'bye.o');
+
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the targets which
+# are not built.
+# Here, hello.tsk is built and its prerequisites are second expanded.
+# bye.tsk is not built and its prerequisites are not second expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Multipe rules per target.
+run_make_test(q!
+.SECONDEXPANSION:
+
+all: hello.tsk
+dep1:=hello.o
+dep2:=hello.h
+hello.tsk: $$(dep1)
+hello.tsk: $$(dep2); $(info $@ from $^)
+hello.o:; $(info $@)
+hello.h:; $(info $@)
+!, 'hello.tsk',
+"hello.h
+hello.o
+hello.tsk from hello.h hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Multiple targets per rule.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk bye.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Grouped targets.
+run_make_test(q!
+.SECONDEXPANSION:
+world.tsk: world.o $$(info 1 second expansion of $$@ prereqs)
+hello.tsk world.tsk &: hello.o $$(info 2 second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+world.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"2 second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+2 second expansion of world.tsk prereqs
+1 second expansion of world.tsk prereqs
+second expansion of world.o prereqs
+world.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Order only.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:| hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+bye.tsk:| bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+hello.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 1 rule per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk:: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 2 rules per targets.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: hello.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+hello.tsk:: hello.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+bye.tsk:: bye.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+bye.tsk:: bye.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+hello.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+hello.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+bye.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+bye.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+!, 'hello.tsk',
+"1 second expansion of hello.tsk prereqs
+1 second expansion of hello.o prereqs
+1 hello.o
+2 second expansion of hello.o prereqs
+2 hello.o
+1 hello.tsk from hello.o
+2 second expansion of hello.tsk prereqs
+2 hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Test that the prerequisites of 'hello.tsk' are second expanded once.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk hello.q
+hello.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+hello.q: hello.tsk $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+!, '',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+second expansion of hello.q prereqs
+hello.q from hello.tsk
+#MAKE#: Nothing to be done for 'all'.\n");
+
+# sv 62706.
+# Merge vpath file and local file.
+# Test that both sets of prerequisites from 'hello.c' rule and from
+# 'src/hello.c' rule are second expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+vpath hello.c src
+all: hello.c; $(info $@ from $^)
+hello.c: $$(info second expansion of hello.c prereqs); $(info 1 $@)
+src/hello.c: $$(info second expansion of src/hello.c prereqs); $(info 2 $@)
+!, '',
+"#MAKEFILE#:5: Recipe was specified for file 'hello.c' at #MAKEFILE#:5,
+#MAKEFILE#:5: but 'hello.c' is now considered the same file as 'src/hello.c'.
+#MAKEFILE#:5: Recipe for 'hello.c' will be ignored in favor of the one for 'src/hello.c'.
+second expansion of src/hello.c prereqs
+second expansion of hello.c prereqs
+2 src/hello.c
+all from src/hello.c
+#MAKE#: 'all' is up to date.\n");
+
+# sv 62706.
+# .DEFAULT.
+run_make_test(q!
+.SECONDEXPANSION:
+bye:=bye.c
+all: hello.o
+.DEFAULT: $$(info second expansion of prereqs of default recipe @ = $$@) ; $(info default recipe $@)
+!, '',
+"default recipe hello.o
+#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.1');
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:; cp hello.1 $@
+unrelated: $$(shell touch hello.1);
+!, '',
+"cp hello.1 hello.tsk
+cp: cannot stat 'hello.1': $ERR_no_such_file
+#MAKE#: *** [#MAKEFILE#:3: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is explicit.
+# .SECONDARY marks hello.x as intermediate.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+.SECONDARY: hello.x
+all: hello.x
+hello.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\n#MAKE#: Nothing to be done for 'all'.\n");
+
+
1;
diff --git a/tests/scripts/features/se_implicit b/tests/scripts/features/se_implicit
index e7d88468..58775631 100644
--- a/tests/scripts/features/se_implicit
+++ b/tests/scripts/features/se_implicit
@@ -292,8 +292,11 @@ all: hello.z
!, '', "hello.z\n");
# subtest 3.
-# hello.x is explicitly mentioned on an unrelated rule and thus is not an
-# intermediate file.
+# make is building hello.z and does not second expand the prerequisites of rule
+# 'unrelated: $$(dep)'. '$$(dep)' stays not expanded and 'hello.x' is never
+# entered to the database. Make considers 'hello.x' intermediate while building
+# 'hello.z'. Because 'hello.z' is present and 'hello.x' is missing and
+# 'hello.x' is intermediate, there is no need to rebuild 'hello.z'.
run_make_test(q!
.SECONDEXPANSION:
dep:=hello.x
@@ -301,7 +304,19 @@ all: hello.z
%.z: %.x; @echo $@
%.x: ;
unrelated: $$(dep)
-!, '', "hello.z\n");
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# subtest 4.
+# Just like subtest 3. $$(dep) is not second expanded. 'hello.x' is
+# intermediate.
+run_make_test(q!
+.SECONDEXPANSION:
+dep:=hello.x
+all: hello.z
+%.z: %.x; @echo $@
+%.x: ;
+%.q: $$(dep)
+!, '', "#MAKE#: Nothing to be done for 'all'.\n");
unlink('hello.z');
@@ -442,5 +457,51 @@ all: bye.x
%.x: $$(firstword %.1;
!, '', "#MAKE#: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the rules which are
+# not tried during implicit search.
+# Here, make tries rules '%.tsk: %.o' and '%.o' and their prerequisites are
+# second expanded.
+# Rules '%.bin: %.x' and '%.x:' are not used in implicit search for 'hello.tsk'
+# and 'hello.o' and their prerequisites are not expanded.
+run_make_test(q!
+.SECONDEXPANSION:
+%.bin: %.x $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+%.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+%.x: $$(info second expansion of $$@ prereqs); $(info $@)
+%.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, '-R hello.tsk',
+"second expansion of hello.o prereqs
+second expansion of hello.tsk prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk
+%.tsk: %.o; cp hello.1 $@
+hello.o:;
+%.q: $$(shell touch hello.1);
+!, '',
+"cp hello.1 hello.tsk
+cp: cannot stat 'hello.1': $ERR_no_such_file
+#MAKE#: *** [#MAKEFILE#:4: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is implicit.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+all: hello.tsk
+%.tsk: %.x; $(info $@)
+%.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\nhello.tsk\n#MAKE#: Nothing to be done for 'all'.\n");
+
# This tells the test driver that the perl test script executed properly.
1;
diff --git a/tests/scripts/features/se_statpat b/tests/scripts/features/se_statpat
index 17f9c348..616a1a85 100644
--- a/tests/scripts/features/se_statpat
+++ b/tests/scripts/features/se_statpat
@@ -91,11 +91,9 @@ baz.a.2
#
run_make_test(q!
.SECONDEXPANSION:
-foo$$bar: f%r: % $$*.1
- @echo '$*'
+foo$$bar: f%r: % $$*.1 ; @echo '$*'
-oo$$ba oo$$ba.1:
- @echo '$@'
+oo$$ba oo$$ba.1: ; @echo '$@'
!,
'', 'oo$ba
oo$ba.1
@@ -110,5 +108,126 @@ all: bye.x
bye.x: %.x: $$(firstword %.1;
!, '', "#MAKEFILE#:4: *** unterminated call to function 'firstword': missing ')'. Stop.", 512);
+#unlink('hello.tsk', 'bye.tsk', 'hello.o', 'hello.q', 'bye.o');
+
+# sv 62706.
+# Test that makes avoids second expanding prerequisites of the targets which
+# are not built.
+# Here, hello.tsk is built and its prerequisites are second expanded.
+# bye.tsk is not built and its prerequisites are not second expanded.
+
+# Static pattern rules.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Order only prereqs.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk: %.tsk:| %.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+bye.tsk: %.tsk:| %.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)
+hello.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:| $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 1 rule per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)
+hello.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+bye.o:: $$(info second expansion of $$@ prereqs); $(info $@)
+!, 'hello.tsk',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Double colon. 2 rules per target.
+run_make_test(q!
+.SECONDEXPANSION:
+hello.tsk:: %.tsk: %.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+hello.tsk:: %.tsk: %.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)
+bye.tsk:: %.tsk: %.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)
+hello.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+hello.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+bye.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)
+bye.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)
+!, 'hello.tsk',
+"1 second expansion of hello.tsk prereqs
+1 second expansion of hello.o prereqs
+1 hello.o
+2 second expansion of hello.o prereqs
+2 hello.o
+1 hello.tsk from hello.o
+2 second expansion of hello.tsk prereqs
+2 hello.tsk from hello.o
+#MAKE#: 'hello.tsk' is up to date.\n");
+
+# sv 62706.
+# Test that the prerequisites of 'hello.tsk' are second expanded once.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk hello.q
+hello.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+hello.o: $$(info second expansion of $$@ prereqs); $(info $@)
+hello.q: %.q: %.tsk $$(info second expansion of $$@ prereqs); $(info $@ from $^)
+!, '',
+"second expansion of hello.tsk prereqs
+second expansion of hello.o prereqs
+hello.o
+hello.tsk from hello.o
+second expansion of hello.q prereqs
+hello.q from hello.tsk
+#MAKE#: Nothing to be done for 'all'.\n");
+
+unlink('hello.1');
+
+# sv 62706.
+# No side effects from second expansion of unrelated rules.
+run_make_test(q!
+.SECONDEXPANSION:
+all: hello.tsk
+hello.tsk: %.tsk: %.o; cp hello.1 $@
+hello.o:;
+bye.tsk: %.tsk: $$(shell touch hello.1);
+!, '',
+"cp hello.1 hello.tsk
+cp: cannot stat 'hello.1': $ERR_no_such_file
+#MAKE#: *** [#MAKEFILE#:4: hello.tsk] Error 1\n", 512);
+
+# sv 62706.
+# Second expansion of intermediate prerequisites.
+# The rule to build hello.x is static pattern.
+# .SECONDARY marks hello.x as intermediate.
+# Test that $$(deps) is secondary expanded.
+run_make_test(q!
+deps:=hello.h
+.SECONDEXPANSION:
+.SECONDARY: hello.x
+all: hello.x
+hello.x: %.x: $$(deps); $(info $@)
+hello.h:; $(info $@)
+!, '', "hello.h\nhello.x\n#MAKE#: Nothing to be done for 'all'.\n");
+
# This tells the test driver that the perl test script executed properly.
1;