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.
mentioned in other targets as "ought to exist".
Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>
+* GNU make was performing secondary expansion of all targets, even targets
+ which didn't need to be considered during the build. In this release
+ only targets which are considered will be secondarily expanded.
+ Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>
+
* If the MAKEFLAGS variable is modified in a makefile, it will be re-parsed
immediately rather than after all makefiles have been read. Note that
although all options are parsed immediately, some special effects won't
@code{.SECONDEXPANSION} must be defined before the first prerequisite
list that makes use of this feature.
-If that special target is defined then in between the two phases
-mentioned above, right at the end of the read-in phase, all the
-prerequisites of the targets defined after the special target are
-expanded a @emph{second time}. In most circumstances this secondary
-expansion will have no effect, since all variable and function
-references will have been expanded during the initial parsing of the
-makefiles. In order to take advantage of the secondary expansion
-phase of the parser, then, it's necessary to @emph{escape} the
-variable or function reference in the makefile. In this case the
-first expansion merely un-escapes the reference but doesn't expand it,
-and expansion is left to the secondary expansion phase. For example,
-consider this makefile:
+If @code{.SECONDEXPANSION} is defined then when GNU @code{make} needs to check
+the prerequisites of a target, the prerequisites are expanded a @emph{second
+time}. In most circumstances this secondary expansion will have no effect,
+since all variable and function references will have been expanded during the
+initial parsing of the makefiles. In order to take advantage of the secondary
+expansion phase of the parser, then, it's necessary to @emph{escape} the
+variable or function reference in the makefile. In this case the first
+expansion merely un-escapes the reference but doesn't expand it, and expansion
+is left to the secondary expansion phase. For example, consider this
+makefile:
@example
.SECONDEXPANSION:
MERGE (secondary);
MERGE (notintermediate);
MERGE (ignore_vpath);
+ MERGE (snapped);
#undef MERGE
to_file->builtin = 0;
return deps;
}
-/* Expand and parse each dependency line. */
-static void
+/* Expand and parse each dependency line.
+ For each dependency of the file, make the 'struct dep' point
+ at the appropriate 'struct file' (which may have to be created). */
+void
expand_deps (struct file *f)
{
struct dep *d;
const char *fstem;
int initialized = 0;
- f->updating = 0;
+ if (f->snapped)
+ return;
+ f->snapped = 1;
/* Walk through the dependencies. For any dependency that needs 2nd
expansion, expand it then insert the result into the list. */
set_file_variables (f, d->stem ? d->stem : f->stem);
+ /* Perform second expansion. */
p = variable_expand_for_file (d->name, f);
/* Free the un-expanded name. */
}
}
-/* For each dependency of each file, make the 'struct dep' point
- at the appropriate 'struct file' (which may have to be created).
-
- Also mark the files depended on by .PRECIOUS, .PHONY, .SILENT,
+/* Mark the files depended on by .PRECIOUS, .PHONY, .SILENT,
and various other special targets. */
void
longer define new targets. */
snapped_deps = 1;
- /* Perform second expansion and enter each dependency name as a file. We
- must use hash_dump() here because within these loops we likely add new
- files to the table, possibly causing an in-situ table expansion.
-
- We only need to do this if second_expansion has been defined; if it
- hasn't then all deps were expanded as the makefile was read in. If we
- ever change make to be able to unset .SECONDARY_EXPANSION this will have
- to change. */
-
- if (second_expansion)
- {
- struct file **file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
- struct file **file_end = file_slot_0 + files.ht_fill;
- struct file **file_slot;
- const char *suffixes;
-
- /* Expand .SUFFIXES: its prerequisites are used for $$* calc. */
- f = lookup_file (".SUFFIXES");
- suffixes = f ? f->name : 0;
- for (; f != 0; f = f->prev)
- expand_deps (f);
-
- /* For every target that's not .SUFFIXES, expand its prerequisites. */
-
- for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
- for (f = *file_slot; f != 0; f = f->prev)
- if (f->name != suffixes)
- expand_deps (f);
- free (file_slot_0);
- }
-
/* Now manage all the special targets. */
for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev)
diagnostics has been issued (dontcare). */
unsigned int was_shuffled:1; /* Did we already shuffle 'deps'? used when
--shuffle passes through the graph. */
+ unsigned int snapped:1; /* True if the deps of this file have been
+ secondary expanded. */
};
struct file *enter_file (const char *name);
struct dep *split_prereqs (char *prereqstr);
struct dep *enter_prereqs (struct dep *prereqs, const char *stem);
+void expand_deps (struct file *f);
struct dep *expand_extra_prereqs (const struct variable *extra);
void remove_intermediates (int sig);
void snap_deps (void);
{
struct dep *lastd = 0;
+ /* Perform second expansion and enter each dependency name as a file.
+ We only need to do this if second_expansion has been defined; if it
+ hasn't then all deps were expanded as the makefile was read in. */
+ if (second_expansion)
+ expand_deps (ad->file);
+
/* Find the deps we're scanning */
du = ad->file->deps;
ad = ad->next;
}
ld = 0;
+ /* Perform second expansion and enter each dependency name as a file.
+ We only need to do this if second_expansion has been defined; if it
+ hasn't then all deps were expanded as the makefile was read in. */
+ if (second_expansion)
+ expand_deps (file);
+
d = file->deps;
while (d != 0)
{
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;
!, '', "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
%.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');
%.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;
#
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
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;