5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 The experience of configuring any
29 software build tool to build a large code base
30 usually, at some point,
31 involves trying to figure out why
32 the tool is behaving a certain way,
33 and how to get it to behave the way you want.
34 &SCons; is no different.
35 This appendix contains a number of
36 different ways in which you can
37 get some additional insight into &SCons' behavior.
43 Note that we're always interested in trying to
44 improve how you can troubleshoot configuration problems.
45 If you run into a problem that has
46 you scratching your head,
47 and which there just doesn't seem to be a good way to debug,
48 odds are pretty good that someone else will run into
49 the same problem, too.
50 If so, please let the SCons development team know
51 (preferably by filing a bug report
52 or feature request at our project pages at tigris.org)
53 so that we can use your feedback
54 to try to come up with a better way to help you,
55 and others, get the necessary insight into &SCons; behavior
56 to help identify and fix configuration issues.
61 <title>Why is That Target Being Rebuilt? the &debug-explain; Option</title>
65 Let's look at a simple example of
67 that causes a target to be rebuilt
68 every time &SCons; is run:
72 <scons_example name="explain1">
73 <file name="SConstruct" printme="1">
74 # Intentionally misspell the output file name in the
75 # command used to create the file:
76 Command('file.out', 'file.in', 'cp $SOURCE file.oout')
85 (Note to Windows users: The POSIX &cp; command
86 copies the first file named on the command line
88 In our example, it copies the &file_in; file
89 to the &file_out; file.)
95 Now if we run &SCons; multiple times on this example,
96 we see that it re-runs the &cp;
101 <scons_output example="explain1" os="posix">
102 <scons_output_command>scons -Q</scons_output_command>
103 <scons_output_command>scons -Q</scons_output_command>
104 <scons_output_command>scons -Q</scons_output_command>
110 the underlying cause is obvious:
111 we've intentionally misspelled the output file name
113 so the command doesn't actually
114 build the &file_out; file that we've told &SCons; to expect.
115 But if the problem weren't obvious,
117 to specify the &debug-explain; option
119 to have &SCons; tell us very specifically
120 why it's decided to rebuild the target:
124 <scons_output example="explain1" os="posix">
125 <scons_output_command>scons -Q --debug=explain</scons_output_command>
130 If this had been a more complicated example
131 involving a lot of build output,
132 having &SCons; tell us that
133 it's trying to rebuild the target file
134 because it doesn't exist
135 would be an important clue
136 that something was wrong with
137 the command that we invoked to build it.
143 The &debug-explain; option also comes in handy
144 to help figure out what input file changed.
145 Given a simple configuration that builds
146 a program from three source files,
147 changing one of the source files
148 and rebuilding with the &debug-explain;
149 option shows very specifically
150 why &SCons; rebuilds the files that it does:
154 <scons_example name="explain2">
155 <file name="SConstruct">
156 Program('prog', ['file1.c', 'file2.c', 'file3.c'])
158 <file name="file1.c">
161 <file name="file2.c">
164 <file name="file3.c">
169 <scons_output example="explain2" os="posix">
170 <scons_output_command>scons -Q</scons_output_command>
171 <scons_output_command output=" [CHANGE THE CONTENTS OF file2.c]">edit file2.c</scons_output_command>
172 <scons_output_command>scons -Q --debug=explain</scons_output_command>
177 This becomes even more helpful
178 in identifying when a file is rebuilt
179 due to a change in an implicit dependency,
180 such as an incuded <filename>.h</filename> file.
181 If the <filename>file1.c</filename>
182 and <filename>file3.c</filename> files
184 both included a &hello_h; file,
185 then changing that included file
186 and re-running &SCons; with the &debug-explain; option
187 will pinpoint that it's the change to the included file
188 that starts the chain of rebuilds:
192 <scons_example name="explain3">
193 <file name="SConstruct">
194 Program('prog', ['file1.c', 'file2.c', 'file3.c'], CPPPATH='.')
196 <file name="file1.c">
197 #include <hello.h>
200 <file name="file2.c">
203 <file name="file3.c">
204 #include <hello.h>
207 <file name="hello.h">
208 #define string "world"
212 <scons_output example="explain3" os="posix">
213 <scons_output_command>scons -Q</scons_output_command>
214 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
215 <scons_output_command>scons -Q --debug=explain</scons_output_command>
220 (Note that the &debug-explain; option will only tell you
221 why &SCons; decided to rebuild necessary targets.
222 It does not tell you what files it examined
223 when deciding <emphasis>not</emphasis>
224 to rebuild a target file,
225 which is often a more valuable question to answer.)
232 <title>What's in That Construction Environment? the &Dump; Method</title>
236 When you create a construction environment,
238 with construction variables that are set up
239 for various compilers, linkers and utilities
240 that it finds on your system.
241 Although this is usually helpful and what you want,
242 it might be frustrating if &SCons;
243 doesn't set certain variables that you
245 In situations like this,
246 it's sometimes helpful to use the
247 construction environment &Dump; method
248 to print all or some of
249 the construction variables.
250 Note that the &Dump; method
251 <emphasis>returns</emphasis>
252 the representation of the variables
254 for you to print (or otherwise manipulate):
258 <scons_example name="Dump">
259 <file name="SConstruct" printme="1">
267 On a POSIX system with gcc installed,
272 <scons_output example="Dump" os="posix" tools="gcc">
273 <scons_output_command>scons</scons_output_command>
278 On a Windows system with Visual C++
279 the output might look like:
283 <scons_output example="Dump" os="win32" tools="msvc">
284 <scons_output_command>scons</scons_output_command>
289 The construction environments in these examples have
290 actually been restricted to just gcc and Visual C++,
292 In a real-life situation,
293 the construction environments will
294 likely contain a great many more variables.
295 Also note that we've massaged the example output above
296 to make the memory address of all objects a constant 0x700000.
297 In reality, you would see a different hexadecimal
298 number for each object.
304 To make it easier to see just what you're
306 the &Dump; method allows you to
307 specify a specific constrcution variable
308 that you want to disply.
310 it's not unusual to want to verify
311 the external environment used to execute build commands,
312 to make sure that the PATH and other
313 environment variables are set up the way they should be.
314 You can do this as follows:
318 <scons_example name="Dump_ENV">
319 <file name="SConstruct" printme="1">
321 print env.Dump('ENV')
327 Which might display the following when executed on a POSIX system:
331 <scons_output example="Dump_ENV" os="posix">
332 <scons_output_command>scons</scons_output_command>
337 And the following when executed on a Windows system:
341 <scons_output example="Dump_ENV" os="win32">
342 <scons_output_command>scons</scons_output_command>
349 <title>What Dependencies Does &SCons; Know About? the &tree; Option</title>
353 Sometimes the best way to try to figure out what
354 &SCons; is doing is simply to take a look at the
355 dependency graph that it constructs
356 based on your &SConscript; files.
357 The <literal>--tree</literal> option
358 will display all or part of the
359 &SCons; dependency graph in an
360 "ASCII art" graphical format
361 that shows the dependency hierarchy.
367 For example, given the following input &SConstruct; file:
371 <scons_example name="tree1">
372 <file name="SConstruct" printme="1">
373 env = Environment(CPPPATH = ['.'])
374 env.Program('prog', ['f1.c', 'f2.c', 'f3.c'])
392 Running &SCons; with the <literal>--tree=all</literal>
397 <scons_output example="tree1">
398 <scons_output_command>scons -Q --tree=all</scons_output_command>
403 The tree will also be printed when the
404 <literal>-n</literal> (no execute) option is used,
405 which allows you to examine the dependency graph
406 for a configuration without actually
407 rebuilding anything in the tree.
413 The <literaL>--tree</literal> option only prints
414 the dependency graph for the specified targets
415 (or the default target(s) if none are specified on the command line).
416 So if you specify a target like <filename>f2.o</filename>
418 the <literaL>--tree</literal> option will only
419 print the dependency graph for that file:
423 <scons_output example="tree1">
424 <scons_output_command>scons -Q --tree=all f2.o</scons_output_command>
429 This is, of course, useful for
430 restricting the output from a very large
431 build configuration to just a
432 portion in which you're interested.
433 Multiple targets are fine,
434 in which case a tree will be printed
435 for each specified target:
439 <scons_output example="tree1">
440 <scons_output_command>scons -Q --tree=all f1.o f3.o</scons_output_command>
445 The <literal>status</literal> argument may be used
446 to tell &SCons; to print status information about
447 each file in the dependency graph:
451 <scons_output example="tree1">
452 <scons_output_command>scons -Q --tree=status</scons_output_command>
457 Note that <literal>--tree=all,status</literal> is equivalent;
458 the <literal>all</literal>
459 is assumed if only <literal>status</literal> is present.
460 As an alternative to <literal>all</literal>,
461 you can specify <literal>--tree=derived</literal>
462 to have &SCons; only print derived targets
464 skipping source files
465 (like <filename>.c</filename> and <filename>.h</filename> files):
469 <scons_output example="tree1">
470 <scons_output_command>scons -Q --tree=derived</scons_output_command>
475 You can use the <literal>status</literal>
476 modifier with <literal>derived</literal> as well:
480 <scons_output example="tree1">
481 <scons_output_command>scons -Q --tree=derived,status</scons_output_command>
486 Note that the order of the <literal>--tree=</literal>
487 arguments doesn't matter;
488 <literal>--tree=status,derived</literal> is
489 completely equivalent.
495 The default behavior of the <literal>--tree</literal> option
496 is to repeat all of the dependencies each time the library dependency
497 (or any other dependency file) is encountered in the tree.
498 If certain target files share other target files,
499 such as two programs that use the same library:
503 <scons_example name="tree2">
504 <file name="SConstruct" printme="1">
505 env = Environment(CPPPATH = ['.'],
508 env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
509 env.Program('prog1.c')
510 env.Program('prog2.c')
512 <file name="prog1.c">
515 <file name="prog2.c">
534 Then there can be a <emphasis>lot</emphasis> of repetition in the
535 <literal>--tree=</literal> output:
539 <scons_output example="tree2">
540 <scons_output_command>scons -Q --tree=all</scons_output_command>
545 In a large configuration with many internal libraries
547 this can very quickly lead to huge output trees.
548 To help make this more manageable,
549 a <literal>prune</literal> modifier may
550 be added to the option list,
551 in which case &SCons;
552 will print the name of a target that has
553 already been visited during the tree-printing
554 in <literal>[square brackets]</literal>
555 as an indication that the dependencies
556 of the target file may be found
557 by looking farther up the tree:
561 <scons_output example="tree2">
562 <scons_output_command>scons -Q --tree=prune</scons_output_command>
567 Like the <literal>status</literal> keyword,
568 the <literal>prune</literal> argument by itself
569 is equivalent to <literal>--tree=all,prune</literal>.
577 <title>How is &SCons; Constructing the Command Lines It Executes? the &debug-presub; Option</title>
581 Sometimes it's useful to look at the
582 pre-substitution string
583 that &SCons; uses to generate
584 the command lines it executes.
585 This can be done with the &debug-presub; option:
589 <scons_example name="presub">
590 <file name="SConstruct">
591 env = Environment(CPPPATH = ['.'])
592 env.Program('prog', 'prog.c')
601 Have to capture output here, otherwise the - -debug=presub output
602 shows the Python functions from the sconsdoc.py execution wrapper
603 used to generate this manual, not the underlying command-line strings.
605 <scons_output example="presub">
606 <scons_output_command>scons -Q - -debug=presub</scons_output_command>
612 % <userinput>scons -Q --debug=presub</userinput>
613 Building prog.o with action:
614 $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCOMCOM $SOURCES
615 cc -o prog.o -c -I. prog.c
616 Building prog with action:
625 <title>Where is &SCons; Searching for Libraries? the &debug-findlibs; Option</title>
629 To get some insight into what library names
630 &SCons; is searching for,
631 and in which directories it is searching,
632 Use the <literal>--debug=findlibs</literal> option.
633 Given the following input &SConstruct; file:
637 <scons_example name="findlibs">
638 <file name="SConstruct" printme="1">
639 env = Environment(LIBPATH = ['libs1', 'libs2'])
640 env.Program('prog.c', LIBS=['foo', 'bar'])
645 <file name="libs1/libfoo.a">
648 <file name="libs2/libbar.a">
655 And the libraries <filename>libfoo.a</filename>
656 and <filename>libbar.a</filename>
657 in <filename>libs1</filename> and <filename>libs2</filename>,
659 use of the <literal>--debug=findlibs</literal> option yields:
663 <scons_output example="findlibs">
664 <scons_output_command>scons -Q --debug=findlibs</scons_output_command>
673 <title>What Implicit Dependencies Did the &SCons; Scanner find? the &debug-includes; Option</title>
677 XXX explain the - - debug=includes option
681 <scons_example name="includes">
682 <file name="SConstruct" printme="1">
683 env = Environment(CPPPATH = ['inc1', 'inc2'])
684 env.Program('prog.c')
691 <file name="inc1/file1.h">
694 <file name="inc2/file2.h">
699 <scons_output example="includes">
700 <scons_output_command>scons -Q - - debug=includes prog</scons_output_command>
709 <title>Where is &SCons; Blowing Up? the &debug-stacktrace; Option</title>
713 In general, &SCons; tries to keep its error
714 messages short and informative.
715 That means we usually try to avoid showing
716 the stack traces that are familiar
717 to experienced Python programmers,
718 since they usually contain much more
719 information than is useful to most people.
725 For example, the following &SConstruct file:
729 <scons_example name="stacktrace">
730 <file name="SConstruct" printme="1">
737 Generates the following error if the
738 <filename>prog.c</filename> file
743 <scons_output example="stacktrace">
744 <scons_output_command>scons -Q</scons_output_command>
750 the error is pretty obvious.
752 and you wanted to try to get more information
754 the &debug-stacktrace; option
755 would show you exactly where in the &SCons; source code
760 <scons_output example="stacktrace">
761 <scons_output_command>scons -Q --debug=stacktrace</scons_output_command>
766 Of course, if you do need to dive into the &SCons; source code,
767 we'd like to know if, or how,
768 the error messages or troubleshooting options
769 could have been improved to avoid that.
770 Not everyone has the necessary time or
771 Python skill to dive into the source code,
772 and we'd like to improve &SCons;
773 for those people as well...
781 <title>How is &SCons; Making Its Decisions? the &taskmastertrace; Option</title>
785 The internal &SCons; subsystem that handles walking
787 and controls the decision-making about what to rebuild
788 is the <literal>Taskmaster</literal>.
789 &SCons; supports a <literal>--taskmastertrace</literal>
790 option that tells the Taskmaster to print
791 information about the children (dependencies)
792 of the various Nodes on its walk down the graph,
793 which specific dependent Nodes are being evaluated,
800 The <literal>--taskmastertrace</literal> option
801 takes as an argument the name of a file in
802 which to put the trace output,
803 with <filename>-</filename> (a single hyphen)
804 indicating that the trace messages
805 should be printed to the standard output:
809 <scons_example name="taskmastertrace">
810 <file name="SConstruct" printme="1">
811 env = Environment(CPPPATH = ['.'])
812 env.Program('prog.c')
823 <scons_output example="taskmastertrace" os="posix">
824 <scons_output_command>scons -Q --taskmastertrace=- prog</scons_output_command>
829 The <literal>--taskmastertrace</literal> option
830 doesn't provide information about the actual
831 calculations involved in deciding if a file is up-to-date,
832 but it does show all of the dependencies
833 it knows about for each Node,
834 and the order in which those dependencies are evaluated.
835 This can be useful as an alternate way to determine
836 whether or not your &SCons; configuration,
837 or the implicit dependency scan,
838 has actually identified all the correct dependencies
849 <title>Where Are My Build Bottlenecks? the &profile; Option</title>
853 XXX explain the - - profile= option
864 <title>Troubleshooting Shared Caching: the &cache-debug; Option</title>
868 XXX describe the - - cache-debug option
869 XXX maybe point to the caching.in chapter?