Add a new test suite for automatic variables.
Jim Kelton <jim_kelton@tivoli.com>
David Lubbren <uhay@rz.uni-karlsruhe.de>
Tim Magill <tim.magill@telops.gte.com>
+ Greg McGary <greg@mcgary.org>
Han-Wen Nienhuys <hanwen@cs.uu.nl>
Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
Carl Staelin (Princeton University)
+2002-07-09 Paul D. Smith <psmith@gnu.org>
+
+ * doc/make.texi (Prerequisite Types): Add a new section describing
+ order-only prerequisites.
+
+ * read.c (uniquize_deps): If we have the same file as both a
+ normal and order-only prereq, get rid of the order-only prereq,
+ since the normal one supersedes it.
+
2002-07-08 Paul D. Smith <psmith@gnu.org>
+ * AUTHORS: Added Greg McGary to the AUTHORS file.
+ * NEWS: Blurbed order-only prerequisites.
+ * file.c (print_file): Show order-only deps properly when printing
+ the database.
+
* maintMakefile: Add "update" targets for wget'ing the latest
versions of various external files. Taken from Makefile.maint in
autoconf, etc.
- * dosbuild.bat: Somehow we got _extra_ ^M's. Remove them.
- Reported by Eli Zaretskii <eliz@is.elta.co.il>.
+ * dosbuild.bat: Somehow we got _double_ ^M's. Remove them.
+ Reported by Eli Zaretskii <eliz@is.elta.co.il>.
2002-07-07 Paul D. Smith <psmith@gnu.org>
* implicit.c (pattern_search): Some systems apparently run short
of stack space, and using alloca() in this function caused an
overrun. I modified it to use xmalloc() on the two variables
- which seemed like they might get large. Bug #476.
+ which seemed like they might get large. Fixes Bug #476.
* main.c (print_version): Update copyright notice to conform with
GNU standards.
\f
Version <next>
+* A new feature exists: order-only prerequisites. These prerequisites
+ affect the order in which targets are built, but they do not impact
+ the rebuild/no-rebuild decision of their dependents. That is to say,
+ they allow you to require target B be built before target A, without
+ requiring that target A will always be rebuilt if target B is updated.
+ Patch for this feature provided by Greg McGary <greg@mcgary.org>.
+
* A new function is defined: $(quote ...). The argument to this
function is the _name_ of a variable. The result of the function is
the value of the variable, without having been expanded.
DEFINE_VARIABLE ("@", 1, at);
DEFINE_VARIABLE ("%", 1, percent);
- /* Compute the values for $^, $+, and $?. */
+ /* Compute the values for $^, $+, $?, and $|. */
{
unsigned int qmark_len, plus_len, bar_len;
* Rule Example:: An example explained.
* Rule Syntax:: General syntax explained.
+* Prerequisite Types:: There are two types of prerequisites.
* Wildcards:: Using wildcard characters such as `*'.
* Directory Search:: Searching other directories for source files.
* Phony Targets:: Using a target that is not a real file's name.
@menu
* Rule Example:: An example explained.
* Rule Syntax:: General syntax explained.
+* Prerequisite Types:: There are two types of prerequisites.
* Wildcards:: Using wildcard characters such as `*'.
* Directory Search:: Searching other directories for source files.
* Phony Targets:: Using a target that is not a real file's name.
@end itemize
@end ifinfo
-@node Rule Syntax, Wildcards, Rule Example, Rules
+@node Rule Syntax, Prerequisite Types, Rule Example, Rules
@section Rule Syntax
@cindex rule syntax
executed by the shell (normally @samp{sh}), but with some extra features
(@pxref{Commands, ,Writing the Commands in Rules}).
-@node Wildcards, Directory Search, Rule Syntax, Rules
+@node Prerequisite Types, Wildcards, Rule Syntax, Rules
+@comment node-name, next, previous, up
+@section Types of Prerequisites
+@cindex prerequisite types
+@cindex types of prerequisites
+
+@cindex prerequisites, normal
+@cindex normal prerequisites
+@cindex prerequisites, order-only
+@cindex order-only prerequisites
+There are actually two different types of prerequisites understood by
+GNU @code{make}: normal prerequisites such as described in the
+previous section, and @dfn{order-only} prerequisites. A normal
+prerequisite actually makes two statements: first, it imposes an order
+of execution of build commands: any commands necessary to build any of
+a target's prerequisites will be fully executed before any commands
+necessary to build the target. Second, it imposes a dependency
+relationship: if any prerequisite is newer than the target, then the
+target is considered out-of-date and must be rebuilt.
+
+Normally, this is exactly what you want: if a target's prerequisite is
+updated, then the target should also be updated.
+
+Occasionally, however, you have a situation where you want to impose a
+specific ordering on the rules to be invoked @emph{without} forcing
+the target to be updated if one of those rules is executed. In that
+case, you want to define @dfn{order-only} prerequisites. Order-only
+prerequisites can be specified by placing a pipe symbol (@code{|})
+in the prerequisites list: any prerequisites to the left of the pipe
+symbol are normal; any prerequisites to the right are order-only:
+
+@example
+@var{targets} : @var{normal-prerequisites} | @var{order-only-prerequisites}
+@end example
+
+The normal prerequisites section may of course be empty. Also, you
+may still declare multiple lines of prerequisites for the same target:
+they are appended appropriately. Note that if you declare the same
+file to be both a normal and an order-only prerequisite, the normal
+prerequisite takes precedence (since they are a strict superset of the
+behavior of an order-only prerequisite).
+
+@node Wildcards, Directory Search, Prerequisite Types, Rules
@section Using Wildcard Characters in File Names
@cindex wildcard
@cindex file name with wildcards
print_file (f)
struct file *f;
{
- register struct dep *d;
+ struct dep *d;
+ struct dep *ood = 0;
putchar ('\n');
if (!f->is_target)
puts (_("# Not a target:"));
printf ("%s:%s", f->name, f->double_colon ? ":" : "");
+ /* Print all normal dependencies; note any order-only deps. */
for (d = f->deps; d != 0; d = d->next)
- printf (" %s", dep_name (d));
+ if (! d->ignore_mtime)
+ printf (" %s", dep_name (d));
+ else if (! ood)
+ ood = d;
+
+ /* Print order-only deps, if we have any. */
+ if (ood)
+ {
+ printf (" | %s", dep_name (ood));
+ for (d = ood->next; d != 0; d = d->next)
+ if (d->ignore_mtime)
+ printf (" %s", dep_name (d));
+ }
+
putchar ('\n');
if (f->precious)
last = d;
next = d->next;
while (next != 0)
- if (streq (dep_name (d), dep_name (next))
- && d->ignore_mtime == next->ignore_mtime)
+ if (streq (dep_name (d), dep_name (next)))
{
struct dep *n = next->next;
+ /* If ignore_mtimes are not equal, one of these is an order-only
+ prerequisite and one isn't. That means that we should remove
+ the one that isn't and keep the one that is. Ideally we'd
+ like to keep the normal one always but that's hard, and
+ probably not very important, so just remove the second one and
+ force the first one to be normal. */
+ if (d->ignore_mtime != next->ignore_mtime)
+ d->ignore_mtime = 0;
last->next = n;
if (next->name != 0 && next->name != d->name)
free (next->name);
+2002-07-09 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/automatic: Create a test for automatic variables.
+
+2002-07-08 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/order_only: Test new order-only prerequisites.
+
2002-07-07 Paul D. Smith <psmith@gnu.org>
* scripts/functions/eval: Test new function.
print MAKEFILE <<'EOF';
foo: bar | baz
@echo '$$^ = $^'
- @echo '$$? = $?'
@echo '$$| = $|'
touch $@
# TEST #1 -- just the syntax
&run_make_with_options($makefile, "", &get_logfile);
-$answer = "touch bar\ntouch baz\n\$^ = bar\n\$? = bar\n\$| = baz\ntouch foo\n";
+$answer = "touch bar\ntouch baz\n\$^ = bar\n\$| = baz\ntouch foo\n";
&compare_output($answer,&get_logfile(1));
print MAKEFILE <<'EOF';
foo: bar | baz
@echo '$$^ = $^'
- @echo '$$? = $?'
@echo '$$| = $|'
touch $@
close(MAKEFILE);
-# TEST #3 -- just the syntax
+# TEST #3 -- Make sure the order-only prereq was promoted to normal.
&run_make_with_options($makefile2, "", &get_logfile);
-$answer = "touch bar\ntouch baz\n\$^ = bar baz\n\$? = bar baz\n\$| = baz\ntouch foo\n";
+$answer = "touch bar\ntouch baz\n\$^ = bar baz\n\$| = \ntouch foo\n";
&compare_output($answer,&get_logfile(1));
-# TEST #2 -- now we do it again: baz is PHONY but foo should _NOT_ be updated
+# TEST #4 -- now we do it again
&run_make_with_options($makefile2, "", &get_logfile);
-$answer = "touch baz\$^ = bar baz\n\$? = baz\n\$| = baz\ntouch foo\n";
+$answer = "touch baz\n\$^ = bar baz\n\$| = \ntouch foo\n";
&compare_output($answer,&get_logfile(1));
unlink(qw(foo bar baz));
+# Test empty normal prereqs
+
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile3");
+
+print MAKEFILE <<'EOF';
+foo:| baz
+ @echo '$$^ = $^'
+ @echo '$$| = $|'
+ touch $@
+
+.PHONY: baz
+
+baz:
+ touch $@
+EOF
+
+close(MAKEFILE);
+
+# TEST #5 -- make sure the parser was correct.
+
+&run_make_with_options($makefile3, "", &get_logfile);
+$answer = "touch baz\n\$^ = \n\$| = baz\ntouch foo\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #6 -- now we do it again: this time foo won't be built
+
+&run_make_with_options($makefile3, "", &get_logfile);
+$answer = "touch baz\n";
+&compare_output($answer,&get_logfile(1));
+
+unlink(qw(foo baz));
+
1;
--- /dev/null
+# -*-perl-*-
+
+$description = "Test automatic variable setting.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+open(MAKEFILE, "> $makefile");
+print MAKEFILE "dir = $dir\n";
+print MAKEFILE <<'EOF';
+.SUFFIXES:
+.SUFFIXES: .x .y .z
+$(dir)/foo.x : baz.z $(dir)/bar.y baz.z
+ @echo '$$@ = $@, $$(@D) = $(@D), $$(@F) = $(@F)'
+ @echo '$$* = $*, $$(*D) = $(*D), $$(*F) = $(*F)'
+ @echo '$$< = $<, $$(<D) = $(<D), $$(<F) = $(<F)'
+ @echo '$$^ = $^, $$(^D) = $(^D), $$(^F) = $(^F)'
+ @echo '$$+ = $+, $$(+D) = $(+D), $$(+F) = $(+F)'
+ @echo '$$? = $?, $$(?D) = $(?D), $$(?F) = $(?F)'
+ touch $@
+
+$(dir)/bar.y baz.z : ; touch $@
+EOF
+close(MAKEFILE);
+
+# TEST #1 -- simple test
+# -------
+
+&touch(qw(foo.x baz.z));
+
+sleep(1);
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "touch $dir/bar.y
+\$\@ = $dir/foo.x, \$(\@D) = $dir, \$(\@F) = foo.x
+\$* = $dir/foo, \$(*D) = $dir, \$(*F) = foo
+\$< = baz.z, \$(<D) = ., \$(<F) = baz.z
+\$^ = baz.z $dir/bar.y, \$(^D) = . $dir, \$(^F) = baz.z bar.y
+\$+ = baz.z $dir/bar.y baz.z, \$(+D) = . $dir ., \$(+F) = baz.z bar.y baz.z
+\$? = $dir/bar.y, \$(?D) = $dir, \$(?F) = bar.y
+touch $dir/foo.x\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink(qw(foo.x bar.y baz.z));
+
+1;