Fix to includes of includes not being considered, broken by 2499.
Details taken from email to jamming:
The challenge is to make included includes appear as direct
includes, so that they get considered. This used to work by
recursion, because each TARGET node computed the summary of its
includes -- the hfate and htime -- along with the summary of
its dependents -- the fate and time. Alas, that previous
arrangement confused make1() into treating headers as direct
dependencies during the build phase.
A.o
|
A.c -- A.h
(Read depends down, includes across)
(Failed build of A.h aborts build of A.c)
The fix to the confused make1() problem was to consolidate the
special handling of includes by having make0() tack onto a
target's list of dependendies any of the target's dependents'
includes. Unfortunately, this fix did not recurse: if the
target's dependents' includes included other files, those files
were not added to the target's dependencies.
A.o
|
A.c -- A.h -- B.h -- C.h
is rewritten to:
A.o
| \
A.c A.h -- B.h -- C.h
(A.o depends on A.h, but not B.h or C.h. This is
the current, broken state of jam 2.5rc1.)
Matt's bugfix added some recursion at this point, by transitively
appending includes' includes onto the includes chain. But, as
he found out (and I did before), this can slow make0() down
considerably, as typically header files all include each other
and you wind up with lots of really long chains.
A.o
|
A.c -- A.h -- B.h -- C.h
is rewritten to:
A.o
|
A.c -- A.h -- B.h -- C.h
- B.h - C.h
- C.h
(Matt's fix: if the .h files include each other, the
includes chains get very long.)
The final(?) fix I have is relatively simple, but is an extra
step: to have make0() replace a target's includes chain with
a single pseudo-target whose dependencies are the original
target's includes. That pseudo-target gets passed to make0(),
which then recursively consolidates its fate and time. This
then makes a target's includes fate and time available in a
single target hanging off the original target.