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