[Scons-users] Bug in C scanner? (not seeing dynamically generated headers)

Greg Ward greg at gerg.ca
Thu Jun 21 10:57:58 EDT 2012


Hi all --

I'm seeing some, err, anomalous behaviour in the dependency scanner
for C source files. Specifically:

* IF file1.c includes <lib1.h>, which includes <zlib.h>
* AND <zlib.h> is put into the include search path dynamically, by an
earlier build step (effectively it's "generated" code)
* THEN file1.o does not depend on <zlib.h> (even though it should)

Here's my source tree:

app/file1.c
app/file2.c
lib1/lib1.h

file1.c and file2.c are both dead simple:

$ cat app/file1.c
#include <lib1.h>

$ cat app/file2.c
#include <zlib.h>

So is lib1/lib1.h:

$ cat lib1/lib1.h
#include <zlib.h>


>From this, you would expect file1.o and file2.o to both depend on

zlib.h. Unfortunately, we don't use /usr/include/zlib.h. We use a
local copy, include/zlib.h, which is copied into include/ by an
earlier build step:

$ scons --debug=explain
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: building `include/.contents' because it doesn't exist
./copyheaders libs.txt include
[...continued below...]

copyheaders is a simple shell script that reads a list of dependencies
from libs.txt, and copies the headers into include/. (This is a
barebones, stripped-down, ultra-simplified version of our production
system, which is a 900-line beast of a Python script.) Oh yeah, it
also does

find include -name "*.h" > include/.contents

so that my SConscript has a way to feed its results back into the
dependency graph. I'm using the trick described in
http://scons.org/wiki/DynamicSourceGenerator.

Anyways, SCons successfully compiles file1.c and file2.c:

[...continuing from above...]
scons: building `app/file1.o' because it doesn't exist
gcc -o app/file1.o -c -Iinclude -Ilib1 app/file1.c
scons: building `app/file2.o' because it doesn't exist
gcc -o app/file2.o -c -Iinclude -Ilib1 app/file2.c
scons: done building targets.

But the dependency info is inaccurate:

$ sconsign .sconsign.dblite
[...]
=== app:
file1.c: ea14432c192e5d9492d847001bdaaff1 1340231434 18
file1.o: 02819226eb311d7903759af075336afb 1340232671 937
app/file1.c: ea14432c192e5d9492d847001bdaaff1 1340231434 18
dummy-include: d41d8cd98f00b204e9800998ecf8427e 0 0
lib1/lib1.h: 08137c641d54ceb7caf7187469d43555 1340231155 18
/usr/bin/gcc: 92746426d101b439684749a28e19b8f6 1331056505 350624
5f7110a9705ccb2208968abf8a082bb7 [$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES]
file2.c: 08137c641d54ceb7caf7187469d43555 1340231464 18
file2.o: 3c55513c46f112dd99f0e58c479ffd8d 1340232671 937
app/file2.c: 08137c641d54ceb7caf7187469d43555 1340231464 18
dummy-include: d41d8cd98f00b204e9800998ecf8427e 0 0
include/zlib.h: 6c784c19bf04eb316bd2e85f2f3aa178 1340232671 79565
include/zconf.h: e7b67b659745ac1d5e0dcfad97123ce2 1340232671 13357
/usr/bin/gcc: 92746426d101b439684749a28e19b8f6 1331056505 350624
132a3fde444ccb6d6eba546de5f71602 [$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES]
[...]

Notice how file2.o correctly depends on include/zlib.h, but file1.o
does not. This leads to unnecessary rebuilds of file1.o:

$ scons --debug=explain
[...]
scons: rebuilding `app/file1.o' because:
`include/zlib.h' is a new dependency
`include/zconf.h' is a new dependency
gcc -o app/file1.o -c -Iinclude -Ilib1 app/file1.c
scons: done building targets.

Any idea what's going on here?

If you want to play around with my code, it's right here:

hg clone http://hg.gerg.ca/copyheaders2/

or just download

http://hg.gerg.ca/copyheaders2/archive/tip.zip

Thanks!

Greg


More information about the Scons-users mailing list