on 05.07.19 at 23:44 Martin Dorey wrote:

... Sadly, though, adding all these things to the dependency list
won't really help me.  We installed this system just three days ago,
yet the mtime on stdio.h is months ago:

devadmin@ch-ep1-3:~$ ls -l /usr/include/stdio.h
-rw-r--r-- 1 root root 31494 Feb  6 21:17 /usr/include/stdio.h
devadmin@ch-ep1-3:~$

That dates from when upstream built the package that included it:

https://metadata.ftp-master.debian.org/changelogs//main/g/glibc/glibc_2.24-11+deb9u4_changelog

Yes, that's unfortunate, and the only generic fix would be
checksum-based dependencies. Decent SCMs like git are also quite helpful
in tackling this issue, see
https://git.wiki.kernel.org/index.php/GitFaq#Why_isn.27t_Git_preserving_modification_time_on_files.3F


If you decide to press on, then I have three minor suggestions:

> the newly introduced GNU Make’s $(filter ) function

The revision history for make.texi shows that $(filter) was added some
three decades ago:

rol...@redhat.com  9f8301ae1ac6d9076e38ec86f12d59ba40b851bd:Revision
1.2  1988/04/23 16:16:04  roland
...
rol...@redhat.com  9f8301ae1ac6d9076e38ec86f12d59ba40b851bd:* Added
the `filter', `filter-out', `strip' and `join' expansion functions.

https://www.gnu.org/software/make/manual/html_node/Features.html#Features 
suggests
that this function was an innovation of GNU make, true, but I found
"newly introduced" misleading.  I'm a native English speaker.
Yes, that's misleading: The "newly introduced" was meant to emphasize
that a $(filter) function was added compared to the previous example,
but you are right, it does more bad than good.

> gcc -o $ $(filter %.o, $^)

You've put a space after the comma.  I wouldn't do that in a Makefile,
though I would in every other programming language.
https://www.gnu.org/software/make/manual/html_node/Text-Functions.html#Text-Functions
 mostly
wouldn't have that space either.  $(filter) is one of those
word-oriented functions where I don't think it would matter, but it's
easier to have simple rules of thumb that keep you safe.  One of the
spaces after a comma here is important:

martind@swiftboat:~/tmp/warlich-2019-07-05$ cat Makefile
INPUT = a.o b.o
fn = $(1)
OUTPUT = $(call fn, $(filter-out %.o, $(INPUT)))
$(if $(OUTPUT),$(error :$(OUTPUT): is non-empty!))
martind@swiftboat:~/tmp/warlich-2019-07-05$ make
Makefile:4: *** : : is non-empty!.  Stop.
martind@swiftboat:~/tmp/warlich-2019-07-05$

> depenency
> conviniently
> reciepe

Spelling.

Thanks for your suggestions, I'm happy to include them all (patch
attached), together with some other doc fixes (hopefully) improving the
grammer.


From 5d647da46a3a1c41cc547caa75f6d8fe318d102e Mon Sep 17 00:00:00 2001
From: Christof Warlich <cwarl...@gmx.de>
Date: Fri, 5 Jul 2019 10:51:54 +0200
Subject: [PATCH 1/2] Add support for dependency-only prerequisites.

---
 doc/make.texi  | 76 ++++++++++++++++++++++++++++++++++++++++++++++----
 src/commands.c |  8 +++---
 src/dep.h      |  3 +-
 src/file.c     | 56 +++++++++++++++++++++++++++++++++++--
 src/main.c     |  1 +
 src/makeint.h  |  1 +
 6 files changed, 132 insertions(+), 13 deletions(-)

diff --git a/doc/make.texi b/doc/make.texi
index 12f70c6..9e58802 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -155,7 +155,7 @@ Writing Rules

 * Rule Example::                An example explained.
 * Rule Syntax::                 General syntax explained.
-* Prerequisite Types::          There are two types of prerequisites.
+* Prerequisite Types::          There are three 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.
@@ -1883,7 +1883,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.
+* Prerequisite Types::          There are three 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.
@@ -2022,10 +2022,13 @@ extra features (@pxref{Recipes, ,Writing Recipes in Rules}).
 @cindex normal prerequisites
 @cindex prerequisites, order-only
 @cindex order-only prerequisites
-There are actually two different types of prerequisites understood by
+There are actually three 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 makes two statements: first, it imposes an order in which
+previous section, @dfn{order-only} prerequisites, and @dfn{dependency-only}
+prerequisites.
+
+A normal prerequisite makes two statements:
+first, it imposes an order in which
 recipes will be invoked: the recipes for all prerequisites of a target
 will be completed before the recipe for the target is run.  Second, it
 imposes a dependency relationship: if any prerequisite is newer than
@@ -2085,6 +2088,69 @@ Now the rule to create the @file{objdir} directory will be run, if
 needed, before any @samp{.o} is built, but no @samp{.o} will be built
 because the @file{objdir} directory timestamp changed.

+Finally, the third type of prerequisites, i.e. depenency-only
+prerequisites, may be specified by placing a "smaller than" symbol
+(@code{<}) in the prerequisite list: any prerequisites to the left
+of the "smaller than" symbol are normal (or order-only); any prerequisites
+to the right are dependency-only (and possibly order-only as well).
+
+Dependency-only prerequisites behave almost identical to the other
+two prerequisite types, with one important exception: They do not
+contribute to any of their list-type related automatic variables.
+Thus, dependency-only prerequisites are not added to neither
+of the automatic variable lists $^, $+, $?, $*, $(^F), $(+F), $(?F),
+$(*F), $(^D), $(+D), $(?D) and $(*D), and prerequisites that are both
+dependency-only and order-only are not added to neither of the
+automatic variable lists $|, $(|F), $(|D).
+
+The rationale behind dependency-only dependencies is to make it more
+easy to extend dependency lists of existing Makefiles. An example may
+illustrate this:
+
+The following code may be considered as a snippet of a large and
+maybe rather complex Makefile:
+
+@example
+myappl: main.o file1.o file2.o
+	gcc -o $@ $^
+@end example
+
+At a first glance, it lists all the relevant prerequisites, but a
+second thought reveals that this is just not true: The target
+certainly also depends on the compiler frontend, the linker backend
+and the Makefile itself.
+
+Thus, a more complete snippet should look more like this:
+
+@example
+myappl: main.o file1.o file2.o /usr/bin/gcc /usr/bin/ld Makefile
+	gcc -o $@ $(filter %.o, $^)
+@end example
+
+Please note the need for the newly introduced GNU Make's $(filter )
+function besides the additional prerequisites.
+
+But for big projects, say the Linux kernel or a toolchain build,
+it would be rather laborious to change and fix all the Makefiles
+accordingly, and it would be more than questionable if such patches
+would be welcomed by every project. Fortunately, with dependency-only
+prerequisites at hand, the upstream Makefiles do not need to be
+changed at all. Instead, it's sufficient to list the additional
+dependencies as dependency-only prerequisites in another Makefile
+that just includes the upstream Makefile. To continue with our
+example (and assuming the related upstream Makefile was just called
+@code{Makefile}, we could most conviniently add a @code{GNUmakefile}
+with the following content:
+
+@example
+include Makefile
+myappl: < /usr/bin/gcc /usr/bin/ld Makefile
+@end example
+
+Calling @code{make} now would prefer @code{GNUmakefile} over
+@code{Makefile}, thus respecting the additional prerequisites
+without affecting the related reciepe.
+
 @node Wildcards, Directory Search, Prerequisite Types, Rules
 @section Using Wildcard Characters in File Names
 @cindex wildcard
diff --git a/src/commands.c b/src/commands.c
index dd47851..7c08c01 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -178,7 +178,7 @@ set_file_variables (struct file *file)
     bar_len = 0;
     for (d = file->deps; d != 0; d = d->next)
       {
-        if (!d->need_2nd_expansion)
+        if (!d->need_2nd_expansion && !d->ignore_automatic_vars)
           {
             if (d->ignore_mtime)
               bar_len += strlen (dep_name (d)) + 1;
@@ -200,7 +200,7 @@ set_file_variables (struct file *file)

     qmark_len = plus_len + 1;   /* Will be this or less.  */
     for (d = file->deps; d != 0; d = d->next)
-      if (! d->ignore_mtime && ! d->need_2nd_expansion)
+      if (! d->ignore_mtime && ! d->need_2nd_expansion && ! d->ignore_automatic_vars)
         {
           const char *c = dep_name (d);

@@ -247,7 +247,7 @@ set_file_variables (struct file *file)

     for (d = file->deps; d != 0; d = d->next)
       {
-        if (d->need_2nd_expansion)
+        if (d->need_2nd_expansion || d->ignore_automatic_vars)
           continue;

         slot = hash_find_slot (&dep_hash, d);
@@ -269,7 +269,7 @@ set_file_variables (struct file *file)
       {
         const char *c;

-        if (d->need_2nd_expansion || hash_find_item (&dep_hash, d) != d)
+        if (d->need_2nd_expansion || d->ignore_automatic_vars || hash_find_item (&dep_hash, d) != d)
           continue;

         c = dep_name (d);
diff --git a/src/dep.h b/src/dep.h
index baa64df..bedf41a 100644
--- a/src/dep.h
+++ b/src/dep.h
@@ -48,7 +48,8 @@ struct nameseq
     unsigned short changed : 1;                 \
     unsigned short ignore_mtime : 1;            \
     unsigned short staticpattern : 1;           \
-    unsigned short need_2nd_expansion : 1
+    unsigned short need_2nd_expansion : 1;      \
+    unsigned short ignore_automatic_vars : 1

 struct dep
   {
diff --git a/src/file.c b/src/file.c
index c20fcf8..f624836 100644
--- a/src/file.c
+++ b/src/file.c
@@ -442,17 +442,41 @@ remove_intermediates (int sig)
 struct dep *
 split_prereqs (char *p)
 {
-  struct dep *new = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE, NULL,
+  struct dep *new = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE|MAP_DEP, NULL,
                                     PARSEFS_NONE);

-  if (*p)
+  if (*p == '<')
+    {
+      /* Files that follow '<' are "dependency-only" prerequisites that do not
+         contribute to the automatic variables $^, $+, $*, $? and their
+         $(xF) and $(xD) counterparts.  */
+      struct dep *dod;
+
+      ++p;
+      dod = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE, NULL, PARSEFS_NONE);
+
+      if (! new)
+        new = dod;
+      else
+        {
+          struct dep *dp;
+          for (dp = new; dp->next != NULL; dp = dp->next)
+            ;
+          dp->next = dod;
+        }
+
+      for (; dod != NULL; dod = dod->next)
+        dod->ignore_automatic_vars = 1;
+    }
+
+  if (*p == '|')
     {
       /* Files that follow '|' are "order-only" prerequisites that satisfy the
          dependency by existing: their modification times are irrelevant.  */
       struct dep *ood;

       ++p;
-      ood = PARSE_SIMPLE_SEQ (&p, struct dep);
+      ood = PARSE_FILE_SEQ (&p, struct dep, MAP_DEP, NULL, PARSEFS_NONE);

       if (! new)
         new = ood;
@@ -468,6 +492,32 @@ split_prereqs (char *p)
         ood->ignore_mtime = 1;
     }

+  if (*p)
+    {
+      /* Files that follow '<' and '|' are "dependency-only" and "order-only" prerequisites,
+         their modification times are irrelevant and they do not contribute to the automatic variable $|.  */
+      struct dep *ood_dod;
+
+      ++p;
+      ood_dod = PARSE_SIMPLE_SEQ (&p, struct dep);
+
+      if (! new)
+        new = ood_dod;
+      else
+        {
+          struct dep *dp;
+          for (dp = new; dp->next != NULL; dp = dp->next)
+            ;
+          dp->next = ood_dod;
+        }
+
+      for (; ood_dod != NULL; ood_dod = ood_dod->next)
+        {
+          ood_dod->ignore_automatic_vars = 1;
+          ood_dod->ignore_mtime = 1;
+        }
+    }
+
   return new;
 }

diff --git a/src/main.c b/src/main.c
index afc7fd9..c3fe228 100644
--- a/src/main.c
+++ b/src/main.c
@@ -637,6 +637,7 @@ initialize_stopchar_map (void)
   stopchar_map[(int)'='] = MAP_EQUALS;
   stopchar_map[(int)':'] = MAP_COLON;
   stopchar_map[(int)'|'] = MAP_PIPE;
+  stopchar_map[(int)'<'] = MAP_DEP;
   stopchar_map[(int)'.'] = MAP_DOT | MAP_USERFUNC;
   stopchar_map[(int)','] = MAP_COMMA;
   stopchar_map[(int)'('] = MAP_VARSEP;
diff --git a/src/makeint.h b/src/makeint.h
index dd6e894..2d38efc 100644
--- a/src/makeint.h
+++ b/src/makeint.h
@@ -402,6 +402,7 @@ extern int unixy_shell;
 #define MAP_PIPE        0x0100
 #define MAP_DOT         0x0200
 #define MAP_COMMA       0x0400
+#define MAP_DEP         0x0800

 /* These are the valid characters for a user-defined function.  */
 #define MAP_USERFUNC    0x2000
--
2.17.1

From 3bcb737d5a64288f2c6ff264ac7def698f17f6ce Mon Sep 17 00:00:00 2001
From: Christof Warlich <cwarl...@gmx.de>
Date: Sat, 6 Jul 2019 10:18:19 +0200
Subject: [PATCH 2/2] Fix documentation for dependency-only prerequisites.

---
 doc/make.texi | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/doc/make.texi b/doc/make.texi
index 9e58802..df9f6b0 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -2088,7 +2088,7 @@ Now the rule to create the @file{objdir} directory will be run, if
 needed, before any @samp{.o} is built, but no @samp{.o} will be built
 because the @file{objdir} directory timestamp changed.

-Finally, the third type of prerequisites, i.e. depenency-only
+Finally, the third type of prerequisites, i.e. dependency-only
 prerequisites, may be specified by placing a "smaller than" symbol
 (@code{<}) in the prerequisite list: any prerequisites to the left
 of the "smaller than" symbol are normal (or order-only); any prerequisites
@@ -2096,19 +2096,19 @@ to the right are dependency-only (and possibly order-only as well).

 Dependency-only prerequisites behave almost identical to the other
 two prerequisite types, with one important exception: They do not
-contribute to any of their list-type related automatic variables.
-Thus, dependency-only prerequisites are not added to neither
+contribute to any of their list-type automatic variables.
+Thus, dependency-only prerequisites are not added to any
 of the automatic variable lists $^, $+, $?, $*, $(^F), $(+F), $(?F),
 $(*F), $(^D), $(+D), $(?D) and $(*D), and prerequisites that are both
-dependency-only and order-only are not added to neither of the
-automatic variable lists $|, $(|F), $(|D).
+dependency-only and order-only are not added to the
+automatic variable list $|.

-The rationale behind dependency-only dependencies is to make it more
-easy to extend dependency lists of existing Makefiles. An example may
+The rationale behind dependency-only dependencies is to make it easier
+to extend dependency lists of existing Makefiles. An example can
 illustrate this:

 The following code may be considered as a snippet of a large and
-maybe rather complex Makefile:
+possibly rather complex Makefile:

 @example
 myappl: main.o file1.o file2.o
@@ -2117,29 +2117,29 @@ myappl: main.o file1.o file2.o

 At a first glance, it lists all the relevant prerequisites, but a
 second thought reveals that this is just not true: The target
-certainly also depends on the compiler frontend, the linker backend
+also depends on the compiler frontend, the linker backend
 and the Makefile itself.

 Thus, a more complete snippet should look more like this:

 @example
 myappl: main.o file1.o file2.o /usr/bin/gcc /usr/bin/ld Makefile
-	gcc -o $@ $(filter %.o, $^)
+	gcc -o $@ $(filter %.o,$^)
 @end example

-Please note the need for the newly introduced GNU Make's $(filter )
-function besides the additional prerequisites.
+Please note the need for GNU Make's $(filter) function besides the
+additional prerequisites.

 But for big projects, say the Linux kernel or a toolchain build,
 it would be rather laborious to change and fix all the Makefiles
-accordingly, and it would be more than questionable if such patches
+accordingly, and it is be more than questionable if such patches
 would be welcomed by every project. Fortunately, with dependency-only
 prerequisites at hand, the upstream Makefiles do not need to be
-changed at all. Instead, it's sufficient to list the additional
+changed at all. Instead, it is sufficient to list the additional
 dependencies as dependency-only prerequisites in another Makefile
-that just includes the upstream Makefile. To continue with our
+that simply includes the upstream Makefile. To continue with our
 example (and assuming the related upstream Makefile was just called
-@code{Makefile}, we could most conviniently add a @code{GNUmakefile}
+@code{Makefile}) we could most conveniently add a @code{GNUmakefile}
 with the following content:

 @example
@@ -2149,7 +2149,7 @@ myappl: < /usr/bin/gcc /usr/bin/ld Makefile

 Calling @code{make} now would prefer @code{GNUmakefile} over
 @code{Makefile}, thus respecting the additional prerequisites
-without affecting the related reciepe.
+without affecting the related recipe.

 @node Wildcards, Directory Search, Prerequisite Types, Rules
 @section Using Wildcard Characters in File Names
--
2.17.1

_______________________________________________
Bug-make mailing list
Bug-make@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-make

Reply via email to