> The target certainly also depends on the compiler frontend, the linker 
> backend and the Makefile itself

It's unimaginable that it doesn't depend on compiler libraries and myriad 
compiler-provided header files too.  Using header files in a compilation 
example would make the $(filter ...) solution less tenable, strengthening your 
case.  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

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.

> 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.

________________________________
From: Bug-make <bug-make-bounces+martin.dorey=hds....@gnu.org> on behalf of 
Christof Warlich <cwarl...@gmx.de>
Sent: Thursday, July 4, 2019 10:13
To: bug-make@gnu.org
Subject: Feature request / patch: dependency-only prerequisites

***** EXTERNAL EMAIL *****

Dear all,

please bear with me if I'm doing something wrong here, this is the first time 
that I'm trying to contribute to GNU Make.

The attached patch would add a minor (but imho useful) feature to GNU Make. 
Here is an extract of the (changed) documentation (changes are in red), giving 
a quite comprehensive idea as to why this feature would be useful:

4.3 Types of Prerequisites

There are actually three different types of prerequisites understood by GNU 
make: normal prerequisites such as described in the previous section, 
order-only prerequisites, and 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 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 without forcing the target to be updated if 
one of those rules is executed. In that case, you want to define order-only 
prerequisites. Order-only prerequisites can be specified by placing a pipe 
symbol (|) in the prerequisites list: any prerequisites to the left of the pipe 
symbol are normal; any prerequisites to the right are order-only:

targets : normal-prerequisites | order-only-prerequisites


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 (normal prerequisites are appended to the list of normal 
prerequisites; order-only prerequisites are appended to the list of order-only 
prerequisites). 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 have a strict superset of the behavior of an order-only prerequisite).

Consider an example where your targets are to be placed in a separate 
directory, and that directory might not exist before make is run. In this 
situation, you want the directory to be created before any targets are placed 
into it but, because the timestamps on directories change whenever a file is 
added, removed, or renamed, we certainly don’t want to rebuild all the targets 
whenever the directory’s timestamp changes. One way to manage this is with 
order-only prerequisites: make the directory an order-only prerequisite on all 
the targets:

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)

$(OBJDIR)/%.o : %.c
        $(COMPILE.c) $(OUTPUT_OPTION) $<

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
        mkdir $(OBJDIR)


Now the rule to create the objdir directory will be run, if needed, before any 
‘.o’ is built, but no ‘.o’ will be built because the objdir directory timestamp 
changed.

Finally, the third type of prerequisites, i.e. depenency-only prerequisites, 
may be specified by placing a "smaller than" symbol (<) 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:

myappl: main.o file1.o file2.o
        gcc -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 and the Makefile itself.

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

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


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 Makefile, we could most 
conviniently add a GNUmakefile with the following content:

include Makefile
myappl: < /usr/bin/gcc /usr/bin/ld Makefile


Calling make now would prefer GNUmakefile over Makefile, thus respecting the 
additional prerequisites without affecting the related reciepe

What do you think: Do I have any chance to have my patch included? I'm 
certainly more that willing to do any modifications desired.

Thanks in advance for any help,

Chris

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

Reply via email to