diff options
author | Steven Knight <knight@baldmt.com> | 2008-08-09 18:23:26 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2008-08-09 18:23:26 (GMT) |
commit | d0c5748eb01e8303b6221afad432cb908672c161 (patch) | |
tree | 962a16c94759f57f27387cb315e72a6a028aa443 /doc/user/output.in | |
parent | 2f5c0f667910c8c9db5e93842f5f6201409f704e (diff) | |
download | SCons-d0c5748eb01e8303b6221afad432cb908672c161.zip SCons-d0c5748eb01e8303b6221afad432cb908672c161.tar.gz SCons-d0c5748eb01e8303b6221afad432cb908672c161.tar.bz2 |
Merged revisions 3057-3059,3061-3264 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core
........
r3061 | stevenknight | 2008-06-10 10:06:24 -0700 (Tue, 10 Jun 2008) | 3 lines
Issue 2085: Fix man page indentation under Debian systems.
Also add escape characters to the beginnings of some necessary lines.
........
r3063 | GregNoel | 2008-06-10 17:50:28 -0700 (Tue, 10 Jun 2008) | 1 line
Add David as a member; parametize input file
........
r3064 | stevenknight | 2008-06-11 07:22:23 -0700 (Wed, 11 Jun 2008) | 3 lines
Issue 1973: Clarify the man page description of the SConscript(src_dir)
argument.
........
r3065 | stevenknight | 2008-06-11 11:25:00 -0700 (Wed, 11 Jun 2008) | 3 lines
Issues 1974, 1999: document {Add,Get,Set}Option(). Reorganize the
section a little bit, other minor edits.
........
r3066 | garyo | 2008-06-12 19:53:51 -0700 (Thu, 12 Jun 2008) | 1 line
Document GetBuildFailures in Users Guide. Closes issue #1989.
........
r3067 | stevenknight | 2008-06-14 06:42:07 -0700 (Sat, 14 Jun 2008) | 2 lines
Fix build errors from undefined &GetBuildFailures; entity in doc.
........
r3073 | garyo | 2008-06-14 18:40:20 -0700 (Sat, 14 Jun 2008) | 1 line
Fix issue #1538 (Handling of string argument in Action.Action). Includes test.
........
r3074 | garyo | 2008-06-14 19:11:30 -0700 (Sat, 14 Jun 2008) | 1 line
doc: Trivial man page typo fix.
........
r3075 | stevenknight | 2008-06-15 14:35:13 -0700 (Sun, 15 Jun 2008) | 3 lines
Add a test to make sure the env.RCS() applied to an individual file works
correctly when the checked-out copy is changed.
........
r3076 | stevenknight | 2008-06-15 23:07:17 -0700 (Sun, 15 Jun 2008) | 2 lines
Issue 2025: User's Guide updates from Randall Spangler's review.
........
r3078 | stevenknight | 2008-06-16 06:26:13 -0700 (Mon, 16 Jun 2008) | 2 lines
Issue 1990: Document the Requires() function in the Users's Guide.
........
r3082 | stevenknight | 2008-06-16 19:31:00 -0700 (Mon, 16 Jun 2008) | 3 lines
Fix the second example in the AddMethod() chapter. Show the Windows
output generating a resource file. Other copyedits.
........
r3083 | stevenknight | 2008-06-17 06:44:02 -0700 (Tue, 17 Jun 2008) | 2 lines
Fix misspelled entity: &Builders; => &Builder;s.
........
r3084 | stevenknight | 2008-06-17 08:30:13 -0700 (Tue, 17 Jun 2008) | 3 lines
Issue 1588: - Document suggested use of the Viual C/C++ /FC option to fix
the ability to double-click on file names in compilation error messages.
........
r3085 | stevenknight | 2008-06-17 08:50:33 -0700 (Tue, 17 Jun 2008) | 3 lines
Issue 1687: Document the need to use Clean() for any SideEffect()
files that must be explicitly removed when their targets are removed.
........
r3086 | stevenknight | 2008-06-17 10:59:28 -0700 (Tue, 17 Jun 2008) | 2 lines
Typo fix in the new SideEffect() paragraph. (Gary Oberbrunner)
........
r3088 | cournape | 2008-06-17 19:55:27 -0700 (Tue, 17 Jun 2008) | 3 lines
Initialized merge tracking via "svnmerge" with revisions "1-3087" from
http://scons.tigris.org/svn/scons/branches/vs_revamp
........
r3094 | stevenknight | 2008-06-19 09:52:16 -0700 (Thu, 19 Jun 2008) | 3 lines
Change the User's Guide to use the new Variables object and its
associated function for controlling command-line build variables.
........
r3115 | stevenknight | 2008-06-25 06:46:36 -0700 (Wed, 25 Jun 2008) | 2 lines
Issue 2072: end indentation after generated Builder text.
........
r3116 | stevenknight | 2008-06-25 19:07:15 -0700 (Wed, 25 Jun 2008) | 2 lines
Reorganize the command-line arguments chapter.
........
r3117 | stevenknight | 2008-06-25 19:13:58 -0700 (Wed, 25 Jun 2008) | 2 lines
Editing pass for formatting in the Glob() sections.
........
r3118 | stevenknight | 2008-06-25 19:23:09 -0700 (Wed, 25 Jun 2008) | 3 lines
Wording changing: Preventing => Controlling, because the chapter
also talks about how to clean additional targets.
........
r3119 | stevenknight | 2008-06-25 19:50:41 -0700 (Wed, 25 Jun 2008) | 2 lines
Fix missing </literal> tags, minor wording fix.
........
r3120 | stevenknight | 2008-06-25 19:58:34 -0700 (Wed, 25 Jun 2008) | 2 lines
Add "the Default Function" to the appropriate subsection title.
........
r3121 | stevenknight | 2008-06-26 08:33:43 -0700 (Thu, 26 Jun 2008) | 2 lines
Issue 1988: Document the Variables.UnknownVariables() method.
........
r3122 | stevenknight | 2008-06-26 08:35:51 -0700 (Thu, 26 Jun 2008) | 3 lines
Remove comments listing some of the variables that have been
documented recently.
........
r3123 | stevenknight | 2008-06-26 12:42:53 -0700 (Thu, 26 Jun 2008) | 2 lines
Issue 2118: Fix incorrectly swapped man page text. (Alexey Zezukin)
........
r3124 | bdbaddog | 2008-06-26 21:23:46 -0700 (Thu, 26 Jun 2008) | 2 lines
Fix bug 2108 - duplicate text in description of interactive mode
........
r3125 | stevenknight | 2008-06-27 21:54:56 -0700 (Fri, 27 Jun 2008) | 3 lines
Issue 1993: Document the $*COMSTR variables, the Progress() function,
and create a common "Controlling Build Output" chapter.
........
r3126 | garyo | 2008-06-28 05:46:44 -0700 (Sat, 28 Jun 2008) | 1 line
Fix issue 2105; temporarily omit doc saying that SetOption can override user-created Options (until that is implemented).
........
r3127 | stevenknight | 2008-06-28 07:29:18 -0700 (Sat, 28 Jun 2008) | 2 lines
Issue 1747: Explicitly document use of Node lists as input to Depends().
........
r3128 | stevenknight | 2008-06-28 07:48:32 -0700 (Sat, 28 Jun 2008) | 6 lines
White space change: indent the construction environment sections
further to make way for combining this chapter with others to make
one big "Controlling Environments" chapter.
Also, get rid of some now-unnecessary doc from the old Cons classic
POD, that was taking up space here waiting to be documented.
........
r3129 | cournape | 2008-06-29 01:56:30 -0700 (Sun, 29 Jun 2008) | 3 lines
Initialized merge tracking via "svnmerge" with revisions "1-3128" from
http://scons.tigris.org/svn/scons/branches/trygrep
........
r3143 | stevenknight | 2008-07-02 10:29:39 -0700 (Wed, 02 Jul 2008) | 3 lines
Initialized merge tracking via "svnmerge" with revisions "1-3142" from
http://scons.tigris.org/svn/scons/branches/sgk_lookup
........
r3181 | stevenknight | 2008-07-08 07:17:27 -0700 (Tue, 08 Jul 2008) | 4 lines
Reorganize the discussion of different environments into one chapter.
Document the SetDefault(), PrependUnique(), AppendUnique(),
PrependENVPath() and AppendENVPath() functions.
........
r3182 | stevenknight | 2008-07-08 08:47:55 -0700 (Tue, 08 Jul 2008) | 2 lines
Issue 1998: Docment the ARGLIST variable in the User's Guide.
........
r3194 | GregNoel | 2008-07-09 23:16:51 -0700 (Wed, 09 Jul 2008) | 1 line
remove unnecessary trailing spaces on lines
........
r3204 | stevenknight | 2008-07-11 08:29:18 -0700 (Fri, 11 Jul 2008) | 2 lines
Issue 1853: Remove referenc to SCons.Util.CLVar from a doc example.
........
r3206 | GregNoel | 2008-07-12 02:08:19 -0700 (Sat, 12 Jul 2008) | 1 line
Another go at describing VariantDir()
........
r3213 | stevenknight | 2008-07-13 08:57:57 -0700 (Sun, 13 Jul 2008) | 3 lines
Set /branches/comments in svnmerge-integrated property to allow
merging changes in both directions.
........
r3217 | stevenknight | 2008-07-16 06:52:44 -0700 (Wed, 16 Jul 2008) | 2 lines
Update the copyright year in the User's Guide.
........
r3218 | stevenknight | 2008-07-16 07:08:52 -0700 (Wed, 16 Jul 2008) | 3 lines
Issue 1881: Add man page text clarifying the behavior of
Add{Pre,Post}Action() when multiple targets are specified.
........
r3223 | stevenknight | 2008-07-18 08:18:45 -0700 (Fri, 18 Jul 2008) | 3 lines
Initialized merge tracking via "svnmerge" with revisions "1-3222" from
http://scons.tigris.org/svn/scons/branches/sgk_subst
........
r3231 | stevenknight | 2008-07-22 01:58:11 -0700 (Tue, 22 Jul 2008) | 4 lines
Enhance MSVSProject() tests so they're runnable on any system, regardless
of whether Visual Studio is installed, or if it's even a Windows system
at all.
........
r3237 | GregNoel | 2008-07-26 00:07:49 -0700 (Sat, 26 Jul 2008) | 1 line
Issue 1983: Document ParseConfig, MergeFlags, and ParseFlags for the Users' Guide
........
r3238 | stevenknight | 2008-07-26 08:38:18 -0700 (Sat, 26 Jul 2008) | 3 lines
Follow-ons for building the User's Guide with Greg's recent additions
for MergeFlags() and ParseFlags().
........
r3239 | stevenknight | 2008-07-26 09:52:40 -0700 (Sat, 26 Jul 2008) | 3 lines
Re-arrange some sections talking about creating construction environments
and fetching/expanding variables.
........
r3240 | stevenknight | 2008-07-26 12:16:11 -0700 (Sat, 26 Jul 2008) | 2 lines
Stylistic editing of new {Merge,Parse}{Config,Flags} sections.
........
r3241 | GregNoel | 2008-07-26 12:42:42 -0700 (Sat, 26 Jul 2008) | 1 line
Issue 1987: Document SideEffect for Users' Guide (incomplete)
........
r3242 | stevenknight | 2008-07-26 13:27:56 -0700 (Sat, 26 Jul 2008) | 2 lines
Correct dumb XML mistakes in my last checkin.
........
r3243 | stevenknight | 2008-07-26 13:34:05 -0700 (Sat, 26 Jul 2008) | 2 lines
One-character typo. Gah.
........
r3244 | stevenknight | 2008-07-26 13:44:14 -0700 (Sat, 26 Jul 2008) | 2 lines
Issue 1977,1980: document the Exit() and Flatten() functions.
........
r3245 | stevenknight | 2008-07-27 10:24:12 -0700 (Sun, 27 Jul 2008) | 14 lines
Updates to the new SideEffect section (kudos to Greg).
While working on this, Greg discovered a bug (issue #2154) that prevents
a SideEffect() file from being used as input to another builder call; it
makes the builder target not get build when run in paralle (e.g. -j2)...
:-( So this patch comments out that section of Greg's section.
This also contains my usual editing pass. In this case I changed some
of the examples and added a bunch of text to try to help clarify some
things that seemed important. I also added a closing paragraph warning
that SideEffect() really shouldn't be used as an alternative to specifying
multiple target files in a Builder call when a command builds more than
one file that you care about.
........
r3246 | stevenknight | 2008-07-27 10:31:17 -0700 (Sun, 27 Jul 2008) | 2 lines
Proofreading edits of the MergeFlags() section. (Greg Noel)
........
r3247 | stevenknight | 2008-07-27 11:17:27 -0700 (Sun, 27 Jul 2008) | 2 lines
Issue 1976: document ensure{Python,SCons}Version() in the User's Guide.
........
r3249 | GregNoel | 2008-07-28 15:57:00 -0700 (Mon, 28 Jul 2008) | 1 line
Add svn-bisect script
........
Diffstat (limited to 'doc/user/output.in')
-rw-r--r-- | doc/user/output.in | 681 |
1 files changed, 681 insertions, 0 deletions
diff --git a/doc/user/output.in b/doc/user/output.in new file mode 100644 index 0000000..02d7484 --- /dev/null +++ b/doc/user/output.in @@ -0,0 +1,681 @@ +<!-- + + __COPYRIGHT__ + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + A key aspect of creating a usable build configuration + is providing good output from the build + so its users can readily understand + what the build is doing + and get information about how to control the build. + &SCons; provides several ways of + controlling output from the build configuration + to help make the build + more useful and understandable. + + </para> + + <section> + <title>Providing Build Help: the &Help; Function</title> + + <para> + + It's often very useful to be able to give + users some help that describes the + specific targets, build options, etc., + that can be used for your build. + &SCons; provides the &Help; function + to allow you to specify this help text: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + Help(""" + Type: 'scons program' to build the production program, + 'scons debug' to build the debug version. + """) + </file> + </scons_example> + + <para> + + (Note the above use of the Python triple-quote syntax, + which comes in very handy for + specifying multi-line strings like help text.) + + </para> + + <para> + + When the &SConstruct; or &SConscript; files + contain such a call to the &Help; function, + the specified help text will be displayed in response to + the &SCons; <literal>-h</literal> option: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> + + <para> + + The &SConscript; files may contain + multiple calls to the &Help; function, + in which case the specified text(s) + will be concatenated when displayed. + This allows you to split up the + help text across multiple &SConscript; files. + In this situation, the order in + which the &SConscript; files are called + will determine the order in which the &Help; functions are called, + which will determine the order in which + the various bits of text will get concatenated. + + </para> + + <para> + + Another use would be to make the help text conditional + on some variable. + For example, suppose you only want to display + a line about building a Windows-only + version of a program when actually + run on Windows. + The following &SConstruct; file: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + env = Environment() + + Help("\nType: 'scons program' to build the production program.\n") + + if env['PLATFORM'] == 'win32': + Help("\nType: 'scons windebug' to build the Windows debug version.\n") + </file> + </scons_example> + + <para> + + Will display the complete help text on Windows: + + </para> + + <scons_output example="ex2" os="win32"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> + + <para> + + But only show the relevant option on a Linux or UNIX system: + + </para> + + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> + + <para> + + If there is no &Help; text in the &SConstruct; or + &SConscript; files, + &SCons; will revert to displaying its + standard list that describes the &SCons; command-line + options. + This list is also always displayed whenever + the <literal>-H</literal> option is used. + + </para> + + </section> + + <section> + <title>Controlling How &SCons; Prints Build Commands: the <envar>$*COMSTR</envar> Variables</title> + + <para> + + Sometimes the commands executed + to compile object files or link programs + (or build other targets) + can get very long, + long enough to make it difficult for users + to distinguish error messages or + other important build output + from the commands themselves. + All of the default <envar>$*COM</envar> variables + that specify the command lines + used to build various types of target files + have a corresponding <envar>$*COMSTR</envar> variable + that can be set to an alternative + string that will be displayed + when the target is built. + + </para> + + <para> + + For example, suppose you want to + have &SCons; display a + <literal>"Compiling"</literal> + message whenever it's compiling an object file, + and a + <literal>"Linking"</literal> + when it's linking an executable. + You could write a &SConstruct; file + that looks like: + + </para> + + <scons_example name="COMSTR"> + <file name="SConstruct" printme="1"> + env = Environment(CCCOMSTR = "Compiling $TARGET", + LINKCOMSTR = "Linking $TARGET") + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + Which would then yield the output: + + </para> + + <!-- + + <scons_output example="COMSTR" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + Compiling foo.o + Linking foo + </screen> + + <para> + + &SCons; performs complete variable substitution + on <envar>$*COMSTR</envar> variables, + so they have access to all of the + standard variables like &cv-TARGET; &cv-SOURCES;, etc., + as well as any construction variables + that happen to be configured in + the construction environment + used to build a specific target. + + </para> + + <para> + + Of course, sometimes it's still important to + be able to see the exact command + that &SCons; will execute to build a target. + For example, you may simply need to verify + that &SCons; is configured to supply + the right options to the compiler, + or a developer may want to + cut-and-paste a comiloe command + to add a few options + for a custom test. + + </para> + + <para> + + One common way to give users + control over whether or not + &SCons; should print the actual command line + or a short, configured summary + is to add support for a + <varname>VERBOSE</varname> + command-line variable to your &SConstruct; file. + A simple configuration for this might look like: + + </para> + + <scons_example name="COMSTR-VERBOSE"> + <file name="SConstruct" printme="1"> + env = Environment() + if ARGUMENTS.get('VERBOSE') != "1': + env['CCCOMSTR'] = "Compiling $TARGET" + env['LINKCOMSTR'] = "Linking $TARGET" + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + + By only setting the appropriate + <envar>$*COMSTR</envar> variables + if the user specifies + <literal>VERBOSE=1</literal> + on the command line, + the user has control + over how &SCons; + displays these particular command lines: + + </para> + + <!-- + + <scons_output example="COMSTR-VERBOSE" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q VERBOSE=1</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + Compiling foo.o + Linking foo + % <userinput>scons -Q -c</userinput> + Removed foo.o + Removed foo + % <userinput>scons -Q VERBOSE=1</userinput> + cc -o foo.o -c foo.c + cc -o foo foo.o + </screen> + + </section> + + <section> + <title>Providing Build Progress Output: the &Progress; Function</title> + + <para> + + Another aspect of providing good build output + is to give the user feedback + about what &SCons; is doing + even when nothing is being built at the moment. + This can be especially true for large builds + when most of the targets are already up-to-date. + Because &SCons; can take a long time + making absolutely sure that every + target is, in fact, up-to-date + with respect to a lot of dependency files, + it can be easy for users to mistakenly + conclude that &SCons; is hung + or that there is some other problem with the build. + + </para> + + <para> + + One way to deal with this perception + is to configure &SCons; to print something to + let the user know what it's "thinking about." + The &Progress; function + allows you to specify a string + that will be printed for every file + that &SCons; is "considering" + while it is traversing the dependency graph + to decide what targets are or are not up-to-date. + + </para> + + <scons_example name="Progress-TARGET"> + <file name="SConstruct" printme="1"> + Progress('Evaluating $TARGET\n') + Program('f1.c') + Program('f2.c') + </file> + <file name="f1.c"> + f1.c + </file> + <file name="f2.c"> + f2.c + </file> + </scons_example> + + <para> + + Note that the &Progress; function does not + arrange for a newline to be printed automatically + at the end of the string (as does the Python + <literal>print</literal> statement), + and we must specify the + <literal>\n</literal> + that we want printed at the end of the configured string. + This configuration, then, + will have &SCons; + print that it is <literal>Evaluating</literal> + each file that it encounters + in turn as it traverses the dependency graph: + + </para> + + <scons_output example="Progress-TARGET" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Of course, normally you don't want to add + all of these additional lines to your build output, + as that can make it difficult for the user + to find errors or other important messages. + A more useful way to display + this progress might be + to have the file names printed + directly to the user's screen, + not to the same standard output + stream where build output is printed, + and to use a carriage return character + (<literal>\r</literal>) + so that each file name gets re-printed on the same line. + Such a configuration would look like: + + </para> + + <sconstruct> + Progress('$TARGET\r', + file=open('/dev/tty', 'w'), + overwrite=True) + Program('f1.c') + Program('f2.c') + </sconstruct> + + <para> + + Note that we also specified the + <literal>overwrite=True</literal> argument + to the &Progress; function, + which causes &SCons; to + "wipe out" the previous string with space characters + before printing the next &Progress; string. + Without the + <literal>overwrite=True</literal> argument, + a shorter file name would not overwrite + all of the charactes in a longer file name that + precedes it, + making it difficult to tell what the + actual file name is on the output. + Also note that we opened up the + <filename>/dev/tty</filename> file + for direct access (on POSIX) to + the user's screen. + On Windows, the equivalent would be to open + the <filename>con:</filename> file name. + + </para> + + <para> + + Also, it's important to know that although you can use + <literal>$TARGET</literal> to substitute the name of + the node in the string, + the &Progress; function does <emphasis>not</emphasis> + perform general variable substitution + (because there's not necessarily a construction + environment involved in evaluating a node + like a source file, for example). + + </para> + + <para> + + You can also specify a list of strings + to the &Progress; function, + in which case &SCons; will + display each string in turn. + This can be used to implement a "spinner" + by having &SCons; cycle through a + sequence of strings: + + </para> + + <sconstruct> + Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5) + Program('f1.c') + Program('f2.c') + </sconstruct> + + <para> + + Note that here we have also used the + <literal>interval=</literal> + keyword argument to have &SCons; + only print a new "spinner" string + once every five evaluated nodes. + Using an <literal>interval=</literal> count, + even with strings that use <literal>$TARGET</literal> like + our examples above, + can be a good way to lessen the + work that &SCons; expends printing &Progress; strings, + while still giving the user feedback + that indicates &SCons; is still + working on evaluating the build. + + </para> + + <para> + + Lastly, you can have direct control + over how to print each evaluated node + by passing a Python function + (or other Python callable) + to the &Progress function. + Your function will be called + for each evaluated node, + allowing you to + implement more sophisticated logic + like adding a counter: + + </para> + + <scons_example name="Progress-callable"> + <file name="SConstruct" printme="1"> + screen = open('/dev/tty', 'w') + count = 0 + def progress_function(node) + count += 1 + screen.write('Node %4d: %s\r' % (count, node)) + + Progress(progress_function) + </file> + </scons_example> + + <para> + + Of course, if you choose, + you could completely ignore the + <varname>node</varname> argument to the function, + and just print a count, + or anything else you wish. + + </para> + + <para> + + (Note that there's an obvious follow-on question here: + how would you find the total number of nodes + that <emphasis>will be</emphasis> + evaluated so you can tell the user how + close the build is to finishing? + Unfortunately, in the general case, + there isn't a good way to do that, + short of having &SCons; evaluate its + dependency graph twice, + first to count the total and + the second time to actually build the targets. + This would be necessary because + you can't know in advance which + target(s) the user actually requested + to be built. + The entire build may consist of thousands of Nodes, + for example, + but maybe the user specifically requested + that only a single object file be built.) + + </para> + + </section> + + <section> + <title>Printing Detailed Build Status: the &GetBuildFailures; Function</title> + + <para> + + SCons, like most build tools, returns zero status to + the shell on success and nonzero status on failure. + Sometimes it's useful to give more information about + the build status at the end of the run, for instance + to print an informative message, send an email, or + page the poor slob who broke the build. + + </para> + + <para> + + SCons provides a &GetBuildFailures; method that + you can use in a python <function>atexit</function> function + to get a list of objects describing the actions that failed + while attempting to build targets. There can be more + than one if you're using <literal>-j</literal>. Here's a + simple example: + + </para> + + <scons_example name="gbf1"> + <file name="SConstruct" printme="1"> + import atexit + + def print_build_failures(): + from SCons.Script import GetBuildFailures + for bf in GetBuildFailures(): + print "%s failed: %s" % (bf.node, bf.errstr) + atexit.register(print_build_failures) + </file> + </scons_example> + + <para> + + The <function>atexit.register</function> call + registers <function>print_build_failures</function> + as an <function>atexit</function> callback, to be called + before &SCons; exits. When that function is called, + it calls &GetBuildFailures; to fetch the list of failed objects. + See the man page + for the detailed contents of the returned objects; + some of the more useful attributes are + <literal>.node</literal>, + <literal>.errstr</literal>, + <literal>.filename</literal>, and + <literal>.command</literal>. + The <literal>filename</literal> is not necessarily + the same file as the <literal>node</literal>; the + <literal>node</literal> is the target that was + being built when the error occurred, while the + <literal>filename</literal>is the file or dir that + actually caused the error. + Note: only call &GetBuildFailures; at the end of the + build; calling it at any other time is undefined. + + </para> + + <para> + + Here is a more complete example showing how to + turn each element of &GetBuildFailures; into a string: + + </para> + + <scons_example name="gbf2"> + <file name="SConstruct" printme="1"> + # Make the build fail if we pass fail=1 on the command line + if ARGUMENTS.get('fail', 0): + Command('target', 'source', ['/bin/false']) + + def bf_to_str(bf): + """Convert an element of GetBuildFailures() to a string + in a useful way.""" + import SCons.Errors + if bf is None: # unknown targets product None in list + return '(unknown tgt)' + elif isinstance(bf, SCons.Errors.StopError): + return str(bf) + elif bf.node: + return str(bf.node) + ': ' + bf.errstr + elif bf.filename: + return bf.filename + ': ' + bf.errstr + return 'unknown failure: ' + bf.errstr + import atexit + + def build_status(): + """Convert the build status to a 2-tuple, (status, msg).""" + from SCons.Script import GetBuildFailures + bf = GetBuildFailures() + if bf: + # bf is normally a list of build failures; if an element is None, + # it's because of a target that scons doesn't know anything about. + status = 'failed' + failures_message = "\n".join(["Failed building %s" % bf_to_str(x) + for x in bf if x is not None]) + else: + # if bf is None, the build completed successfully. + status = 'ok' + failures_message = '' + return (status, failures_message) + + def display_build_status(): + """Display the build status. Called by atexit. + Here you could do all kinds of complicated things.""" + status, failures_message = build_status() + if status == 'failed': + print "FAILED!!!!" # could display alert, ring bell, etc. + elif status == 'ok': + print "Build succeeded." + print failures_message + + atexit.register(display_build_status) + </file> + </scons_example> + + <para> + + When this runs, you'll see the appropriate output: + + </para> + + <scons_output example="gbf2"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q fail=1</scons_output_command> + </scons_output> + + </section> |