From 140d836e9cd54fb67b969fd82ef7ed19ba574d40 Mon Sep 17 00:00:00 2001 From: Luca Falavigna Date: Sat, 26 Apr 2014 15:11:58 +0200 Subject: Imported Upstream version 2.3.1 --- doc/user/output.in | 681 ----------------------------------------------------- 1 file changed, 681 deletions(-) delete mode 100644 doc/user/output.in (limited to 'doc/user/output.in') diff --git a/doc/user/output.in b/doc/user/output.in deleted file mode 100644 index 5acf2c5..0000000 --- a/doc/user/output.in +++ /dev/null @@ -1,681 +0,0 @@ - - - - - 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. - - - -
- Providing Build Help: the &Help; Function - - - - 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: - - - - - - Help(""" - Type: 'scons program' to build the production program, - 'scons debug' to build the debug version. - """) - - - - - - (Note the above use of the Python triple-quote syntax, - which comes in very handy for - specifying multi-line strings like help text.) - - - - - - 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; -h option: - - - - - scons -h - - - - - 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. - - - - - - 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: - - - - - - 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") - - - - - - Will display the complete help text on Windows: - - - - - scons -h - - - - - But only show the relevant option on a Linux or UNIX system: - - - - - scons -h - - - - - 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 -H option is used. - - - -
- -
- Controlling How &SCons; Prints Build Commands: the <envar>$*COMSTR</envar> Variables - - - - 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 $*COM variables - that specify the command lines - used to build various types of target files - have a corresponding $*COMSTR variable - that can be set to an alternative - string that will be displayed - when the target is built. - - - - - - For example, suppose you want to - have &SCons; display a - "Compiling" - message whenever it's compiling an object file, - and a - "Linking" - when it's linking an executable. - You could write a &SConstruct; file - that looks like: - - - - - - env = Environment(CCCOMSTR = "Compiling $TARGET", - LINKCOMSTR = "Linking $TARGET") - env.Program('foo.c') - - - foo.c - - - - - - Which would then yield the output: - - - - - - - % scons -Q - Compiling foo.o - Linking foo - - - - - &SCons; performs complete variable substitution - on $*COMSTR 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. - - - - - - 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 compile command - to add a few options - for a custom test. - - - - - - 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 - VERBOSE - command-line variable to your &SConstruct; file. - A simple configuration for this might look like: - - - - - - env = Environment() - if ARGUMENTS.get('VERBOSE') != "1': - env['CCCOMSTR'] = "Compiling $TARGET" - env['LINKCOMSTR'] = "Linking $TARGET" - env.Program('foo.c') - - - foo.c - - - - - - - By only setting the appropriate - $*COMSTR variables - if the user specifies - VERBOSE=1 - on the command line, - the user has control - over how &SCons; - displays these particular command lines: - - - - - - - % scons -Q - Compiling foo.o - Linking foo - % scons -Q -c - Removed foo.o - Removed foo - % scons -Q VERBOSE=1 - cc -o foo.o -c foo.c - cc -o foo foo.o - - -
- -
- Providing Build Progress Output: the &Progress; Function - - - - 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. - - - - - - 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. - - - - - - Progress('Evaluating $TARGET\n') - Program('f1.c') - Program('f2.c') - - - f1.c - - - f2.c - - - - - - 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 - print statement), - and we must specify the - \n - that we want printed at the end of the configured string. - This configuration, then, - will have &SCons; - print that it is Evaluating - each file that it encounters - in turn as it traverses the dependency graph: - - - - - scons -Q - - - - - 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 - (\r) - so that each file name gets re-printed on the same line. - Such a configuration would look like: - - - - - Progress('$TARGET\r', - file=open('/dev/tty', 'w'), - overwrite=True) - Program('f1.c') - Program('f2.c') - - - - - Note that we also specified the - overwrite=True 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 - overwrite=True 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 - /dev/tty file - for direct access (on POSIX) to - the user's screen. - On Windows, the equivalent would be to open - the con: file name. - - - - - - Also, it's important to know that although you can use - $TARGET to substitute the name of - the node in the string, - the &Progress; function does not - perform general variable substitution - (because there's not necessarily a construction - environment involved in evaluating a node - like a source file, for example). - - - - - - 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: - - - - - Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5) - Program('f1.c') - Program('f2.c') - - - - - Note that here we have also used the - interval= - keyword argument to have &SCons; - only print a new "spinner" string - once every five evaluated nodes. - Using an interval= count, - even with strings that use $TARGET 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. - - - - - - 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: - - - - - - screen = open('/dev/tty', 'w') - count = 0 - def progress_function(node) - count += 1 - screen.write('Node %4d: %s\r' % (count, node)) - - Progress(progress_function) - - - - - - Of course, if you choose, - you could completely ignore the - node argument to the function, - and just print a count, - or anything else you wish. - - - - - - (Note that there's an obvious follow-on question here: - how would you find the total number of nodes - that will be - 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.) - - - -
- -
- Printing Detailed Build Status: the &GetBuildFailures; Function - - - - 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. - - - - - - SCons provides a &GetBuildFailures; method that - you can use in a python atexit 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 -j. Here's a - simple example: - - - - - - 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) - - - - - - The atexit.register call - registers print_build_failures - as an atexit 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 - .node, - .errstr, - .filename, and - .command. - The filename is not necessarily - the same file as the node; the - node is the target that was - being built when the error occurred, while the - filenameis 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. - - - - - - Here is a more complete example showing how to - turn each element of &GetBuildFailures; into a string: - - - - - - # 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) - - - - - - When this runs, you'll see the appropriate output: - - - - - scons -Q - scons -Q fail=1 - - -
-- cgit v1.2.3