Please note:The SCons wiki is in read-only mode due to ongoing spam/DoS issues. Also, new account creation is currently disabled. We are looking into alternative wiki hosts.

ParseDepends

ParseDepends allows to parse compiler-generated dependency files and let SCons establish the listed dependencies.

What's that in aid of?

As a rule of thumb, never use it unless you have to. SCons has scanners to extract implicit dependencies. However, sometimes the built-in scanners choke on pre-processor statements.

Consider the following example:

hello.c:

#define FOO_HEADER "foo.h"

#include FOO_HEADER

int main() {
        return FOO;
}

foo.h:

#define FOO 42

SConstruct:

Program('hello.c')

scons --tree=prune

As the dependency tree reveals, SCons does not know about foo.h and does not recompile hello.o when foo.h changes.

If the compiler is able to extract implicit dependencies and output those as Make rules, SCons can parse these files and properly set up the dependencies.

Generate dependency files as a side effect

Here is an example of how to let gcc generate a dependency file while compiling the object file:

   1 Program('hello.c', CCFLAGS = '-MD -MF hello.d')
   2 ParseDepends('hello.d')
   3 SideEffect('hello.d', 'hello.o')

GCC generates a dependency file that looks like the following:

hello.o: hello.c foo.h

There is one problem with this approach: Read the full story here.

To wrap it up, ParseDepends does not read the file in the first pass, leading to unnecessary rebuilds in the second pass. The reason is, that the signature changes as new dependencies are added (foo.h in the example above).

Generate dependency files in advance

If you want to extract the dependencies (and call ParseDepends) before building the object files, the only viable solution is to use a multi-stage builder with a source scanner:

   1 def parsedep(node, env, path):
   2         print "ParseDepends(%s)" % str(node)
   3         ParseDepends(str(node))
   4         return []
   5 
   6 def parsecheck(node, env):
   7         return node.exists()
   8 
   9 depscan = Scanner(function = parsedep, skeys = ['.d'], scan_check=parsecheck)
  10 
  11 depbuild = Builder(action = '$CC -M -MF $TARGET $CCFLAGS -c $SOURCE', 
  12                    suffix='.d', src_suffix='.c')
  13 
  14 depparse = Builder(action = Copy('$TARGET', '$SOURCE'), 
  15                    suffix='.dep', 
  16                    src_builder=depbuild, 
  17                    source_scanner=depscan)
  18 
  19 env = Environment(BUILDERS = {'ExtractDependencies': depparse})
  20 
  21 dep = env.ExtractDependencies('hello.c')
  22 
  23 obj = env.Object('hello.c')
  24 env.Requires(obj, dep)
  25 env.Program(obj)

Some notes:

ParseDepends (last edited 2008-04-16 18:49:47 by LudwigHaehne)