Documentation and tests for order-only prerequisites.
authorPaul Smith <psmith@gnu.org>
Tue, 9 Jul 2002 06:35:56 +0000 (06:35 +0000)
committerPaul Smith <psmith@gnu.org>
Tue, 9 Jul 2002 06:35:56 +0000 (06:35 +0000)
Add a new test suite for automatic variables.

AUTHORS
ChangeLog
NEWS
commands.c
doc/make.texi
file.c
read.c
tests/ChangeLog
tests/scripts/features/order_only
tests/scripts/variables/automatic [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index e3acf483f2637e12511c07bfbbfe297012d4caba..88d61c3033a55ff8a59a10bda127781750e358b8 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -47,6 +47,7 @@ Other contributors:
   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)
index 65ba46f99dba32e15fbcd96064e6d1859caafffc..97e88bc6b9dafc47362a23ba869b6ca25710a54e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,25 @@
+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>
 
@@ -22,7 +36,7 @@
        * 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.
diff --git a/NEWS b/NEWS
index 0237ae4c33195a55d71b7ac7c10b0dbbb4e15dad..4c7309317ab3d6613452a07fd8cc80a1120701ee 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,13 @@ reports.
 \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.
index 19a175e0063600fb5472644f182b4be2d32dd0a5..f6baefcb29c09d031eaccafee64502ecac32b837 100644 (file)
@@ -124,7 +124,7 @@ set_file_variables (file)
   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;
index 20fc1c826be45182e0b77181367aa4f39dfef369..6fac1148766c14b7bbbf6572e37bdb6fa5697516 100644 (file)
@@ -158,6 +158,7 @@ Writing Rules
 
 * 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.
@@ -1473,6 +1474,7 @@ the makefile (often with a target called @samp{all}).
 @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.
@@ -1524,7 +1526,7 @@ added to the prerequisites.
 @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
@@ -1593,7 +1595,49 @@ How to update is specified by @var{commands}.  These are lines to be
 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
diff --git a/file.c b/file.c
index 2602810b9b58317cecdb73d9819df29fd073fc36..1e87443a8877119a87e204981213b4e22bd24226 100644 (file)
--- a/file.c
+++ b/file.c
@@ -680,15 +680,30 @@ static void
 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)
diff --git a/read.c b/read.c
index 510266a0896dfaa05ae9c30f4f79cbd246750627..4b7c79c6a418c6b2c166bababf758f8a366a6c78 100644 (file)
--- a/read.c
+++ b/read.c
@@ -1524,10 +1524,17 @@ uniquize_deps (chain)
       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);
index aa5f78d1adccd1a53173a31230ee82328f39e26d..fec51861e0c886097149e3f369232badebf63d5a 100644 (file)
@@ -1,3 +1,11 @@
+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.
index 81284c5d10a93ef007572da9999a363516f79de3..e324d6812d0990f13f9f08e57f291f6f709d5bbb 100644 (file)
@@ -10,7 +10,6 @@ open(MAKEFILE,"> $makefile");
 print MAKEFILE <<'EOF';
 foo: bar | baz
        @echo '$$^ = $^'
-       @echo '$$? = $?'
        @echo '$$| = $|'
        touch $@
 
@@ -26,7 +25,7 @@ close(MAKEFILE);
 # 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));
 
 
@@ -47,7 +46,6 @@ open(MAKEFILE,"> $makefile2");
 print MAKEFILE <<'EOF';
 foo: bar | baz
        @echo '$$^ = $^'
-       @echo '$$? = $?'
        @echo '$$| = $|'
        touch $@
 
@@ -61,19 +59,54 @@ EOF
 
 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;
diff --git a/tests/scripts/variables/automatic b/tests/scripts/variables/automatic
new file mode 100644 (file)
index 0000000..b80d478
--- /dev/null
@@ -0,0 +1,50 @@
+#                                                                    -*-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;