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:
73 # Intentionally misspell the output file name in the
74 # command used to create the file:
75 Command('file.out', 'file.in', 'cp $SOURCE file.oout')
80 (Note to Windows users: The POSIX &cp; command
81 copies the first file named on the command line
83 In our example, it copies the &file_in; file
84 to the &file_out; file.)
90 Now if we run &SCons; multiple times on this example,
91 we see that it re-runs the &cp;
97 % <userinput>scons -Q</userinput>
99 % <userinput>scons -Q</userinput>
101 % <userinput>scons -Q</userinput>
108 the underlying cause is obvious:
109 we've intentionally misspelled the output file name
111 so the command doesn't actually
112 build the &file_out; file that we've told &SCons; to expect.
113 But if the problem weren't obvious,
115 to specify the &debug-explain; option
117 to have &SCons; tell us very specifically
118 why it's decided to rebuild the target:
123 % <userinput>scons -Q --debug=explain</userinput>
124 scons: building `file.out' because it doesn't exist
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:
157 % <userinput>scons -Q</userinput>
158 cc -o file1.o -c file1.c
159 cc -o file2.o -c file2.c
160 cc -o file3.o -c file3.c
161 cc -o prog file1.o file2.o file3.o
162 % <userinput>edit file2.c</userinput>
163 [CHANGE THE CONTENTS OF file2.c]
164 % <userinput>scons -Q --debug=explain</userinput>
165 scons: rebuilding `file2.o' because `file2.c' changed
166 cc -o file2.o -c file2.c
167 scons: rebuilding `prog' because `file2.o' changed
168 cc -o prog file1.o file2.o file3.o
173 This becomes even more helpful
174 in identifying when a file is rebuilt
175 due to a change in an implicit dependency,
176 such as an incuded <filename>.h</filename> file.
177 If the <filename>file1.c</filename>
178 and <filename>file3.c</filename> files
180 both included a &hello_h; file,
181 then changing that included file
182 and re-running &SCons; with the &debug-explain; option
183 will pinpoint that it's the change to the included file
184 that starts the chain of rebuilds:
191 % <userinput>scons -Q</userinput>
192 cc -o file1.o -c -I. file1.c
193 cc -o file2.o -c -I. file2.c
194 cc -o file3.o -c -I. file3.c
195 cc -o prog file1.o file2.o file3.o
196 % <userinput>edit hello.h</userinput>
197 [CHANGE THE CONTENTS OF hello.h]
198 % <userinput>scons -Q --debug=explain</userinput>
199 scons: rebuilding `file1.o' because `hello.h' changed
200 cc -o file1.o -c -I. file1.c
201 scons: rebuilding `file3.o' because `hello.h' changed
202 cc -o file3.o -c -I. file3.c
203 scons: rebuilding `prog' because:
206 cc -o prog file1.o file2.o file3.o
211 (Note that the &debug-explain; option will only tell you
212 why &SCons; decided to rebuild necessary targets.
213 It does not tell you what files it examined
214 when deciding <emphasis>not</emphasis>
215 to rebuild a target file,
216 which is often a more valuable question to answer.)
223 <title>What's in That Construction Environment? the &Dump; Method</title>
227 When you create a construction environment,
229 with construction variables that are set up
230 for various compilers, linkers and utilities
231 that it finds on your system.
232 Although this is usually helpful and what you want,
233 it might be frustrating if &SCons;
234 doesn't set certain variables that you
236 In situations like this,
237 it's sometimes helpful to use the
238 construction environment &Dump; method
239 to print all or some of
240 the construction variables.
241 Note that the &Dump; method
242 <emphasis>returns</emphasis>
243 the representation of the variables
245 for you to print (or otherwise manipulate):
256 On a POSIX system with gcc installed,
262 % <userinput>scons</userinput>
263 scons: Reading SConscript files ...
264 { 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>},
265 'CONFIGUREDIR': '#/.sconf_temp',
266 'CONFIGURELOG': '#/config.log',
267 'CPPSUFFIXES': [ '.c',
287 'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
288 'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
289 'ENV': { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'},
290 'ESCAPE': <function escape at 0x700000>,
291 'File': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
294 'IDLSUFFIXES': ['.idl', '.IDL'],
295 'INSTALL': <function copyFunc at 0x700000>,
297 'LIBPREFIXES': ['$LIBPREFIX'],
299 'LIBSUFFIXES': ['$LIBSUFFIX', '$SHLIBSUFFIX'],
300 'MAXLINELENGTH': 128072,
306 'PSPAWN': <function piped_env_spawn at 0x700000>,
307 'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
310 'SHLIBPREFIX': '$LIBPREFIX',
311 'SHLIBSUFFIX': '.so',
312 'SHOBJPREFIX': '$OBJPREFIX',
313 'SHOBJSUFFIX': '$OBJSUFFIX',
314 'SPAWN': <function spawnvpe_spawn at 0x700000>,
317 'TEMPFILE': <class SCons.Platform.TempFileMunge at 0x700000>,
318 'TEMPFILEPREFIX': '@',
319 'TOOLS': ['install', 'install'],
320 '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
321 '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
322 '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
323 '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
324 '__RPATH': '$_RPATH',
325 '_concat': <function _concat at 0x700000>,
326 '_defines': <function _defines at 0x700000>,
327 '_stripixes': <function _stripixes at 0x700000>}
328 scons: done reading SConscript files.
329 scons: Building targets ...
330 scons: `.' is up to date.
331 scons: done building targets.
336 On a Windows system with Visual C++
337 the output might look like:
342 C:\><userinput>scons</userinput>
343 scons: Reading SConscript files ...
344 { 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000>, 'Object': <SCons.Builder.CompositeBuilder instance at 0x700000>, 'PCH': <SCons.Builder.BuilderBase instance at 0x700000>, 'RES': <SCons.Builder.BuilderBase instance at 0x700000>, 'SharedObject': <SCons.Builder.CompositeBuilder instance at 0x700000>, 'StaticObject': <SCons.Builder.CompositeBuilder instance at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>},
346 'CCCOM': <SCons.Action.FunctionAction instance at 0x700000>,
347 'CCFLAGS': ['/nologo'],
348 'CCPCHFLAGS': ['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'],
349 'CCPDBFLAGS': ['${(PDB and "/Z7") or ""}'],
352 'CONFIGUREDIR': '#/.sconf_temp',
353 'CONFIGURELOG': '#/config.log',
354 'CPPDEFPREFIX': '/D',
356 'CPPSUFFIXES': [ '.c',
376 'CXXCOM': '$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM',
377 'CXXFILESUFFIX': '.cc',
378 'CXXFLAGS': ['$(', '/TP', '$)'],
380 'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
381 'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
382 'ENV': { 'PATH': 'C:\\WINDOWS\\System32',
383 'PATHEXT': '.COM;.EXE;.BAT;.CMD',
384 'SystemRoot': 'C:\\WINDOWS'},
385 'ESCAPE': <function escape at 0x700000>,
386 'File': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
389 'IDLSUFFIXES': ['.idl', '.IDL'],
392 'INSTALL': <function copyFunc at 0x700000>,
394 'LIBPREFIXES': ['$LIBPREFIX'],
396 'LIBSUFFIXES': ['$LIBSUFFIX'],
397 'MAXLINELENGTH': 2048,
398 'MSVC_SETUP_RUN': True,
401 'PCHCOM': '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS',
402 'PCHPDBFLAGS': ['${(PDB and "/Yd") or ""}'],
405 'PROGSUFFIX': '.exe',
406 'PSPAWN': <function piped_spawn at 0x700000>,
408 'RCCOM': <SCons.Action.FunctionAction instance at 0x700000>,
410 'RCSUFFIXES': ['.rc', '.rc2'],
411 'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
414 'SHCCCOM': <SCons.Action.FunctionAction instance at 0x700000>,
415 'SHCCFLAGS': ['$CCFLAGS'],
416 'SHCFLAGS': ['$CFLAGS'],
418 'SHCXXCOM': '$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM',
419 'SHCXXFLAGS': ['$CXXFLAGS'],
422 'SHLIBSUFFIX': '.dll',
423 'SHOBJPREFIX': '$OBJPREFIX',
424 'SHOBJSUFFIX': '$OBJSUFFIX',
425 'SPAWN': <function spawn at 0x700000>,
426 'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1,
428 'TARGET_OS': 'win32',
429 'TEMPFILE': <class SCons.Platform.TempFileMunge at 0x700000>,
430 'TEMPFILEPREFIX': '@',
431 'TOOLS': ['msvc', 'install', 'install'],
432 '_CCCOMCOM': '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS',
433 '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
434 '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
435 '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
436 '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
437 '_MSVC_OUTPUT_FLAG': <function msvc_output_flag at 0x700000>,
438 '_concat': <function _concat at 0x700000>,
439 '_defines': <function _defines at 0x700000>,
440 '_stripixes': <function _stripixes at 0x700000>}
441 scons: done reading SConscript files.
442 scons: Building targets ...
443 scons: `.' is up to date.
444 scons: done building targets.
449 The construction environments in these examples have
450 actually been restricted to just gcc and Visual C++,
452 In a real-life situation,
453 the construction environments will
454 likely contain a great many more variables.
455 Also note that we've massaged the example output above
456 to make the memory address of all objects a constant 0x700000.
457 In reality, you would see a different hexadecimal
458 number for each object.
464 To make it easier to see just what you're
466 the &Dump; method allows you to
467 specify a specific constrcution variable
468 that you want to disply.
470 it's not unusual to want to verify
471 the external environment used to execute build commands,
472 to make sure that the PATH and other
473 environment variables are set up the way they should be.
474 You can do this as follows:
480 print env.Dump('ENV')
485 Which might display the following when executed on a POSIX system:
490 % <userinput>scons</userinput>
491 scons: Reading SConscript files ...
492 { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}
493 scons: done reading SConscript files.
494 scons: Building targets ...
495 scons: `.' is up to date.
496 scons: done building targets.
501 And the following when executed on a Windows system:
506 C:\><userinput>scons</userinput>
507 scons: Reading SConscript files ...
508 { 'PATH': 'C:\\WINDOWS\\System32',
509 'PATHEXT': '.COM;.EXE;.BAT;.CMD',
510 'SystemRoot': 'C:\\WINDOWS'}
511 scons: done reading SConscript files.
512 scons: Building targets ...
513 scons: `.' is up to date.
514 scons: done building targets.
521 <title>What Dependencies Does &SCons; Know About? the &tree; Option</title>
525 Sometimes the best way to try to figure out what
526 &SCons; is doing is simply to take a look at the
527 dependency graph that it constructs
528 based on your &SConscript; files.
529 The <literal>--tree</literal> option
530 will display all or part of the
531 &SCons; dependency graph in an
532 "ASCII art" graphical format
533 that shows the dependency hierarchy.
539 For example, given the following input &SConstruct; file:
544 env = Environment(CPPPATH = ['.'])
545 env.Program('prog', ['f1.c', 'f2.c', 'f3.c'])
550 Running &SCons; with the <literal>--tree=all</literal>
556 % <userinput>scons -Q --tree=all</userinput>
557 cc -o f1.o -c -I. f1.c
558 cc -o f2.o -c -I. f2.c
559 cc -o f3.o -c -I. f3.c
560 cc -o prog f1.o f2.o f3.o
590 The tree will also be printed when the
591 <literal>-n</literal> (no execute) option is used,
592 which allows you to examine the dependency graph
593 for a configuration without actually
594 rebuilding anything in the tree.
600 The <literal>--tree</literal> option only prints
601 the dependency graph for the specified targets
602 (or the default target(s) if none are specified on the command line).
603 So if you specify a target like <filename>f2.o</filename>
605 the <literal>--tree</literal> option will only
606 print the dependency graph for that file:
611 % <userinput>scons -Q --tree=all f2.o</userinput>
612 cc -o f2.o -c -I. f2.c
620 This is, of course, useful for
621 restricting the output from a very large
622 build configuration to just a
623 portion in which you're interested.
624 Multiple targets are fine,
625 in which case a tree will be printed
626 for each specified target:
631 % <userinput>scons -Q --tree=all f1.o f3.o</userinput>
632 cc -o f1.o -c -I. f1.c
636 cc -o f3.o -c -I. f3.c
644 The <literal>status</literal> argument may be used
645 to tell &SCons; to print status information about
646 each file in the dependency graph:
651 % <userinput>scons -Q --tree=status</userinput>
652 cc -o f1.o -c -I. f1.c
653 cc -o f2.o -c -I. f2.c
654 cc -o f3.o -c -I. f3.c
655 cc -o prog f1.o f2.o f3.o
657 R = exists in repository only
696 Note that <literal>--tree=all,status</literal> is equivalent;
697 the <literal>all</literal>
698 is assumed if only <literal>status</literal> is present.
699 As an alternative to <literal>all</literal>,
700 you can specify <literal>--tree=derived</literal>
701 to have &SCons; only print derived targets
703 skipping source files
704 (like <filename>.c</filename> and <filename>.h</filename> files):
709 % <userinput>scons -Q --tree=derived</userinput>
710 cc -o f1.o -c -I. f1.c
711 cc -o f2.o -c -I. f2.c
712 cc -o f3.o -c -I. f3.c
713 cc -o prog f1.o f2.o f3.o
726 You can use the <literal>status</literal>
727 modifier with <literal>derived</literal> as well:
732 % <userinput>scons -Q --tree=derived,status</userinput>
733 cc -o f1.o -c -I. f1.c
734 cc -o f2.o -c -I. f2.c
735 cc -o f3.o -c -I. f3.c
736 cc -o prog f1.o f2.o f3.o
738 R = exists in repository only
760 Note that the order of the <literal>--tree=</literal>
761 arguments doesn't matter;
762 <literal>--tree=status,derived</literal> is
763 completely equivalent.
769 The default behavior of the <literal>--tree</literal> option
770 is to repeat all of the dependencies each time the library dependency
771 (or any other dependency file) is encountered in the tree.
772 If certain target files share other target files,
773 such as two programs that use the same library:
778 env = Environment(CPPPATH = ['.'],
781 env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
782 env.Program('prog1.c')
783 env.Program('prog2.c')
788 Then there can be a <emphasis>lot</emphasis> of repetition in the
789 <literal>--tree=</literal> output:
794 % <userinput>scons -Q --tree=all</userinput>
795 cc -o f1.o -c -I. f1.c
796 cc -o f2.o -c -I. f2.c
797 cc -o f3.o -c -I. f3.c
798 ar rc libfoo.a f1.o f2.o f3.o
800 cc -o prog1.o -c -I. prog1.c
801 cc -o prog1 prog1.o -L. -lfoo
802 cc -o prog2.o -c -I. prog2.c
803 cc -o prog2 prog2.o -L. -lfoo
869 In a large configuration with many internal libraries
871 this can very quickly lead to huge output trees.
872 To help make this more manageable,
873 a <literal>prune</literal> modifier may
874 be added to the option list,
875 in which case &SCons;
876 will print the name of a target that has
877 already been visited during the tree-printing
878 in <literal>[square brackets]</literal>
879 as an indication that the dependencies
880 of the target file may be found
881 by looking farther up the tree:
886 % <userinput>scons -Q --tree=prune</userinput>
887 cc -o f1.o -c -I. f1.c
888 cc -o f2.o -c -I. f2.c
889 cc -o f3.o -c -I. f3.c
890 ar rc libfoo.a f1.o f2.o f3.o
892 cc -o prog1.o -c -I. prog1.c
893 cc -o prog1 prog1.o -L. -lfoo
894 cc -o prog2.o -c -I. prog2.c
895 cc -o prog2 prog2.o -L. -lfoo
933 Like the <literal>status</literal> keyword,
934 the <literal>prune</literal> argument by itself
935 is equivalent to <literal>--tree=all,prune</literal>.
943 <title>How is &SCons; Constructing the Command Lines It Executes? the &debug-presub; Option</title>
947 Sometimes it's useful to look at the
948 pre-substitution string
949 that &SCons; uses to generate
950 the command lines it executes.
951 This can be done with the &debug-presub; option:
959 Have to capture output here, otherwise the - -debug=presub output
960 shows the Python functions from the sconsdoc.py execution wrapper
961 used to generate this manual, not the underlying command-line strings.
963 <scons_output example="presub">
964 <scons_output_command>scons -Q - -debug=presub</scons_output_command>
970 % <userinput>scons -Q --debug=presub</userinput>
971 Building prog.o with action:
972 $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCOMCOM $SOURCES
973 cc -o prog.o -c -I. prog.c
974 Building prog with action:
983 <title>Where is &SCons; Searching for Libraries? the &debug-findlibs; Option</title>
987 To get some insight into what library names
988 &SCons; is searching for,
989 and in which directories it is searching,
990 Use the <literal>--debug=findlibs</literal> option.
991 Given the following input &SConstruct; file:
996 env = Environment(LIBPATH = ['libs1', 'libs2'])
997 env.Program('prog.c', LIBS=['foo', 'bar'])
1002 And the libraries <filename>libfoo.a</filename>
1003 and <filename>libbar.a</filename>
1004 in <filename>libs1</filename> and <filename>libs2</filename>,
1006 use of the <literal>--debug=findlibs</literal> option yields:
1011 % <userinput>scons -Q --debug=findlibs</userinput>
1012 findlibs: looking for 'libfoo.a' in 'libs1' ...
1013 findlibs: ... FOUND 'libfoo.a' in 'libs1'
1014 findlibs: looking for 'libfoo.so' in 'libs1' ...
1015 findlibs: looking for 'libfoo.so' in 'libs2' ...
1016 findlibs: looking for 'libbar.a' in 'libs1' ...
1017 findlibs: looking for 'libbar.a' in 'libs2' ...
1018 findlibs: ... FOUND 'libbar.a' in 'libs2'
1019 findlibs: looking for 'libbar.so' in 'libs1' ...
1020 findlibs: looking for 'libbar.so' in 'libs2' ...
1021 cc -o prog.o -c prog.c
1022 cc -o prog prog.o -Llibs1 -Llibs2 -lfoo -lbar
1031 <title>What Implicit Dependencies Did the &SCons; Scanner find? the &debug-includes; Option</title>
1035 XXX explain the - - debug=includes option
1039 <scons_example name="includes">
1040 <file name="SConstruct" printme="1">
1041 env = Environment(CPPPATH = ['inc1', 'inc2'])
1042 env.Program('prog.c')
1044 <file name="prog.c">
1049 <file name="inc1/file1.h">
1052 <file name="inc2/file2.h">
1057 <scons_output example="includes">
1058 <scons_output_command>scons -Q - - debug=includes prog</scons_output_command>
1067 <title>Where is &SCons; Blowing Up? the &debug-stacktrace; Option</title>
1071 In general, &SCons; tries to keep its error
1072 messages short and informative.
1073 That means we usually try to avoid showing
1074 the stack traces that are familiar
1075 to experienced Python programmers,
1076 since they usually contain much more
1077 information than is useful to most people.
1083 For example, the following &SConstruct; file:
1093 Generates the following error if the
1094 <filename>prog.c</filename> file
1100 % <userinput>scons -Q</userinput>
1101 scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'.
1107 the error is pretty obvious.
1109 and you wanted to try to get more information
1111 the &debug-stacktrace; option
1112 would show you exactly where in the &SCons; source code
1118 % <userinput>scons -Q --debug=stacktrace</userinput>
1119 scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'.
1120 scons: internal stack trace:
1121 File "bootstrap/src/engine/SCons/Job.py", line 199, in start
1123 File "bootstrap/src/engine/SCons/Script/Main.py", line 167, in prepare
1124 return SCons.Taskmaster.OutOfDateTask.prepare(self)
1125 File "bootstrap/src/engine/SCons/Taskmaster.py", line 190, in prepare
1127 File "bootstrap/src/engine/SCons/Executor.py", line 397, in prepare
1128 raise SCons.Errors.StopError, msg % (s, self.batches[0].targets[0])
1133 Of course, if you do need to dive into the &SCons; source code,
1134 we'd like to know if, or how,
1135 the error messages or troubleshooting options
1136 could have been improved to avoid that.
1137 Not everyone has the necessary time or
1138 Python skill to dive into the source code,
1139 and we'd like to improve &SCons;
1140 for those people as well...
1148 <title>How is &SCons; Making Its Decisions? the &taskmastertrace; Option</title>
1152 The internal &SCons; subsystem that handles walking
1153 the dependency graph
1154 and controls the decision-making about what to rebuild
1155 is the <literal>Taskmaster</literal>.
1156 &SCons; supports a <literal>--taskmastertrace</literal>
1157 option that tells the Taskmaster to print
1158 information about the children (dependencies)
1159 of the various Nodes on its walk down the graph,
1160 which specific dependent Nodes are being evaluated,
1167 The <literal>--taskmastertrace</literal> option
1168 takes as an argument the name of a file in
1169 which to put the trace output,
1170 with <filename>-</filename> (a single hyphen)
1171 indicating that the trace messages
1172 should be printed to the standard output:
1177 env = Environment(CPPPATH = ['.'])
1178 env.Program('prog.c')
1182 % <userinput>scons -Q --taskmastertrace=- prog</userinput>
1184 Taskmaster: Looking for a node to evaluate
1185 Taskmaster: Considering node <no_state 0 'prog'> and its children:
1186 Taskmaster: <no_state 0 'prog.o'>
1187 Taskmaster: adjusted ref count: <pending 1 'prog'>, child 'prog.o'
1188 Taskmaster: Considering node <no_state 0 'prog.o'> and its children:
1189 Taskmaster: <no_state 0 'prog.c'>
1190 Taskmaster: <no_state 0 'inc.h'>
1191 Taskmaster: adjusted ref count: <pending 1 'prog.o'>, child 'prog.c'
1192 Taskmaster: adjusted ref count: <pending 2 'prog.o'>, child 'inc.h'
1193 Taskmaster: Considering node <no_state 0 'prog.c'> and its children:
1194 Taskmaster: Evaluating <pending 0 'prog.c'>
1196 Task.make_ready_current(): node <pending 0 'prog.c'>
1197 Task.prepare(): node <up_to_date 0 'prog.c'>
1198 Task.executed_with_callbacks(): node <up_to_date 0 'prog.c'>
1199 Task.postprocess(): node <up_to_date 0 'prog.c'>
1200 Task.postprocess(): removing <up_to_date 0 'prog.c'>
1201 Task.postprocess(): adjusted parent ref count <pending 1 'prog.o'>
1203 Taskmaster: Looking for a node to evaluate
1204 Taskmaster: Considering node <no_state 0 'inc.h'> and its children:
1205 Taskmaster: Evaluating <pending 0 'inc.h'>
1207 Task.make_ready_current(): node <pending 0 'inc.h'>
1208 Task.prepare(): node <up_to_date 0 'inc.h'>
1209 Task.executed_with_callbacks(): node <up_to_date 0 'inc.h'>
1210 Task.postprocess(): node <up_to_date 0 'inc.h'>
1211 Task.postprocess(): removing <up_to_date 0 'inc.h'>
1212 Task.postprocess(): adjusted parent ref count <pending 0 'prog.o'>
1214 Taskmaster: Looking for a node to evaluate
1215 Taskmaster: Considering node <pending 0 'prog.o'> and its children:
1216 Taskmaster: <up_to_date 0 'prog.c'>
1217 Taskmaster: <up_to_date 0 'inc.h'>
1218 Taskmaster: Evaluating <pending 0 'prog.o'>
1220 Task.make_ready_current(): node <pending 0 'prog.o'>
1221 Task.prepare(): node <executing 0 'prog.o'>
1222 Task.execute(): node <executing 0 'prog.o'>
1223 cc -o prog.o -c -I. prog.c
1224 Task.executed_with_callbacks(): node <executing 0 'prog.o'>
1225 Task.postprocess(): node <executed 0 'prog.o'>
1226 Task.postprocess(): removing <executed 0 'prog.o'>
1227 Task.postprocess(): adjusted parent ref count <pending 0 'prog'>
1229 Taskmaster: Looking for a node to evaluate
1230 Taskmaster: Considering node <pending 0 'prog'> and its children:
1231 Taskmaster: <executed 0 'prog.o'>
1232 Taskmaster: Evaluating <pending 0 'prog'>
1234 Task.make_ready_current(): node <pending 0 'prog'>
1235 Task.prepare(): node <executing 0 'prog'>
1236 Task.execute(): node <executing 0 'prog'>
1238 Task.executed_with_callbacks(): node <executing 0 'prog'>
1239 Task.postprocess(): node <executed 0 'prog'>
1241 Taskmaster: Looking for a node to evaluate
1242 Taskmaster: No candidate anymore.
1247 The <literal>--taskmastertrace</literal> option
1248 doesn't provide information about the actual
1249 calculations involved in deciding if a file is up-to-date,
1250 but it does show all of the dependencies
1251 it knows about for each Node,
1252 and the order in which those dependencies are evaluated.
1253 This can be useful as an alternate way to determine
1254 whether or not your &SCons; configuration,
1255 or the implicit dependency scan,
1256 has actually identified all the correct dependencies
1267 <title>Where Are My Build Bottlenecks? the &profile; Option</title>
1271 XXX explain the - - profile= option
1282 <title>Troubleshooting Shared Caching: the &cache-debug; Option</title>
1286 XXX describe the - - cache-debug option
1287 XXX maybe point to the caching.in chapter?