Troubleshooting

The experience of configuring any software build tool to build a large code base usually, at some point, involves trying to figure out why the tool is behaving a certain way, and how to get it to behave the way you want. SCons is no different.

Why is That Target Being Rebuilt? the --debug=explain Option

Let's take a simple example of a misconfigured build that causes a target to be rebuilt every time SCons is run:

      # Intentionally misspell the output file name in the
      # command used to create the file:
      Command('file.out', 'file.in', 'cp $SOURCE file.oout')
    

(Note to Windows users: The POSIX cp command copies the first file named on the command line to the second file. In our example, it copies the file.in file to the file.out file.)

Now if we run SCons multiple on this example, we see that it re-runs the cp command every time:

      % scons -Q
      cp file.in file.oout
      % scons -Q
      cp file.in file.oout
      % scons -Q
      cp file.in file.oout
    

In this example, the underlying cause is obvious: we've intentionally misspelled the output file name in the cp command, so the command doesn't actually build the file.out file that we've told SCons to expect. But if the problem weren't obvious, it would be helpful to specify the --debug=explain option on the command line to have SCons tell us very specifically why it's decided to rebuild the target:

      % scons -Q --debug=explain
      scons: building `file.out' because it doesn't exist
      cp file.in file.oout
    

If this had been a more complicated example involving a lot of build output, having SCons tell us that it's trying to rebuild the target file because it doesn't exist would be an important clue that something was wrong with the command that we invoked to build it.

The --debug=explain option also comes in handy to help figure out what input file changed. Given a simple configuration that builds a program from three source files, changing one of the source files and rebuilding with the --debug=explain option shows very specifically why SCons rebuilds the files that it does:

      % scons -Q
      cc -c -o file1.o file1.c
      cc -c -o file2.o file2.c
      cc -c -o file3.o file3.c
      cc -o prog file1.o file2.o file3.o
      % edit file2.c
          [CHANGE THE CONTENTS OF file2.c]
      % scons -Q --debug=explain
      scons: rebuilding `file2.o' because `file2.c' changed
      cc -c -o file2.o file2.c
      scons: rebuilding `prog' because `file2.o' changed
      cc -o prog file1.o file2.o file3.o
    

This becomes even more helpful in identifying when a file is rebuilt due to a change in an implicit dependency, such as an incuded .h file. If the file1.c and file3.c files in our example both included a hello.h file, then changing that included file and re-running SCons with the --debug=explain option will pinpoint that it's the change to the included file that starts the chain of rebuilds:

      % scons -Q
      cc -I. -c -o file1.o file1.c
      cc -I. -c -o file2.o file2.c
      cc -I. -c -o file3.o file3.c
      cc -o prog file1.o file2.o file3.o
      % edit hello.h
          [CHANGE THE CONTENTS OF hello.h]
      % scons -Q --debug=explain
      scons: rebuilding `file1.o' because `hello.h' changed
      cc -I. -c -o file1.o file1.c
      scons: rebuilding `file3.o' because `hello.h' changed
      cc -I. -c -o file3.o file3.c
      scons: rebuilding `prog' because:
                 `file1.o' changed
                 `file3.o' changed
      cc -o prog file1.o file2.o file3.o