ParseDepends
FunctionSCons has built-in scanners for a number of languages. Sometimes these scanners fail to extract certain implicit dependencies due to limitations of the scanner implementation.
The following example illustrates a case where the built-in C scanner is unable to extract the implicit dependency on a header file.
#define FOO_HEADER <foo.h> #include FOO_HEADER int main() { return FOO; }
% scons -Q cc -o hello.o -c -I. hello.c cc -o hello hello.o % edit foo.h [CHANGE CONTENTS OF foo.h] % scons -Q scons: `.' is up to date.
Apparently, the scanner does not know about the header dependency. Being not a full-fledged C preprocessor, the scanner does not expand the macro.
In these cases, you may also use the compiler to extract the
implicit dependencies. ParseDepends
can parse the contents of
the compiler output in the style of Make, and explicitly
establish all of the listed dependencies.
The following example uses ParseDepends
to process a compiler
generated dependency file which is generated as a side effect
during compilation of the object file:
obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') SideEffect('hello.d', obj) ParseDepends('hello.d') Program('hello', obj)
% scons -Q cc -o hello.o -c -MD -MF hello.d -I. hello.c cc -o hello hello.o % edit foo.h [CHANGE CONTENTS OF foo.h] % scons -Q cc -o hello.o -c -MD -MF hello.d -I. hello.c
Parsing dependencies from a compiler-generated .d file has a chicken-and-egg problem, that causes unnecessary rebuilds:
% scons -Q cc -o hello.o -c -MD -MF hello.d -I. hello.c cc -o hello hello.o % scons -Q --debug=explain scons: rebuilding `hello.o' because `foo.h' is a new dependency cc -o hello.o -c -MD -MF hello.d -I. hello.c % scons -Q scons: `.' is up to date.
In the first pass, the dependency file is generated while the object file is compiled. At that time, SCons does not know about the dependency on foo.h. In the second pass, the object file is regenerated because foo.h is detected as a new dependency.
ParseDepends
immediately reads the specified file at invocation
time and just returns if the file does not exist. A dependency
file generated during the build process is not automatically
parsed again. Hence, the compiler-extracted dependencies are not
stored in the signature database during the same build pass. This
limitation of ParseDepends
leads to unnecessary recompilations.
Therefore, ParseDepends
should only be used if scanners are not
available for the employed language or not powerful enough for the
specific task.