tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Changing make(1) behavior: do not add inferred dependencies on non-inferred targets



Recent changes cause make to no longer add inferred dependencies on
targets that are made by an explicit rule.  It has been proposed that
the previous behavior was actually a useful feature and should be
re-instated to not break old makefiles.  Presumably this also means
that the value of $(.IMPSRC) should be as it was, because it was set
by the same code that added the inferred dependencies.  The other point
of view is that the behavior was totally incorrect and makefiles relying
on the behavior need to be fixed.

Here is a simplified makefile and its usage demonstrating the case.
Assume that files bar.c, foo.S, foo.proto and xyz.y exist.

    .SUFFIXES:
    .SUFFIXES: .c .o
    .c.o: $(CC) ...

    foo.o: foo.S
        $(AS) -o $(@) foo.S

    foo.c: foo.proto
        process foo.proto >foo.c

    bar.o: bar.h
        $(CC) -c -o $(@) bar.c

    xyz.x: xyz.y
        cp xyz.y xyz.x

    $ make foo.o bar.o xyz.x


Historical behavior
===================

A dependency on foo.c is added for foo.o, causing foo.c to be generated
from foo.proto.  Then foo.o is assembled from foo.S.  If foo.proto
changes, foo.o is assembled again.  $(.ALLSRC) and $(.OODATE)
will contain foo.c and foo.S [1].

bar.o is compiled from bar.c.  If bar.c changes, bar.o is recompiled.
$(.ALLSRC) and $(.OODATE) will contain bar.c and bar.h [1].

xyz.y is copied to xyz.x.

$(.IMPSRC) is set as follows:
    foo.o: foo.c
    bar.o: bar.c
    xyz.x: <unset>


New behavior
============

Explicit rules are self-contained.  All the dependencies are listed
right in that rule, unless explicitly added with a dependency line
with no commands.
    target: source

foo.c will not be generated.  If foo.proto changes, foo.o will not be
recompiled.  foo.o is assembled from foo.S.  $(.ALLSRC) and $(.OODATE)
will contain foo.S only [1].

bar.o is compiled from bar.c.  If bar.c changes, bar.o is _not_
recompiled, because the dependency information in the makefile is
incomplete (user error).  $(.ALLSRC) and $(.OODATE) will contain
bar.h only [1].

xyz.y is copied to xyz.x.

$(.IMPSRC) is set as follows:
    foo.o: foo.S
    bar.o: bar.h
    xyz.x: xyz.y


Comparing old and new
=====================

With the historical behavior make will in some cases add unrelated files
as dependencies, possibly causing unneeded targets to be made or targets
to be re-made unnecessarily.  This does not happen with the new
behavior.

Historically an explicit rule could be written without listing all
dependencies, if the omitted dependency would have been the implied
source were the target to be made by a suffix rule.  This is no longer
possible with the new behavior, all dependencies need to be listed
explicitly for explicit rules.

With historical behavior the value of $(.IMPSRC) is seemingly random
(and undocumented) in explicit rules.  From source: it is the file
which would have been the implied source if the target would've been
inferred.  Sometimes the value is usable, sometimes not.  New behavior
has the value documentedly be the first listed dependency in
an explicit rule.  The new behavior is compatible with gmake, POSIX only
specifies the value of $(.IMPSRC) (actually $(<)) for suffix rules.


Footnotes:
[1] File is listed in $(.OODATE) only if it has been modified.

-- 
Jarmo Jaakkola


Home | Main Index | Thread Index | Old Index