28.3. What Dependencies Does SCons Know About? the `--tree` Option
Prev | Chapter 28. Troubleshooting | Next

## 28.3. What Dependencies Does SCons Know About? the `--tree` Option

Sometimes the best way to try to figure out what SCons is doing is simply to take a look at the dependency graph that it constructs based on your `SConscript` files. The `--tree` option will display all or part of the SCons dependency graph in an "ASCII art" graphical format that shows the dependency hierarchy.

For example, given the following input `SConstruct` file:

    env = Environment(CPPPATH = ['.'])
    env.Program('prog', ['f1.c', 'f2.c', 'f3.c'])

Running SCons with the `--tree=all` option yields:

    % scons -Q --tree=all
    cc -o f1.o -c -I. f1.c
    cc -o f2.o -c -I. f2.c
    cc -o f3.o -c -I. f3.c
    cc -o prog f1.o f2.o f3.o
    +-.
      +-SConstruct
      +-f1.c
      +-f1.o
      | +-f1.c
      | +-inc.h
      +-f2.c
      +-f2.o
      | +-f2.c
      | +-inc.h
      +-f3.c
      +-f3.o
      | +-f3.c
      | +-inc.h
      +-inc.h
      +-prog
        +-f1.o
        | +-f1.c
        | +-inc.h
        +-f2.o
        | +-f2.c
        | +-inc.h
        +-f3.o
          +-f3.c
          +-inc.h

The tree will also be printed when the `-n` (no execute) option is used, which allows you to examine the dependency graph for a configuration without actually rebuilding anything in the tree.

By default, SCons uses "ASCII art" to draw the tree. It is possible to use line-drawing characters (Unicode calls these Box Drawing) to make a nicer display. To do this, add the `linedraw` qualifier:

    % scons -Q --tree=all,linedraw
    cc -o f1.o -c -I. f1.c
    cc -o f2.o -c -I. f2.c
    cc -o f3.o -c -I. f3.c
    cc -o prog f1.o f2.o f3.o
    └─┬.
      ├─SConstruct
      ├─f1.c
      ├─┬f1.o
      │ ├─f1.c
      │ └─inc.h
      ├─f2.c
      ├─┬f2.o
      │ ├─f2.c
      │ └─inc.h
      ├─f3.c
      ├─┬f3.o
      │ ├─f3.c
      │ └─inc.h
      ├─inc.h
      └─┬prog
        ├─┬f1.o
        │ ├─f1.c
        │ └─inc.h
        ├─┬f2.o
        │ ├─f2.c
        │ └─inc.h
        └─┬f3.o
          ├─f3.c
          └─inc.h

The `--tree` option only prints the dependency graph for the specified targets (or the default target(s) if none are specified on the command line). So if you specify a target like `f2.o` on the command line, the `--tree` option will only print the dependency graph for that file:

    % scons -Q --tree=all f2.o
    cc -o f2.o -c -I. f2.c
    +-f2.o
      +-f2.c
      +-inc.h

This is, of course, useful for restricting the output from a very large build configuration to just a portion in which you're interested. Multiple targets are fine, in which case a tree will be printed for each specified target:

    % scons -Q --tree=all f1.o f3.o
    cc -o f1.o -c -I. f1.c
    +-f1.o
      +-f1.c
      +-inc.h
    cc -o f3.o -c -I. f3.c
    +-f3.o
      +-f3.c
      +-inc.h

The `status` argument may be used to tell SCons to print status information about each file in the dependency graph:

    % scons -Q --tree=status
    cc -o f1.o -c -I. f1.c
    cc -o f2.o -c -I. f2.c
    cc -o f3.o -c -I. f3.c
    cc -o prog f1.o f2.o f3.o
     E         = exists
      R        = exists in repository only
       b       = implicit builder
       B       = explicit builder
        S      = side effect
         P     = precious
          A    = always build
           C   = current
            N  = no clean
             H = no cache

    [E b      ]+-.
    [E     C  ]  +-SConstruct
    [E     C  ]  +-f1.c
    [E B   C  ]  +-f1.o
    [E     C  ]  | +-f1.c
    [E     C  ]  | +-inc.h
    [E     C  ]  +-f2.c
    [E B   C  ]  +-f2.o
    [E     C  ]  | +-f2.c
    [E     C  ]  | +-inc.h
    [E     C  ]  +-f3.c
    [E B   C  ]  +-f3.o
    [E     C  ]  | +-f3.c
    [E     C  ]  | +-inc.h
    [E     C  ]  +-inc.h
    [E B   C  ]  +-prog
    [E B   C  ]    +-f1.o
    [E     C  ]    | +-f1.c
    [E     C  ]    | +-inc.h
    [E B   C  ]    +-f2.o
    [E     C  ]    | +-f2.c
    [E     C  ]    | +-inc.h
    [E B   C  ]    +-f3.o
    [E     C  ]      +-f3.c
    [E     C  ]      +-inc.h

Note that `--tree=all,status` is equivalent; the `all` is assumed if only `status` is present. As an alternative to `all`, you can specify `--tree=derived` to have SCons only print derived targets in the tree output, skipping source files (like `.c` and `.h` files):

    % scons -Q --tree=derived
    cc -o f1.o -c -I. f1.c
    cc -o f2.o -c -I. f2.c
    cc -o f3.o -c -I. f3.c
    cc -o prog f1.o f2.o f3.o
    +-.
      +-f1.o
      +-f2.o
      +-f3.o
      +-prog
        +-f1.o
        +-f2.o
        +-f3.o

You can use the `status` modifier with `derived` as well:

    % scons -Q --tree=derived,status
    cc -o f1.o -c -I. f1.c
    cc -o f2.o -c -I. f2.c
    cc -o f3.o -c -I. f3.c
    cc -o prog f1.o f2.o f3.o
     E         = exists
      R        = exists in repository only
       b       = implicit builder
       B       = explicit builder
        S      = side effect
         P     = precious
          A    = always build
           C   = current
            N  = no clean
             H = no cache

    [E b      ]+-.
    [E B   C  ]  +-f1.o
    [E B   C  ]  +-f2.o
    [E B   C  ]  +-f3.o
    [E B   C  ]  +-prog
    [E B   C  ]    +-f1.o
    [E B   C  ]    +-f2.o
    [E B   C  ]    +-f3.o

Note that the order of the `--tree=` arguments doesn't matter; `--tree=status,derived` is completely equivalent.

The default behavior of the `--tree` option is to repeat all of the dependencies each time the library dependency (or any other dependency file) is encountered in the tree. If certain target files share other target files, such as two programs that use the same library:

    env = Environment(CPPPATH = ['.'],
                      LIBS = ['foo'],
                      LIBPATH = ['.'])
    env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
    env.Program('prog1.c')
    env.Program('prog2.c')

Then there can be a lot of repetition in the `--tree=` output:

    % scons -Q --tree=all
    cc -o f1.o -c -I. f1.c
    cc -o f2.o -c -I. f2.c
    cc -o f3.o -c -I. f3.c
    ar rc libfoo.a f1.o f2.o f3.o
    ranlib libfoo.a
    cc -o prog1.o -c -I. prog1.c
    cc -o prog1 prog1.o -L. -lfoo
    cc -o prog2.o -c -I. prog2.c
    cc -o prog2 prog2.o -L. -lfoo
    +-.
      +-SConstruct
      +-f1.c
      +-f1.o
      | +-f1.c
      | +-inc.h
      +-f2.c
      +-f2.o
      | +-f2.c
      | +-inc.h
      +-f3.c
      +-f3.o
      | +-f3.c
      | +-inc.h
      +-inc.h
      +-libfoo.a
      | +-f1.o
      | | +-f1.c
      | | +-inc.h
      | +-f2.o
      | | +-f2.c
      | | +-inc.h
      | +-f3.o
      |   +-f3.c
      |   +-inc.h
      +-prog1
      | +-prog1.o
      | | +-prog1.c
      | | +-inc.h
      | +-libfoo.a
      |   +-f1.o
      |   | +-f1.c
      |   | +-inc.h
      |   +-f2.o
      |   | +-f2.c
      |   | +-inc.h
      |   +-f3.o
      |     +-f3.c
      |     +-inc.h
      +-prog1.c
      +-prog1.o
      | +-prog1.c
      | +-inc.h
      +-prog2
      | +-prog2.o
      | | +-prog2.c
      | | +-inc.h
      | +-libfoo.a
      |   +-f1.o
      |   | +-f1.c
      |   | +-inc.h
      |   +-f2.o
      |   | +-f2.c
      |   | +-inc.h
      |   +-f3.o
      |     +-f3.c
      |     +-inc.h
      +-prog2.c
      +-prog2.o
        +-prog2.c
        +-inc.h

In a large configuration with many internal libraries and include files, this can very quickly lead to huge output trees. To help make this more manageable, a `prune` modifier may be added to the option list, in which case SCons will print the name of a target that has already been visited during the tree-printing in square brackets (`[]`) as an indication that the dependencies of the target file may be found by looking farther up the tree:

    % scons -Q --tree=prune
    cc -o f1.o -c -I. f1.c
    cc -o f2.o -c -I. f2.c
    cc -o f3.o -c -I. f3.c
    ar rc libfoo.a f1.o f2.o f3.o
    ranlib libfoo.a
    cc -o prog1.o -c -I. prog1.c
    cc -o prog1 prog1.o -L. -lfoo
    cc -o prog2.o -c -I. prog2.c
    cc -o prog2 prog2.o -L. -lfoo
    +-.
      +-SConstruct
      +-f1.c
      +-f1.o
      | +-f1.c
      | +-inc.h
      +-f2.c
      +-f2.o
      | +-f2.c
      | +-inc.h
      +-f3.c
      +-f3.o
      | +-f3.c
      | +-inc.h
      +-inc.h
      +-libfoo.a
      | +-[f1.o]
      | +-[f2.o]
      | +-[f3.o]
      +-prog1
      | +-prog1.o
      | | +-prog1.c
      | | +-inc.h
      | +-[libfoo.a]
      +-prog1.c
      +-[prog1.o]
      +-prog2
      | +-prog2.o
      | | +-prog2.c
      | | +-inc.h
      | +-[libfoo.a]
      +-prog2.c
      +-[prog2.o]

Like the `status` keyword, the `prune` argument by itself is equivalent to `--tree=all,prune`.

Prev | Up | Next
28.2. What's in That Construction Environment? the `Dump` Method | Home | 28.4. How is SCons Constructing the Command Lines It Executes? the `--debug=presub` Option