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