diff options
Diffstat (limited to 'doc')
37 files changed, 1821 insertions, 442 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 6f87b20..526a5a3 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -264,8 +264,8 @@ scons foo bar in which case only the specified targets will be built (along with any derived files on which they depend). -Specifying "cleanup" targets in SConscript files is not -necessary. The +Specifying "cleanup" targets in SConscript files is not usually necessary. +The .B -c flag removes all files necessary to build the specified target: @@ -1271,7 +1271,7 @@ These warnings are disabled by default. Search the specified repository for any input and target files not found in the local directory hierarchy. Multiple .B -Y -options may specified, in which case the +options may be specified, in which case the repositories are searched in the order specified. .SH CONFIGURATION FILE REFERENCE @@ -1340,7 +1340,7 @@ env = Environment(platform = my_platform) Additionally, a specific set of tools with which to initialize the environment -may specified as an optional keyword argument: +may be specified as an optional keyword argument: .ES env = Environment(tools = ['msvc', 'lex']) @@ -1530,10 +1530,12 @@ Build rules are specified by calling a construction environment's builder methods. The arguments to the builder methods are .B target -(a list of target files) +(a list of targets to be built, +usually file names) and .B source -(a list of source files). +(a list of sources to be built, +usually file names). Because long lists of file names can lead to a lot of quoting, @@ -1569,6 +1571,58 @@ env.Program(target = 'bar', env.Split('bar.c foo.c')) env.Program('bar', source = string.split('bar.c foo.c')) .EE +Target and source file names +that are not absolute path names +(that is, do not begin with +.B / +on POSIX systems +or +.B \\ +on Windows systems, +with or without +an optional drive letter) +are interpreted relative to the directory containing the +.B SConscript +file being read. +An initial +.B # +(hash mark) +on a path name means that the rest of the file name +is interpreted relative to +the directory containing +the top-level +.B SConstruct +file, +even if the +.B # +is followed by a directory separator character +(slash or backslash). + +Examples: + +.ES +# The comments describing the targets that will be built +# assume these calls are in a SConscript file in the +# a subdirectory named "subdir". + +# Builds the program "subdir/foo" from "subdir/foo.c": +env.Program('foo', 'foo.c') + +# Builds the program "/tmp/bar" from "subdir/bar.c": +env.Program('/tmp/bar', 'bar.c') + +# An initial '#' or '#/' are equivalent; the following +# calls build the programs "foo" and "bar" (in the +# top-level SConstruct directory) from "subdir/foo.c" and +# "subdir/bar.c", respectively: +env.Program('#foo', 'foo.c') +env.Program('#/bar', 'bar.c') + +# Builds the program "other/foo" (relative to the top-level +# SConstruct directory) from "subdir/foo.c": +env.Program('#other/foo', 'foo.c') +.EE + When the target shares the same base name as the source and only the suffix varies, and if the builder method has a suffix defined for the target file type, @@ -1665,15 +1719,16 @@ to the Python module: from SCons.Script import * .EE -All builder methods return a list of Nodes -that represent the target or targets that will be built. +All builder methods return a list-like object +containing Nodes that +represent the target or targets that will be built. A .I Node is an internal SCons object which represents build targets or sources. -The returned Node(s) +The returned Node-list object can be passed to other builder methods as source(s) or passed to any SCons function or method where a filename would normally be accepted. @@ -1712,7 +1767,7 @@ for object in objects: Or you can use the .BR Flatten () -supplied by scons +function supplied by scons to create a list containing just the Nodes, which may be more convenient: @@ -1724,6 +1779,40 @@ for object in objects: print str(object) .EE +Note also that because Builder calls return +a list-like object, not an actual Python list, +you should +.I not +use the Python +.B += +operator to append Builder results to a Python list. +Because the list and the object are different types, +Python will not update the original list in place, +but will instead create a new Node-list object +containing the concatenation of the list +elements and the Builder results. +This will cause problems for any other Python variables +in your SCons configuration +that still hold on to a reference to the original list. +Instead, use the Python +.B .extend() +method to make sure the list is updated in-place. +Example: + +.ES +object_files = [] + +# Do NOT use += as follows: +# +# object_files += Object('bar.c') +# +# It will not update the object_files list in place. +# +# Instead, use the .extend() method: +object_files.extend(Object('bar.c')) + +.EE + The path name for a Node's file may be used by passing the Node to the Python-builtin .B str() @@ -3303,14 +3392,14 @@ foo = env.FindFile('foo', ['dir1', 'dir2']) .RI FindInstalledFiles( ) .TP .RI env.FindInstalledFiles( ) -Returns the list of targets setup by the +Returns the list of targets set up by the .B Install() or .B InstallAs() builders. This function serves as a convenient method to select the contents of -a Binary Package. +a binary package. Example: @@ -3338,7 +3427,7 @@ Returns the list of nodes which serve as the source of the built files. It does so by inspecting the dependency tree starting at the optional argument .B node -which defaults to the '"."'-node. It will then return all leafs of +which defaults to the '"."'-node. It will then return all leaves of .B node. These are all children which have no further children. @@ -3453,6 +3542,111 @@ for object in Flatten(objects): .EE '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI GetBuildFailures() +Returns a list of exceptions for the +actions that failed while +attempting to build targets. +Each element in the returned list is a +.B BuildError +object +with the following attributes +that record various aspects +of the build failure: + +.B .node +The node that was being built +when the build failure occurred. + +.B .status +The numeric exit status +returned by the command or Python function +that failed when trying to build the +specified Node. + +.B .errstr +The SCons error string +describing the build failure. +(This is often a generic +message like "Error 2" +to indicate that an executed +command exited with a status of 2.) + +.B .filename +The name of the file or +directory that actually caused the failure. +This may be different from the +.B .node +attribute. +For example, +if an attempt to build a target named +.B sub/dir/target +fails because the +.B sub/dir +directory could not be created, +then the +.B .node +attribute will be +.B sub/dir/target +but the +.B .filename +attribute will be +.BR sub/dir . + +.B .executor +The SCons Executor object +for the target Node +being built. +This can be used to retrieve +the construction environment used +for the failed action. + +.B .action +The actual SCons Action object that failed. +This will be one specific action +out of the possible list of +actions that would have been +executed to build the target. + +.B .command +The actual expanded command that was executed and failed, +after expansion of +.BR $TARGET , +.BR $SOURCE , +and other construction variables. + +Note that the +.BR GetBuildFailures () +function +will always return an empty list +until any build failure has occurred, +which means that +.BR GetBuildFailures () +will always return an empty list +while the +.B SConscript +files are being read. +Its primary intended use is +for functions that will be +executed before SCons exits +by passing them to the +standard Python +.BR atexit.register () +function. +Example: + +.ES +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) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .TP .RI GetBuildPath( file ", [" ... ]) .TP @@ -3498,6 +3692,111 @@ options from a SConscript file. See .IR SetOption () for a description of the options available. +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Glob( pattern ", [" ondisk ", " source ", " strings ]) +.TP +.RI env.Glob( pattern ", [" ondisk ", " source ", " strings ]) +Returns Nodes (or strings) that match the specified +.IR pattern , +relative to the directory of the current +.B SConscript +file. +The +.BR env.Glob () +form performs string substition on +.I pattern +and returns whatever matches +the resulting expanded pattern. + +The specified +.I pattern +uses Unix shell style metacharacters for matching: + +.ES + * matches everything + ? matches any single character + [seq] matches any character in seq + [!seq] matches any char not in seq +.EE + +Character matches do +.I not +span directory separators. + +The +.BR Glob () +knows about +repositories +(see the +.BR Repository () +function) +and source directories +(see the +.BR BuildDir () +function) +and +returns a Node (or string, if so configured) +in the local (SConscript) directory +if matching Node is found +anywhere in a corresponding +repository or source directory. + +The +.B ondisk +argument may be set to +.B False +(or any other non-true value) +to disable the search for matches on disk, +thereby only returning matches among +already-configured File or Dir Nodes. +The default behavior is to +return corresponding Nodes +for any on-disk matches found. + +The +.B source +argument may be set to +.B True +(or any equivalent value) +to specify that, +when the local directory is a +.BR BuildDir (), +the returned Nodes should be from the +corresponding source directory, +not the local directory. + +The +.B strings +argument may be set to +.B True +(or any equivalent value) +to have the +.BR Glob () +function return strings, not Nodes, +that represent the matched files or directories. +The returned strings will be relative to +the local (SConscript) directory. +(Note that This may make it easier to perform +arbitrary manipulation of file names, +but if the returned strings are +passed to a different +.B SConscript +file, +any Node translation will be relative +to the other +.B SConscript +directory, +not the original +.B SConscript +directory.) + +Example: + +.ES +Program('foo', Glob('*.c')) +.EE + '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" '\".TP '\".RI GlobalBuilders( flag ) @@ -4267,6 +4566,29 @@ method. '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .TP +.RI Requires( target ", " prerequisite ) +.TP +.RI env.Requires( target ", " prerequisite ) +Specifies an order-only relationship +between the specified target file(s) +and the specified prerequisite file(s). +The prerequisite file(s) +will be (re)built, if necessary, +.I before +the target file(s), +but the target file(s) do not actually +depend on the prerequisites +and will not be rebuilt simply because +the prerequisite file(s) change. + +Example: + +.ES +env.Requires('foo', 'file-that-must-be-built-before-foo') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP .RI Return([ vars "... , " stop= ]) By default, this stops processing the current SConscript @@ -4875,7 +5197,16 @@ source_nodes = env.subst('$EXPAND_TO_NODELIST', .RI SourceSignatures( type ) .TP .RI env.SourceSignatures( type ) -This function tells +Note: Although it is not yet officially deprecated, +use of this function is discouraged. +See the +.BR Decider () +function for a more flexible and straightforward way +to configure SCons' decision-making. + +The +.BR SourceSignatures () +function tells .B scons how to decide if a source file (a file that is not built from any other files) @@ -4906,8 +5237,12 @@ the last time it was used to rebuild a particular target file. means .B scons decides that a source file has changed -if its timestamp (modification time) is newer than +if its timestamp (modification time) has changed since the last time it was used to rebuild a particular target file. +(Note that although this is similar to the behavior of Make, +by default it will also rebuild if the dependency is +.I older +than the last time it was used to rebuild the target file.) There is no different between the two behaviors for Python @@ -4993,7 +5328,16 @@ Tag( 'file2.txt', DOC ) .RI TargetSignatures( type ) .TP .RI env.TargetSignatures( type ) -This function tells +Note: Although it is not yet officially deprecated, +use of this function is discouraged. +See the +.BR Decider () +function for a more flexible and straightforward way +to configure SCons' decision-making. + +The +.BR TargetSignatures () +function tells .B scons how to decide if a target file (a file that @@ -5040,8 +5384,12 @@ rebuilt with exactly the same contents as the last time. means .B scons decides that a target file has changed -if its timestamp (modification time) is newer than +if its timestamp (modification time) has changed since the last time it was used to rebuild some other target file. +(Note that although this is similar to the behavior of Make, +by default it will also rebuild if the dependency is +.I older +than the last time it was used to rebuild the target file.) .B "source" means @@ -5476,7 +5824,7 @@ defined construction variables: '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" '\" BEGIN GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS '\" -'\" The descriptions below of the various SCons contruction variables +'\" The descriptions below of the various SCons construction variables '\" are generated from the .xml files that live next to the various '\" Python modules in the build enginer library. If you're reading '\" this [gnt]roff file with an eye towards patching this man page, @@ -5491,7 +5839,7 @@ defined construction variables: '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" '\" END GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS '\" -'\" The descriptions above of the various SCons contruction variables +'\" The descriptions above of the various SCons construction variables '\" are generated from the .xml files that live next to the various '\" Python modules in the build enginer library. If you're reading '\" this [gnt]roff file with an eye towards patching this man page, @@ -5554,9 +5902,9 @@ command line option. The following methods can be used to perform checks: .TP -.RI Configure( env ", [" custom_tests ", " conf_dir ", " log_file ", " config_h ]) +.RI Configure( env ", [" custom_tests ", " conf_dir ", " log_file ", " config_h ", " clean ", " help]) .TP -.RI env.Configure([ custom_tests ", " conf_dir ", " log_file ", " config_h ]) +.RI env.Configure([ custom_tests ", " conf_dir ", " log_file ", " config_h ", " clean ", " help]) This creates a configure context, which can be used to perform checks. .I env specifies the environment for building the tests. @@ -5604,6 +5952,30 @@ and some target that depends on the .I config_h file is being built. +The optional +.B clean +and +.B help +arguments can be used to suppress execution of the configuration +tests when the +.B -c/--clean +or +.B -H/-h/--help +options are used, respectively. +The default behavior is always to execute +configure context tests, +since the results of the tests may +affect the list of targets to be cleaned +or the help text. +If the configure tests do not affect these, +then you may add the +.B clean=False +or +.B help=False +arguments +(or both) +to avoid unnecessary test execution. + .EE A created .B Configure @@ -5843,6 +6215,42 @@ if conf.CheckLibWithHeader( 'qt', 'qapp.h', 'c++', 'QApplication qapp(0,0);' ): env = conf.Finish() .EE +.TP +.RI Configure.CheckTypeSize( self ", " type_name ", [" header ", " language ", " expect ]) +Checks for the size of a type defined by +.BR typedef . +.I type_name +specifies the typedef name to check for. +The optional +.I header +argument is a string +that will be +placed at the top +of the test file +that will be compiled +to check if the function exists; +the default is empty. +The optional +.I language +argument should be +.B C +or +.B C++ +and selects the compiler to be used for the check; +the default is "C". +The optional +.I expect +argument should be an integer. +If this argument is used, +the function will only check whether the type +given in type_name has the expected size (in bytes). +For example, +.B "CheckTypeSize('short', expect = 2)" +will return success only if short is two bytes. + +.ES +.EE + .EE You can define your own custom checks. in addition to the predefined checks. @@ -5990,9 +6398,13 @@ written. For example, libraries needed for the build may be in non-standard locations, or site-specific compiler options may need to be passed to the compiler. .B scons -provides a mechanism for overridding construction variables from the -command line or a text-based SConscript file through an Options -object. To create an Options object, call the Options() function: +provides an Options object for overridding construction variables +on the command line: +.ES +$ scons VARIABLE=foo +.EE +The variable values can also be specified in a text-based SConscript file. +To create an Options object, call the Options() function: .TP .RI Options([ files "], [" args ]) @@ -6091,8 +6503,17 @@ opt.AddOptions( .RI Update( env ", [" args ]) This updates a construction environment .I env -with the customized construction variables. Normally this method is not -called directly, but is called indirectly by passing the Options object to +with the customized construction variables. +Any specified variables that are +.I not +configured for the Options object +will be saved and may be +retrieved with the +.BR UnknownOptions () +method, below. + +Normally this method is not called directly, +but is called indirectly by passing the Options object to the Environment() function: .ES @@ -6105,6 +6526,7 @@ when the Options object was created are executed as Python scripts, and the values of (global) Python variables set in the file are added to the construction environment. + Example: .ES @@ -6112,6 +6534,21 @@ CC = 'my_cc' .EE .TP +.RI UnknownOptions( ) +Returns a dictionary containing any +variables that were specified +either in the files or the dictionary +with which the Options object was intialized, +but for which the Options object was +not configured. + +.ES +env = Environment(options=opts) +for key, value in opts.UnknownOptions(): + print "unknown variable: %s=%s" % (key, value) +.EE + +.TP .RI Save( filename ", " env ) This saves the currently set options into a script file named .I filename @@ -8436,7 +8873,7 @@ prefix and suffix for the current platform (for example, 'liba.a' on POSIX systems, 'a.lib' on Windows). -.SS Customizing contruction variables from the command line. +.SS Customizing construction variables from the command line. The following would allow the C compiler to be specified on the command line or in the file custom.py. diff --git a/doc/scons.mod b/doc/scons.mod index f3c1a86..c23e6ae 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -162,6 +162,7 @@ <!ENTITY Command "<function>Command</function>"> <!ENTITY Configure "<function>Configure</function>"> <!ENTITY Copy "<function>Copy</function>"> +<!ENTITY Decider "<function>Decider</function>"> <!ENTITY Default "<function>Default</function>"> <!ENTITY DefaultRules "<function>DefaultRules</function>"> <!ENTITY Delete "<function>Delete</function>"> diff --git a/doc/user/ENV.in b/doc/user/ENV.in index 3c8cfd5..3d8bc4b 100644 --- a/doc/user/ENV.in +++ b/doc/user/ENV.in @@ -196,7 +196,7 @@ The drawback is that the build can behave differently if it's run by people with different &PATH; values in their environment--for example, - both the <literal>/bin</literal> and + if both the <literal>/bin</literal> and <literal>/usr/local/bin</literal> directories have different &cc; commands, then which one will be used to compile programs diff --git a/doc/user/ENV.xml b/doc/user/ENV.xml index d843276..9fa2ec1 100644 --- a/doc/user/ENV.xml +++ b/doc/user/ENV.xml @@ -196,7 +196,7 @@ The drawback is that the build can behave differently if it's run by people with different &PATH; values in their environment--for example, - both the <literal>/bin</literal> and + if both the <literal>/bin</literal> and <literal>/usr/local/bin</literal> directories have different &cc; commands, then which one will be used to compile programs diff --git a/doc/user/builders-writing.in b/doc/user/builders-writing.in index 7497277..2285ac8 100644 --- a/doc/user/builders-writing.in +++ b/doc/user/builders-writing.in @@ -263,7 +263,7 @@ This functionality could be invoked as in the following example: <para> - To be able use both our own defined &Builder; objects + To be able to use both our own defined &Builder; objects and the default &Builder; objects in the same &consenv;, you can either add to the &cv-BUILDERS; variable using the &Append; function: diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index 50f6556..8ab4fca 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -239,7 +239,7 @@ This functionality could be invoked as in the following example: <para> - To be able use both our own defined &Builder; objects + To be able to use both our own defined &Builder; objects and the default &Builder; objects in the same &consenv;, you can either add to the &cv-BUILDERS; variable using the &Append; function: diff --git a/doc/user/command-line.in b/doc/user/command-line.in index b2cb888..dbbddaf 100644 --- a/doc/user/command-line.in +++ b/doc/user/command-line.in @@ -53,7 +53,7 @@ <para> If, for example, - and you're using a POSIX shell that's + you're using a POSIX shell that's compatible with the Bourne shell, and you always want &SCons; to use the <literal>-Q</literal> option, @@ -96,7 +96,7 @@ <para> - Windows users may typically want to set this + Windows users may typically want to set the &SCONSFLAGS; in the appropriate tab of the <literal>System Properties</literal> window. @@ -1285,7 +1285,7 @@ to control an expected path name. If, for example, you need to define a variable in the preprocessor - that control the location of a + that controls the location of a configuration file: </para> @@ -1557,3 +1557,9 @@ </para> </section> + + <!-- + + AddOption() function for things like - -prefix=, - -force + + --> diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index d7f3d7b..8675c19 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -53,7 +53,7 @@ <para> If, for example, - and you're using a POSIX shell that's + you're using a POSIX shell that's compatible with the Bourne shell, and you always want &SCons; to use the <literal>-Q</literal> option, @@ -89,7 +89,7 @@ <para> - Windows users may typically want to set this + Windows users may typically want to set the &SCONSFLAGS; in the appropriate tab of the <literal>System Properties</literal> window. @@ -1256,7 +1256,7 @@ to control an expected path name. If, for example, you need to define a variable in the preprocessor - that control the location of a + that controls the location of a configuration file: </para> @@ -1484,3 +1484,9 @@ </para> </section> + + <!-- + + AddOption() function for things like - -prefix=, - -force + + --> diff --git a/doc/user/depends.in b/doc/user/depends.in index e0d5e92..7c15c52 100644 --- a/doc/user/depends.in +++ b/doc/user/depends.in @@ -26,12 +26,12 @@ <para> So far we've seen how &SCons; handles one-time builds. - But the real point of a build tool like &SCons; + But one of the main functions of a build tool like &SCons; is to rebuild only the necessary things when source files change--or, put another way, &SCons; should <emphasis>not</emphasis> waste time rebuilding things that have already been built. - You can see this at work simply be re-invoking &SCons; + You can see this at work simply by re-invoking &SCons; after building our simple &hello; example: </para> @@ -75,33 +75,36 @@ </para> <section> - <title>Deciding When a Source File Has Changed: the &SourceSignatures; Function</title> + <title>Deciding When an Input File Has Changed: the &Decider; Function</title> <para> - The other side of avoiding unnecessary rebuilds + Another aspect of avoiding unnecessary rebuilds is the fundamental build tool behavior of <emphasis>rebuilding</emphasis> - things when a source file changes, + things when an input file changes, so that the built software is up to date. - &SCons; keeps track of this through a - &signature; for each source file, - and allows you to configure - whether you want to use the source - file contents or the modification time (timestamp) - as the signature. + By default, + &SCons; keeps track of this through an + MD5 &signature;, or checksum, of the contents of each file, + although you can easily configure + &SCons; to use the + modification times (or time stamps) + instead. + You can even specify your own Python function + for deciding if an input file has changed. </para> <section> - <title>MD5 Source File Signatures</title> + <title>Using MD5 Signatures to Decide if a File Has Changed</title> <para> By default, - &SCons; keeps track of whether a source file has changed - based on the file's contents, - not the modification time. + &SCons; keeps track of whether a file has changed + based on an MD5 checksum of the file's contents, + not the file's modification time. This means that you may be surprised by the default &SCons; behavior if you are used to the &Make; convention of forcing @@ -143,36 +146,110 @@ Note that you can, if you wish, specify this default behavior (MD5 signatures) explicitly - using the &SourceSignatures; function as follows: + using the &Decider; function as follows: </para> <sconstruct> Program('hello.c') - SourceSignatures('MD5') + Decider('MD5') </sconstruct> + <para> + + You can also use the string <literal>'content'</literal> + as a synonym for <literal>'MD5'</literal> + when calling the &Decider; function. + + </para> + + <section> + <title>Ramifications of Using MD5 Signatures</title> + + <para> + + Using MD5 Signatures to decide if an input file has changed + has one surprising benefit: + if a source file has been changed + in such a way that the contents of the + rebuilt target file(s) + will be exactly the same as the last time + the file was built, + then any "downstream" target files + that depend on the rebuilt-but-not-changed target + file actually need not be rebuilt. + + </para> + + <para> + + So if, for example, + a user were to only change a comment in a &hello_c; file, + then the rebuilt &hello_o; file + would be exactly the same as the one previously built + (assuming the compiler doesn't put any build-specific + information in the object file). + &SCons; would then realize that it would not + need to rebuild the &hello; program as follows: + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + In essence, &SCons; + "short-circuits" any dependent builds + when it realizes that a target file + has been rebuilt to exactly the same file as the last build. + This does take some extra processing time + to read the contents of the target (&hello_o;) file, + but often saves time when the rebuild that was avoided + would have been time-consuming and expensive. + + </para> + + </section> + </section> <section> - <title>Source File Time Stamps</title> + <title>Using Time Stamps to Decide If a File Has Changed</title> <para> If you prefer, you can configure &SCons; to use the modification time - of source files, - not the file contents, - when deciding if something needs to be rebuilt. - To do this, call the &SourceSignatures; + of a file, not the file contents, + when deciding if a target needs to be rebuilt. + &SCons; gives you two ways to use time stamps + to decide if an input file has changed + since the last time a target has been built. + + </para> + + <para> + + The most familiar way to use time stamps + is the way &Make; does: + that is, have &SCons; decide + and target must be rebuilt if + if a source file's modification time is + <emphasis>newer</emphasis> + than the target file. + To do this, call the &Decider; function as follows: </para> - <scons_example name="ex2"> + <scons_example name="newer"> <file name="SConstruct" printme="1"> Program('hello.c') - SourceSignatures('timestamp') + Decider('timestamp-newer') </file> <file name="hello.c"> int main() { printf("Hello, world!\n"); } @@ -187,117 +264,222 @@ </para> - <scons_output example="ex2" os="posix"> + <scons_output example="newer" os="posix"> <scons_output_command>scons -Q hello</scons_output_command> <scons_output_command>touch hello.c</scons_output_command> <scons_output_command>scons -Q hello</scons_output_command> </scons_output> - </section> + <para> - </section> + And, in fact, because this behavior is the same + as the behavior of &Make;, + you can also use the string <literal>'make'</literal> + as a synonym for <literal>'timestamp-newer'</literal> + when calling the &Decider; function: - <section> - <title>Deciding When a Target File Has Changed: the &TargetSignatures; Function</title> + </para> - <para> + <sconstruct> + Program('hello.c') + Decider('make') + </sconstruct> - As you've just seen, - &SCons; uses signatures to decide whether a - target file is up to date or must be rebuilt. - When a target file depends on another target file, - &SCons; allows you to configure separately - how the signatures of "intermediate" target files - are used when deciding if a dependent target file - must be rebuilt. + <para> - </para> + One drawback to using times stamps exactly like &Make; + is that if an input file's modification time suddenly + becomes <emphasis>older</emphasis> than a target file, + the target file will not be rebuilt. + This can happen if an old copy of a source file is restored + from a backup archive, for example. + The contents of the restored file will likely be different + than they were the last time a dependent target was built, + but the target won't be rebuilt + because the modification time of the source file + is not newer than the target. - <section> - <title>Build Signatures</title> + </para> <para> - Modifying a source file - will cause not only its direct target file to be rebuilt, - but also the target file(s) - that depend on that direct target file. - In our example, - changing the contents of the &hello_c; file causes - the &hello_o; file to be rebuilt, - which in turn causes the - &hello; program to be rebuilt: + Because &SCons; actually stores information + about the source files' time stamps whenever a target is built, + it can handle this situation by checking for + an exact match of the source file time stamp, + instead of just whether or not the source file + is newer than the target file. + To do this, specify the argument + <literal>'timestamp-match'</literal> + when calling the &Decider; function: </para> - <scons_output example="ex1" os="posix"> + <scons_example name="match"> + <file name="SConstruct" printme="1"> + Program('hello.c') + Decider('timestamp-match') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + When configured this way, + &SCons; will rebuild a target whenever + a source file's modification time has changed. + So if we use the <literal>touch -t</literal> + option to change the modification time of + &hello_c; to an old date (January 1, 1989), + &SCons; will still rebuild the target file: + + </para> + + <scons_output example="match" os="posix"> <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> + <scons_output_command>touch -t 198901010000 hello.c</scons_output_command> <scons_output_command>scons -Q hello</scons_output_command> </scons_output> <para> - What's not obvious, though, - is that &SCons; internally handles the signature of - the target file(s) - (&hello_o; in the above example) - differently from the signature of the source file - (&hello_c;). - By default, - &SCons; tracks whether a target file must be rebuilt - by using a &buildsignature; - that consists of the combined - signatures of all the files - that go into making the target file. - This is efficient because - the accumulated signatures - actually give &SCons; all of the - information it needs - to decide if the target file is out of date. + In general, the only reason to prefer + <literal>timestamp-newer</literal> + instead of + <literal>timestamp-match</literal>, + would be if you have some specific reason + to require this &Make;-like behavior of + not rebuilding a target when an otherwise-modified + source file is older. </para> + </section> + + <section> + <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title> + <para> - If you wish, you can - specify this default behavior - (build signatures) explicitly - using the &TargetSignatures; function: + As a performance enhancement, + &SCons; provides a way to use + MD5 checksums of file contents + but to only read the contents + whenever the file's timestamp has changed. + To do this, call the &Decider; + function with <literal>'MD5-timestamp'</literal> + argument as follows: </para> - <sconstruct> + <scons_example name="MD5-timestamp"> + <file name="SConstruct" printme="1"> Program('hello.c') - TargetSignatures('build') - </sconstruct> + Decider('MD5-timestamp') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + So configured, &SCons will still behave like + it does when using <literal>Decider('MD5')</literal>: + + </para> + + <scons_output example="MD5-timestamp" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>touch hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + However, the second call to &SCons; in the above output, + when the build is up-to-date, + will have been performed by simply looking at the + modification time of the &hello_c; file, + not by opening it and performing + an MD5 checksum calcuation on its contents. + This can significantly speed up many up-to-date builds. + + </para> + + <para> + + The only drawback to using + <literal>Decider('MD5-timestamp')</literal> + is that &SCons; will <emphasis>not</emphasis> + rebuild a target file if a source file was modified + within one second of the last time &SCons; built the file. + While most developers are programming, + this isn't a problem in practice, + since it's unlikely that someone will have built + and then thought quickly enought to make a substantive + change to a source file within one second. + Certain build scripts or + continuous integration tools may, however, + rely on the ability to applying changes to files + automatically and then rebuild as quickly as possible, + in which case use of + <literal>Decider('MD5-timestamp')</literal> + may not be appropriate. + + </para> </section> <section> - <title>File Contents</title> + <title>Writing Your Own Custom &Decider; Function</title> <para> - Sometimes a source file can be changed - in such a way that the contents of the - rebuilt target file(s) - will be exactly the same as the last time - the file was built. - If so, then any other target files - that depend on such a built-but-not-changed target - file actually need not be rebuilt. - You can make &SCons; - realize that it does not need to rebuild - a dependent target file in this situation - using the &TargetSignatures; function as follows: + The different string values that we've passed to + the &Decider; function are essentially used by &SCons; + to pick one of several specific internal functions + that implement various ways of deciding if a dependency + (usually a source file) + has changed since a target file has been built. + As it turns out, + you can also supply your own function + to decide if a dependency has changed. </para> - <scons_example name="ex3"> + <para> + + For example, suppose we have an input file + that contains a lot of data, + in some specific regular format, + that is used to rebuild a lot of different target files, + but each target file really only depends on + one particular section of the input file. + We'd like to have each target file depend on + only its section of the input file. + However, since the input file may contain a lot of data, + we only want to open the input file if its timestamp has changed. + This could done with a custom + &Decider; function that might look something like this: + + </para> + + <scons_example name="function"> <file name="SConstruct" printme="1"> Program('hello.c') - TargetSignatures('content') + def decide_if_changed(dependency, target, prev_ni): + if self.get_timestamp() != prev_ni.timestamp: + dep = str(dependency) + tgt = str(target) + if specific_part_of_file_has_changed(dep, tgt): + return True + return False + Decider(decide_if_changed) </file> <file name="hello.c"> int main() { printf("Hello, world!\n"); } @@ -306,35 +488,294 @@ <para> - So if, for example, - a user were to only change a comment in a C file, - then the rebuilt &hello_o; file - would be exactly the same as the one previously built - (assuming the compiler doesn't put any build-specific - information in the object file). - &SCons; would then realize that it would not - need to rebuild the &hello; program as follows: + Note that in the function definition, + the <literal>dependency</literal> + (input file) is the first argument, + and then the <literal>target</literal>. + Both of these are passed to the functions as + SCons &Node; objects, + which we convert to strings using the Python + <function>str()</function>. + The third argument, <literal>prev_ni</literal>, + is an object that holds the + signature or timestamp information + that was recorded about the dependency + the last time the target was built. </para> - <scons_output example="ex3" os="posix"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> + <para> + + Note that ignoring some of the arguments + in your custom &Decider; function + is a perfectly normal thing to do, + if they don't impact the way you want to + decide if the dependency file has changed. + + </para> + + </section> + + <section> + <title>Mixing Different Ways of Deciding If a File Has Changed</title> + + <para> + + The previous examples have all demonstrated calling + the global &Decider; function + to configure all dependency decisions that &SCons; makes. + Sometimes, however, you want to be able to configure + different decision-making for different targets. + When that's necessary, you can use the + <function>env.Decider</function> + method to affect only the configuration + decisions for targets built with a + specific construction environment. + + </para> + + <para> + + For example, if we arbitrarily want to build + one program using MD5 checkums + and another use file modification times + from the same source + we might configure it this way: + + </para> + + <scons_example name="mixing"> + <file name="SConstruct" printme="1"> + env1 = Environment(CPPPATH = ['.']) + env2 = env1.Clone() + env2.Decider('timestamp-match') + env1.Program('prog-MD5', 'program1.c') + env2.Program('prog-timestamp', 'program2.c') + </file> + <file name="program1.c"> + #include "inc.h" + int main() { printf("Hello, world!\n"); } + </file> + <file name="program2.c"> + #include "inc.h" + int main() { printf("Hello, world!\n"); } + </file> + <file name="inc.h"> + #define INC 1 + </file> + </scons_example> + + <para> + + If both of the programs include the same + <filename>inc.h</filename> file, + then updating the modification time of + <filename>inc.h</filename> + (using the &touch; command) + will cause only <filename>prog-timestamp</filename> + to be rebuilt: + + </para> + + <scons_output example="mixing" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>touch inc.h</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> </scons_output> + </section> + + </section> + + <section> + <title>Older Functions for Deciding When an Input File Has Changed</title> + + <para> + + &SCons; still supports two functions that used to be the + primary methods for configuring the + decision about whether or not an input file has changed. + Although they're not officially deprecated yet, + their use is discouraged, + mainly because they rely on a somewhat + confusing distinction between how + source files and target files are handled. + These functions are documented here mainly in case you + encounter them in existing &SConscript; files. + + </para> + + <section> + <title>The &SourceSignatures; Function</title> + <para> - In essence, &SCons; has - "short-circuited" any dependent builds - when it realizes that a target file - has been rebuilt to exactly the same file as the last build. - So configured, - &SCons; does take some extra processing time - to scan the contents of the target (&hello_o;) file, - but this may save time - if the rebuild that was avoided - would have been very time-consuming and expensive. + The &SourceSignatures; function is fairly straightforward, + and supports two different argument values + to configure whether source file changes should be decided + using MD5 signatures: + + </para> + + <sconstruct> + Program('hello.c') + SourceSignatures('MD5') + </sconstruct> + + <para> + + Or using time stamps: + + </para> + + <sconstruct> + Program('hello.c') + SourceSignatures('timestamp') + </sconstruct> + + <para> + + These are roughly equivalent to specifying + <function>Decider('MD5')</function> + or + <function>Decider('timestamp-match')</function>, + respectively, + although it only affects how SCons makes + decisions about dependencies on + <emphasis>source</emphasis> files--that is, + files that are not built from any other files. + + </para> + + </section> + + <section> + <title>The &TargetSignatures; Function</title> + + <para> + + The &TargetSignatures; function + specifies how &SCons; decides + when a target file has changed + <emphasis>when it is used as a + dependency of (input to) another target</emphasis>--that is, + the &TargetSignatures; function configures + how the signatures of "intermediate" target files + are used when deciding if a "downstream" target file + must be rebuilt. + <footnote><para> + This easily-overlooked distinction between + how &SCons; decides if the target itself must be rebuilt + and how the target is then used to decide if a different + target must be rebuilt is one of the confusing + things that has led to the &TargetSignatures; + and &SourceSignatures; functions being + replaced by the simpler &Decider; function. + </para></footnote> + + </para> + + <para> + + The &TargetSignatures; function supports the same + <literal>'MD5'</literal> and <literal>'timestamp'</literal> + argument values that are supported by the &SourceSignatures;, + with the same meanings, but applied to target files. + That is, in the example: + + </para> + + <sconstruct> + Program('hello.c') + TargetSignatures('MD5') + </sconstruct> + + <para> + + The MD5 checksum of the &hello_o; target file + will be used to decide if it has changed since the last + time the "downstream" &hello; target file was built. + And in the example: + + </para> + + <sconstruct> + Program('hello.c') + TargetSignatures('timestamp') + </sconstruct> + + <para> + + The modification time of the &hello_o; target file + will be used to decide if it has changed since the last + time the "downstream" &hello; target file was built. + + </para> + + <para> + + The &TargetSignatures; function supports + two additional argument values: + <literal>'source'</literal> and <literal>'build'</literal>. + The <literal>'source'</literal> argument + specifies that decisions involving + whether target files have changed + since a previous build + should use the same behavior + for the decisions configured for source files + (using the &SourceSignatures; function). + So in the example: + + </para> + + <sconstruct> + Program('hello.c') + TargetSignatures('source') + SourceSignatures('timestamp') + </sconstruct> + + <para> + + All files, both targets and sources, + will use modification times + when deciding if an input file + has changed since the last + time a target was built. + + </para> + + <para> + + Lastly, the <literal>'build'</literal> argument + specifies that &SCons; should examine + the build status of a target file + and always rebuild a "downstream" target + if the target file was itself rebuilt, + without re-examining the contents or timestamp + of the newly-built target file. + If the target file was not rebuilt during + this &scons; invocation, + then the target file will be examined + the same way as configured by + the &SourceSignature; call + to decide if it has changed. + + </para> + + <para> + + This mimics the behavior of + <literal>build signatures</literal> + in earlier versions of &SCons;. + A &buildsignature; re-combined + signatures of all the input files + that went into making the target file, + so that the target file itself + did not need to have its contents read + to compute an MD5 signature. + This can improve performance for some configurations, + but is generally not as effective as using + <literal>Decider('MD5-timestamp')</literal>. </para> @@ -348,12 +789,12 @@ <para> Now suppose that our "Hello, World!" program - actually has a <literal>#include</literal> line + actually has an <literal>#include</literal> line to include the &hello_h; file in the compilation: </para> - <scons_example name="ex4"> + <scons_example name="include"> <file name="SConstruct"> Program('hello.c', CPPPATH = '.') </file> @@ -376,7 +817,7 @@ </para> - <scons_example_file example="ex4" name="hello.h"> + <scons_example_file example="include" name="hello.h"> </scons_example_file> <para> @@ -389,7 +830,7 @@ </para> - <scons_example_file example="ex4" name="SConstruct"> + <scons_example_file example="include" name="SConstruct"> </scons_example_file> <para> @@ -403,7 +844,7 @@ </para> - <scons_output example="ex4" os="posix"> + <scons_output example="include" os="posix"> <scons_output_command>scons -Q hello</scons_output_command> <scons_output_command>scons -Q hello</scons_output_command> <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> @@ -445,7 +886,7 @@ the &cv-CPPPATH; variable may be a list of directories, or a string separated by - the system-specific path separate character + the system-specific path separation character (':' on POSIX/Linux, ';' on Windows). Either way, &SCons; creates the right command-line options @@ -682,7 +1123,44 @@ </section> <section> - <title>Ignoring Dependencies: the &Ignore; Method</title> + <title>Explicit Dependencies: the &Depends; Function</title> + + <para> + + Sometimes a file depends on another file + that is not detected by an &SCons; scanner. + For this situation, + &SCons; allows you to specific explicitly that one file + depends on another file, + and must be rebuilt whenever that file changes. + This is specified using the &Depends; method: + + </para> + + <programlisting> + hello = Program('hello.c') + Depends(hello, 'other_file') + </programlisting> + + <!-- XXX mention that you can use arrays for target and source? --> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit other_file</userinput> + [CHANGE THE CONTENTS OF other_file] + % <userinput>scons -Q hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Ignoring Dependencies: the &Ignore; Function</title> <para> @@ -737,7 +1215,7 @@ Now, the above example is a little contrived, because it's hard to imagine a real-world situation - where you wouldn't to rebuild &hello; + where you wouldn't want to rebuild &hello; if the &hello_h; file changed. A more realistic example might be if the &hello; @@ -762,45 +1240,7 @@ </section> <section> - <title>Explicit Dependencies: the &Depends; Method</title> - - <para> - - On the other hand, - sometimes a file depends on another file - that is not detected by an &SCons; scanner. - For this situation, - &SCons; allows you to specific explicitly that one file - depends on another file, - and must be rebuilt whenever that file changes. - This is specified using the &Depends; method: - - </para> - - <programlisting> - hello = Program('hello.c') - Depends(hello, 'other_file') - </programlisting> - - <!-- XXX mention that you can use arrays for target and source? --> - - <screen> - % <userinput>scons -Q hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - % <userinput>edit other_file</userinput> - [CHANGE THE CONTENTS OF other_file] - % <userinput>scons -Q hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - </screen> - - </section> - - <section> - <title>The &AlwaysBuild; Method</title> + <title>The &AlwaysBuild; Function</title> <para> diff --git a/doc/user/depends.xml b/doc/user/depends.xml index 9e055ee..936e4b2 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -26,12 +26,12 @@ <para> So far we've seen how &SCons; handles one-time builds. - But the real point of a build tool like &SCons; + But one of the main functions of a build tool like &SCons; is to rebuild only the necessary things when source files change--or, put another way, &SCons; should <emphasis>not</emphasis> waste time rebuilding things that have already been built. - You can see this at work simply be re-invoking &SCons; + You can see this at work simply by re-invoking &SCons; after building our simple &hello; example: </para> @@ -74,33 +74,36 @@ </para> <section> - <title>Deciding When a Source File Has Changed: the &SourceSignatures; Function</title> + <title>Deciding When an Input File Has Changed: the &Decider; Function</title> <para> - The other side of avoiding unnecessary rebuilds + Another aspect of avoiding unnecessary rebuilds is the fundamental build tool behavior of <emphasis>rebuilding</emphasis> - things when a source file changes, + things when an input file changes, so that the built software is up to date. - &SCons; keeps track of this through a - &signature; for each source file, - and allows you to configure - whether you want to use the source - file contents or the modification time (timestamp) - as the signature. + By default, + &SCons; keeps track of this through an + MD5 &signature;, or checksum, of the contents of each file, + although you can easily configure + &SCons; to use the + modification times (or time stamps) + instead. + You can even specify your own Python function + for deciding if an input file has changed. </para> <section> - <title>MD5 Source File Signatures</title> + <title>Using MD5 Signatures to Decide if a File Has Changed</title> <para> By default, - &SCons; keeps track of whether a source file has changed - based on the file's contents, - not the modification time. + &SCons; keeps track of whether a file has changed + based on an MD5 checksum of the file's contents, + not the file's modification time. This means that you may be surprised by the default &SCons; behavior if you are used to the &Make; convention of forcing @@ -150,35 +153,114 @@ Note that you can, if you wish, specify this default behavior (MD5 signatures) explicitly - using the &SourceSignatures; function as follows: + using the &Decider; function as follows: </para> <programlisting> Program('hello.c') - SourceSignatures('MD5') + Decider('MD5') </programlisting> + <para> + + You can also use the string <literal>'content'</literal> + as a synonym for <literal>'MD5'</literal> + when calling the &Decider; function. + + </para> + + <section> + <title>Ramifications of Using MD5 Signatures</title> + + <para> + + Using MD5 Signatures to decide if an input file has changed + has one surprising benefit: + if a source file has been changed + in such a way that the contents of the + rebuilt target file(s) + will be exactly the same as the last time + the file was built, + then any "downstream" target files + that depend on the rebuilt-but-not-changed target + file actually need not be rebuilt. + + </para> + + <para> + + So if, for example, + a user were to only change a comment in a &hello_c; file, + then the rebuilt &hello_o; file + would be exactly the same as the one previously built + (assuming the compiler doesn't put any build-specific + information in the object file). + &SCons; would then realize that it would not + need to rebuild the &hello; program as follows: + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>edit hello.c</userinput> + [CHANGE A COMMENT IN hello.c] + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + scons: `hello' is up to date. + </screen> + + <para> + + In essence, &SCons; + "short-circuits" any dependent builds + when it realizes that a target file + has been rebuilt to exactly the same file as the last build. + This does take some extra processing time + to read the contents of the target (&hello_o;) file, + but often saves time when the rebuild that was avoided + would have been time-consuming and expensive. + + </para> + + </section> + </section> <section> - <title>Source File Time Stamps</title> + <title>Using Time Stamps to Decide If a File Has Changed</title> <para> If you prefer, you can configure &SCons; to use the modification time - of source files, - not the file contents, - when deciding if something needs to be rebuilt. - To do this, call the &SourceSignatures; + of a file, not the file contents, + when deciding if a target needs to be rebuilt. + &SCons; gives you two ways to use time stamps + to decide if an input file has changed + since the last time a target has been built. + + </para> + + <para> + + The most familiar way to use time stamps + is the way &Make; does: + that is, have &SCons; decide + and target must be rebuilt if + if a source file's modification time is + <emphasis>newer</emphasis> + than the target file. + To do this, call the &Decider; function as follows: </para> <programlisting> Program('hello.c') - SourceSignatures('timestamp') + Decider('timestamp-newer') </programlisting> <para> @@ -199,40 +281,118 @@ cc -o hello hello.o </screen> - </section> + <para> - </section> + And, in fact, because this behavior is the same + as the behavior of &Make;, + you can also use the string <literal>'make'</literal> + as a synonym for <literal>'timestamp-newer'</literal> + when calling the &Decider; function: - <section> - <title>Deciding When a Target File Has Changed: the &TargetSignatures; Function</title> + </para> - <para> + <programlisting> + Program('hello.c') + Decider('make') + </programlisting> - As you've just seen, - &SCons; uses signatures to decide whether a - target file is up to date or must be rebuilt. - When a target file depends on another target file, - &SCons; allows you to configure separately - how the signatures of "intermediate" target files - are used when deciding if a dependent target file - must be rebuilt. + <para> - </para> + One drawback to using times stamps exactly like &Make; + is that if an input file's modification time suddenly + becomes <emphasis>older</emphasis> than a target file, + the target file will not be rebuilt. + This can happen if an old copy of a source file is restored + from a backup archive, for example. + The contents of the restored file will likely be different + than they were the last time a dependent target was built, + but the target won't be rebuilt + because the modification time of the source file + is not newer than the target. + + </para> + + <para> + + Because &SCons; actually stores information + about the source files' time stamps whenever a target is built, + it can handle this situation by checking for + an exact match of the source file time stamp, + instead of just whether or not the source file + is newer than the target file. + To do this, specify the argument + <literal>'timestamp-match'</literal> + when calling the &Decider; function: + + </para> + + <programlisting> + Program('hello.c') + Decider('timestamp-match') + </programlisting> + + <para> + + When configured this way, + &SCons; will rebuild a target whenever + a source file's modification time has changed. + So if we use the <literal>touch -t</literal> + option to change the modification time of + &hello_c; to an old date (January 1, 1989), + &SCons; will still rebuild the target file: + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>touch -t 198901010000 hello.c</userinput> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + scons: `hello' is up to date. + </screen> + + <para> + + In general, the only reason to prefer + <literal>timestamp-newer</literal> + instead of + <literal>timestamp-match</literal>, + would be if you have some specific reason + to require this &Make;-like behavior of + not rebuilding a target when an otherwise-modified + source file is older. + + </para> + + </section> <section> - <title>Build Signatures</title> + <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title> + + <para> + + As a performance enhancement, + &SCons; provides a way to use + MD5 checksums of file contents + but to only read the contents + whenever the file's timestamp has changed. + To do this, call the &Decider; + function with <literal>'MD5-timestamp'</literal> + argument as follows: + + </para> + + <programlisting> + Program('hello.c') + Decider('MD5-timestamp') + </programlisting> <para> - Modifying a source file - will cause not only its direct target file to be rebuilt, - but also the target file(s) - that depend on that direct target file. - In our example, - changing the contents of the &hello_c; file causes - the &hello_o; file to be rebuilt, - which in turn causes the - &hello; program to be rebuilt: + So configured, &SCons; will still behave like + it does when using <literal>Decider('MD5')</literal>: </para> @@ -240,112 +400,380 @@ % <userinput>scons -Q hello</userinput> cc -o hello.o -c hello.c cc -o hello hello.o + % <userinput>touch hello.c</userinput> + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. % <userinput>edit hello.c</userinput> [CHANGE THE CONTENTS OF hello.c] % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o + scons: `hello' is up to date. </screen> <para> - What's not obvious, though, - is that &SCons; internally handles the signature of - the target file(s) - (&hello_o; in the above example) - differently from the signature of the source file - (&hello_c;). - By default, - &SCons; tracks whether a target file must be rebuilt - by using a &buildsignature; - that consists of the combined - signatures of all the files - that go into making the target file. - This is efficient because - the accumulated signatures - actually give &SCons; all of the - information it needs - to decide if the target file is out of date. + However, the second call to &SCons; in the above output, + when the build is up-to-date, + will have been performed by simply looking at the + modification time of the &hello_c; file, + not by opening it and performing + an MD5 checksum calcuation on its contents. + This can significantly speed up many up-to-date builds. </para> <para> - If you wish, you can - specify this default behavior - (build signatures) explicitly - using the &TargetSignatures; function: + The only drawback to using + <literal>Decider('MD5-timestamp')</literal> + is that &SCons; will <emphasis>not</emphasis> + rebuild a target file if a source file was modified + within one second of the last time &SCons; built the file. + While most developers are programming, + this isn't a problem in practice, + since it's unlikely that someone will have built + and then thought quickly enought to make a substantive + change to a source file within one second. + Certain build scripts or + continuous integration tools may, however, + rely on the ability to applying changes to files + automatically and then rebuild as quickly as possible, + in which case use of + <literal>Decider('MD5-timestamp')</literal> + may not be appropriate. + + </para> + + </section> + + <section> + <title>Writing Your Own Custom &Decider; Function</title> + + <para> + + The different string values that we've passed to + the &Decider; function are essentially used by &SCons; + to pick one of several specific internal functions + that implement various ways of deciding if a dependency + (usually a source file) + has changed since a target file has been built. + As it turns out, + you can also supply your own function + to decide if a dependency has changed. + + </para> + + <para> + + For example, suppose we have an input file + that contains a lot of data, + in some specific regular format, + that is used to rebuild a lot of different target files, + but each target file really only depends on + one particular section of the input file. + We'd like to have each target file depend on + only its section of the input file. + However, since the input file may contain a lot of data, + we only want to open the input file if its timestamp has changed. + This could done with a custom + &Decider; function that might look something like this: </para> <programlisting> Program('hello.c') - TargetSignatures('build') + def decide_if_changed(dependency, target, prev_ni): + if self.get_timestamp() != prev_ni.timestamp: + dep = str(dependency) + tgt = str(target) + if specific_part_of_file_has_changed(dep, tgt): + return True + return False + Decider(decide_if_changed) </programlisting> + <para> + + Note that in the function definition, + the <literal>dependency</literal> + (input file) is the first argument, + and then the <literal>target</literal>. + Both of these are passed to the functions as + SCons &Node; objects, + which we convert to strings using the Python + <function>str()</function>. + The third argument, <literal>prev_ni</literal>, + is an object that holds the + signature or timestamp information + that was recorded about the dependency + the last time the target was built. + + </para> + + <para> + + Note that ignoring some of the arguments + in your custom &Decider; function + is a perfectly normal thing to do, + if they don't impact the way you want to + decide if the dependency file has changed. + + </para> + </section> <section> - <title>File Contents</title> + <title>Mixing Different Ways of Deciding If a File Has Changed</title> + + <para> + + The previous examples have all demonstrated calling + the global &Decider; function + to configure all dependency decisions that &SCons; makes. + Sometimes, however, you want to be able to configure + different decision-making for different targets. + When that's necessary, you can use the + <function>env.Decider</function> + method to affect only the configuration + decisions for targets built with a + specific construction environment. + + </para> <para> - Sometimes a source file can be changed - in such a way that the contents of the - rebuilt target file(s) - will be exactly the same as the last time - the file was built. - If so, then any other target files - that depend on such a built-but-not-changed target - file actually need not be rebuilt. - You can make &SCons; - realize that it does not need to rebuild - a dependent target file in this situation - using the &TargetSignatures; function as follows: + For example, if we arbitrarily want to build + one program using MD5 checkums + and another use file modification times + from the same source + we might configure it this way: </para> <programlisting> - Program('hello.c') - TargetSignatures('content') + env1 = Environment(CPPPATH = ['.']) + env2 = env1.Clone() + env2.Decider('timestamp-match') + env1.Program('prog-MD5', 'program1.c') + env2.Program('prog-timestamp', 'program2.c') </programlisting> <para> - So if, for example, - a user were to only change a comment in a C file, - then the rebuilt &hello_o; file - would be exactly the same as the one previously built - (assuming the compiler doesn't put any build-specific - information in the object file). - &SCons; would then realize that it would not - need to rebuild the &hello; program as follows: + If both of the programs include the same + <filename>inc.h</filename> file, + then updating the modification time of + <filename>inc.h</filename> + (using the &touch; command) + will cause only <filename>prog-timestamp</filename> + to be rebuilt: </para> <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>edit hello.c</userinput> - [CHANGE A COMMENT IN hello.c] - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - scons: `hello' is up to date. + % <userinput>scons -Q</userinput> + cc -o program1.o -c -I. program1.c + cc -o prog-MD5 program1.o + cc -o program2.o -c -I. program2.c + cc -o prog-timestamp program2.o + % <userinput>touch inc.h</userinput> + % <userinput>scons -Q</userinput> + cc -o program2.o -c -I. program2.c + cc -o prog-timestamp program2.o </screen> + </section> + + </section> + + <section> + <title>Older Functions for Deciding When an Input File Has Changed</title> + + <para> + + &SCons; still supports two functions that used to be the + primary methods for configuring the + decision about whether or not an input file has changed. + Although they're not officially deprecated yet, + their use is discouraged, + mainly because they rely on a somewhat + confusing distinction between how + source files and target files are handled. + These functions are documented here mainly in case you + encounter them in existing &SConscript; files. + + </para> + + <section> + <title>The &SourceSignatures; Function</title> + + <para> + + The &SourceSignatures; function is fairly straightforward, + and supports two different argument values + to configure whether source file changes should be decided + using MD5 signatures: + + </para> + + <programlisting> + Program('hello.c') + SourceSignatures('MD5') + </programlisting> + + <para> + + Or using time stamps: + + </para> + + <programlisting> + Program('hello.c') + SourceSignatures('timestamp') + </programlisting> + <para> - In essence, &SCons; has - "short-circuited" any dependent builds - when it realizes that a target file - has been rebuilt to exactly the same file as the last build. - So configured, - &SCons; does take some extra processing time - to scan the contents of the target (&hello_o;) file, - but this may save time - if the rebuild that was avoided - would have been very time-consuming and expensive. + These are roughly equivalent to specifying + <function>Decider('MD5')</function> + or + <function>Decider('timestamp-match')</function>, + respectively, + although it only affects how SCons makes + decisions about dependencies on + <emphasis>source</emphasis> files--that is, + files that are not built from any other files. + + </para> + + </section> + + <section> + <title>The &TargetSignatures; Function</title> + + <para> + + The &TargetSignatures; function + specifies how &SCons; decides + when a target file has changed + <emphasis>when it is used as a + dependency of (input to) another target</emphasis>--that is, + the &TargetSignatures; function configures + how the signatures of "intermediate" target files + are used when deciding if a "downstream" target file + must be rebuilt. + <footnote><para> + This easily-overlooked distinction between + how &SCons; decides if the target itself must be rebuilt + and how the target is then used to decide if a different + target must be rebuilt is one of the confusing + things that has led to the &TargetSignatures; + and &SourceSignatures; functions being + replaced by the simpler &Decider; function. + </para></footnote> + + </para> + + <para> + + The &TargetSignatures; function supports the same + <literal>'MD5'</literal> and <literal>'timestamp'</literal> + argument values that are supported by the &SourceSignatures;, + with the same meanings, but applied to target files. + That is, in the example: + + </para> + + <programlisting> + Program('hello.c') + TargetSignatures('MD5') + </programlisting> + + <para> + + The MD5 checksum of the &hello_o; target file + will be used to decide if it has changed since the last + time the "downstream" &hello; target file was built. + And in the example: + + </para> + + <programlisting> + Program('hello.c') + TargetSignatures('timestamp') + </programlisting> + + <para> + + The modification time of the &hello_o; target file + will be used to decide if it has changed since the last + time the "downstream" &hello; target file was built. + + </para> + + <para> + + The &TargetSignatures; function supports + two additional argument values: + <literal>'source'</literal> and <literal>'build'</literal>. + The <literal>'source'</literal> argument + specifies that decisions involving + whether target files have changed + since a previous build + should use the same behavior + for the decisions configured for source files + (using the &SourceSignatures; function). + So in the example: + + </para> + + <programlisting> + Program('hello.c') + TargetSignatures('source') + SourceSignatures('timestamp') + </programlisting> + + <para> + + All files, both targets and sources, + will use modification times + when deciding if an input file + has changed since the last + time a target was built. + + </para> + + <para> + + Lastly, the <literal>'build'</literal> argument + specifies that &SCons; should examine + the build status of a target file + and always rebuild a "downstream" target + if the target file was itself rebuilt, + without re-examining the contents or timestamp + of the newly-built target file. + If the target file was not rebuilt during + this &scons; invocation, + then the target file will be examined + the same way as configured by + the &SourceSignature; call + to decide if it has changed. + + </para> + + <para> + + This mimics the behavior of + <literal>build signatures</literal> + in earlier versions of &SCons;. + A &buildsignature; re-combined + signatures of all the input files + that went into making the target file, + so that the target file itself + did not need to have its contents read + to compute an MD5 signature. + This can improve performance for some configurations, + but is generally not as effective as using + <literal>Decider('MD5-timestamp')</literal>. </para> @@ -359,7 +787,7 @@ <para> Now suppose that our "Hello, World!" program - actually has a <literal>#include</literal> line + actually has an <literal>#include</literal> line to include the &hello_h; file in the compilation: </para> @@ -458,7 +886,7 @@ the &cv-CPPPATH; variable may be a list of directories, or a string separated by - the system-specific path separate character + the system-specific path separation character (':' on POSIX/Linux, ';' on Windows). Either way, &SCons; creates the right command-line options @@ -703,7 +1131,44 @@ </section> <section> - <title>Ignoring Dependencies: the &Ignore; Method</title> + <title>Explicit Dependencies: the &Depends; Function</title> + + <para> + + Sometimes a file depends on another file + that is not detected by an &SCons; scanner. + For this situation, + &SCons; allows you to specific explicitly that one file + depends on another file, + and must be rebuilt whenever that file changes. + This is specified using the &Depends; method: + + </para> + + <programlisting> + hello = Program('hello.c') + Depends(hello, 'other_file') + </programlisting> + + <!-- XXX mention that you can use arrays for target and source? --> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit other_file</userinput> + [CHANGE THE CONTENTS OF other_file] + % <userinput>scons -Q hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Ignoring Dependencies: the &Ignore; Function</title> <para> @@ -749,7 +1214,7 @@ Now, the above example is a little contrived, because it's hard to imagine a real-world situation - where you wouldn't to rebuild &hello; + where you wouldn't want to rebuild &hello; if the &hello_h; file changed. A more realistic example might be if the &hello; @@ -774,45 +1239,7 @@ </section> <section> - <title>Explicit Dependencies: the &Depends; Method</title> - - <para> - - On the other hand, - sometimes a file depends on another file - that is not detected by an &SCons; scanner. - For this situation, - &SCons; allows you to specific explicitly that one file - depends on another file, - and must be rebuilt whenever that file changes. - This is specified using the &Depends; method: - - </para> - - <programlisting> - hello = Program('hello.c') - Depends(hello, 'other_file') - </programlisting> - - <!-- XXX mention that you can use arrays for target and source? --> - - <screen> - % <userinput>scons -Q hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - % <userinput>edit other_file</userinput> - [CHANGE THE CONTENTS OF other_file] - % <userinput>scons -Q hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - </screen> - - </section> - - <section> - <title>The &AlwaysBuild; Method</title> + <title>The &AlwaysBuild; Function</title> <para> diff --git a/doc/user/environments.in b/doc/user/environments.in index 504ef67..3fcec02 100644 --- a/doc/user/environments.in +++ b/doc/user/environments.in @@ -391,7 +391,7 @@ environment undisturbed. enabled on the command line, or different executable programs need to be linked with different libraries. - &SCons; accomodates these different build + &SCons; accommodates these different build requirements by allowing you to create and configure multiple &consenvs; that control how the software is built. @@ -416,7 +416,7 @@ environment undisturbed. <para> - By default, &SCons; intializes every + By default, &SCons; initializes every new construction environment with a set of &consvars; based on the tools that it finds on your system, @@ -845,7 +845,7 @@ environment undisturbed. (Note that because we're not expanding this in the context of building something there are no target or source files - for &cv-link-TARGET; and &cv-link-SOURCES; to expand. + for &cv-link-TARGET; and &cv-link-SOURCES; to expand.) </para> diff --git a/doc/user/environments.xml b/doc/user/environments.xml index fbcef99..01ae2ed 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -391,7 +391,7 @@ environment undisturbed. enabled on the command line, or different executable programs need to be linked with different libraries. - &SCons; accomodates these different build + &SCons; accommodates these different build requirements by allowing you to create and configure multiple &consenvs; that control how the software is built. @@ -416,7 +416,7 @@ environment undisturbed. <para> - By default, &SCons; intializes every + By default, &SCons; initializes every new construction environment with a set of &consvars; based on the tools that it finds on your system, @@ -842,7 +842,7 @@ environment undisturbed. (Note that because we're not expanding this in the context of building something there are no target or source files - for &cv-link-TARGET; and &cv-link-SOURCES; to expand. + for &cv-link-TARGET; and &cv-link-SOURCES; to expand.) </para> diff --git a/doc/user/factories.in b/doc/user/factories.in index d0c5313..222f02a 100644 --- a/doc/user/factories.in +++ b/doc/user/factories.in @@ -246,7 +246,7 @@ The &Move; factory allows you to rename a file or directory. For example, if we don't want to copy the temporary file, - we could: + we could use: </para> @@ -334,7 +334,7 @@ a file in a temporary directory in which the processing tool will create other files that we don't care about, - you could: + you could use: </para> diff --git a/doc/user/factories.xml b/doc/user/factories.xml index 7c09e4b..6d0de02 100644 --- a/doc/user/factories.xml +++ b/doc/user/factories.xml @@ -224,7 +224,7 @@ The &Move; factory allows you to rename a file or directory. For example, if we don't want to copy the temporary file, - we could: + we could use: </para> @@ -296,7 +296,7 @@ a file in a temporary directory in which the processing tool will create other files that we don't care about, - you could: + you could use: </para> diff --git a/doc/user/file-removal.in b/doc/user/file-removal.in index adc5b5f..1d1b604 100644 --- a/doc/user/file-removal.in +++ b/doc/user/file-removal.in @@ -101,7 +101,7 @@ By default, &SCons; removes all built targets when invoked with the <literal>-c</literal> option to clean a source tree - of built tragets. + of built targets. Sometimes, however, this is not what you want. For example, you may want to remove only intermediate generated files (such as object files), diff --git a/doc/user/file-removal.xml b/doc/user/file-removal.xml index f64d394..bfec7ac 100644 --- a/doc/user/file-removal.xml +++ b/doc/user/file-removal.xml @@ -94,7 +94,7 @@ By default, &SCons; removes all built targets when invoked with the <literal>-c</literal> option to clean a source tree - of built tragets. + of built targets. Sometimes, however, this is not what you want. For example, you may want to remove only intermediate generated files (such as object files), diff --git a/doc/user/help.in b/doc/user/help.in index 4356d18..5ab7e83 100644 --- a/doc/user/help.in +++ b/doc/user/help.in @@ -105,7 +105,7 @@ <para> - Will display the completely help text on Windows: + Will display the complete help text on Windows: </para> diff --git a/doc/user/help.xml b/doc/user/help.xml index ca44a40..ed2b5de 100644 --- a/doc/user/help.xml +++ b/doc/user/help.xml @@ -108,7 +108,7 @@ <para> - Will display the completely help text on Windows: + Will display the complete help text on Windows: </para> diff --git a/doc/user/hierarchy.in b/doc/user/hierarchy.in index e0d6b00..4286556 100644 --- a/doc/user/hierarchy.in +++ b/doc/user/hierarchy.in @@ -518,7 +518,7 @@ make no difference to the build. so that it may be used by other &SConscript; files. First, you can call the &Export; function with a list of variables, - or a string white-space separated variable names. + or a string of white-space separated variable names. Each call to &Export; adds one or more variables to a global list of variables that are available for import @@ -770,6 +770,10 @@ make no difference to the build. <scons_output_command>scons -Q</scons_output_command> </scons_output> + <!-- + XXX Return(stop=False) + --> + </section> </section> diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml index 4c84d5b..2e2941c 100644 --- a/doc/user/hierarchy.xml +++ b/doc/user/hierarchy.xml @@ -482,7 +482,7 @@ make no difference to the build. so that it may be used by other &SConscript; files. First, you can call the &Export; function with a list of variables, - or a string white-space separated variable names. + or a string of white-space separated variable names. Each call to &Export; adds one or more variables to a global list of variables that are available for import @@ -722,6 +722,10 @@ make no difference to the build. ranlib libprog.a </screen> + <!-- + XXX Return(stop=False) + --> + </section> </section> diff --git a/doc/user/install.in b/doc/user/install.in index ac9510f..ba179e7 100644 --- a/doc/user/install.in +++ b/doc/user/install.in @@ -209,7 +209,7 @@ you can either call the &InstallAs; function multiple times, or as a shorthand, you can supply same-length lists - for the both the target and source arguments: + for both the target and source arguments: </para> diff --git a/doc/user/install.xml b/doc/user/install.xml index 2a6d1b8..dd79153 100644 --- a/doc/user/install.xml +++ b/doc/user/install.xml @@ -201,7 +201,7 @@ you can either call the &InstallAs; function multiple times, or as a shorthand, you can supply same-length lists - for the both the target and source arguments: + for both the target and source arguments: </para> diff --git a/doc/user/libraries.in b/doc/user/libraries.in index 1ccb1c3..73ba6c9 100644 --- a/doc/user/libraries.in +++ b/doc/user/libraries.in @@ -251,6 +251,10 @@ the library will be found in the &cv-link-LIBPATH; construction variable: + <!-- In the preceding paragraph, the "$" notation for + LIBS, LIBPATH etc. is used for the first time. + Maybe some words of explanation would be nice. --> + </para> <scons_example name="ex2"> @@ -427,6 +431,8 @@ <scons_output example="ex3" os="win32"> <scons_output_command>scons -Q</scons_output_command> </scons_output> + <!-- The link command is too wide in the PDF version. + There are some other examples of this throughout the document. --> <para> diff --git a/doc/user/libraries.xml b/doc/user/libraries.xml index 035ebd3..da7d835 100644 --- a/doc/user/libraries.xml +++ b/doc/user/libraries.xml @@ -235,6 +235,10 @@ the library will be found in the &cv-link-LIBPATH; construction variable: + <!-- In the preceding paragraph, the "$" notation for + LIBS, LIBPATH etc. is used for the first time. + Maybe some words of explanation would be nice. --> + </para> <programlisting> @@ -409,6 +413,8 @@ cl /nologo /c prog.c /Foprog.obj link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj </screen> + <!-- The link command is too wide in the PDF version. + There are some other examples of this throughout the document. --> <para> diff --git a/doc/user/main.in b/doc/user/main.in index c3cf2c2..4095e6b 100644 --- a/doc/user/main.in +++ b/doc/user/main.in @@ -103,6 +103,7 @@ XXX GetBuildPath() XXX GetLaunchDir() + XXX ParseConfig() XXX MergeFlags() XXX ParseFlags() @@ -125,6 +126,20 @@ XXX GetOption('num_jobs') XXX SetOption('num_jobs') + XXX Options.UnknownOption() + + XXX GetBuildFailures() + + XXX Requires() + + XXX CheckTypeSize() + + XXX Glob() + + XXX Progress() + + XXX AddMethod() + XXX - - diskcheck= XXX site_scons diff --git a/doc/user/main.xml b/doc/user/main.xml index c3cf2c2..4095e6b 100644 --- a/doc/user/main.xml +++ b/doc/user/main.xml @@ -103,6 +103,7 @@ XXX GetBuildPath() XXX GetLaunchDir() + XXX ParseConfig() XXX MergeFlags() XXX ParseFlags() @@ -125,6 +126,20 @@ XXX GetOption('num_jobs') XXX SetOption('num_jobs') + XXX Options.UnknownOption() + + XXX GetBuildFailures() + + XXX Requires() + + XXX CheckTypeSize() + + XXX Glob() + + XXX Progress() + + XXX AddMethod() + XXX - - diskcheck= XXX site_scons diff --git a/doc/user/parseconfig.in b/doc/user/parseconfig.in index d3f563c..45b58cc 100644 --- a/doc/user/parseconfig.in +++ b/doc/user/parseconfig.in @@ -50,7 +50,7 @@ <scons_example name="ParseConfig1"> <file name="SConstruct" printme="1"> env = Environment() - env.ParseConfig("pkg-config") + env.ParseConfig("pkg-config x11") </file> <file name="f1.c"> int f1() { } diff --git a/doc/user/parseconfig.xml b/doc/user/parseconfig.xml index 067ef37..25ea12c 100644 --- a/doc/user/parseconfig.xml +++ b/doc/user/parseconfig.xml @@ -49,7 +49,7 @@ <programlisting> env = Environment() - env.ParseConfig("pkg-config") + env.ParseConfig("pkg-config x11") </programlisting> <para> @@ -62,7 +62,6 @@ <screen> % <userinput>scons -Q</userinput> scons: `.' is up to date. - Must specify package names on the command line </screen> <para> diff --git a/doc/user/repositories.in b/doc/user/repositories.in index 9065593..d4ed418 100644 --- a/doc/user/repositories.in +++ b/doc/user/repositories.in @@ -487,8 +487,8 @@ coming into existence.) Usually, this would be done by a build integrator who would run &SCons; in the repository to create all of its derived files and &sconsign; files, - or who would &SCons; in a separate build directory - and copying the resulting tree to the desired repository: + or who would run &SCons; in a separate build directory + and copy the resulting tree to the desired repository: </para> @@ -552,7 +552,7 @@ coming into existence.) <para> Notice that &SCons; realizes that it does not need to - rebuild local copies file1.o and file2.o files, + rebuild local copies <filename>file1.o</filename> and <filename>file2.o</filename> files, but instead uses the already-compiled files from the repository. diff --git a/doc/user/repositories.xml b/doc/user/repositories.xml index f22611b..766d8bc 100644 --- a/doc/user/repositories.xml +++ b/doc/user/repositories.xml @@ -457,8 +457,8 @@ coming into existence.) Usually, this would be done by a build integrator who would run &SCons; in the repository to create all of its derived files and &sconsign; files, - or who would &SCons; in a separate build directory - and copying the resulting tree to the desired repository: + or who would run &SCons; in a separate build directory + and copy the resulting tree to the desired repository: </para> @@ -511,7 +511,7 @@ coming into existence.) <para> Notice that &SCons; realizes that it does not need to - rebuild local copies file1.o and file2.o files, + rebuild local copies <filename>file1.o</filename> and <filename>file2.o</filename> files, but instead uses the already-compiled files from the repository. diff --git a/doc/user/sconf.in b/doc/user/sconf.in index 0165ddd..265b720 100644 --- a/doc/user/sconf.in +++ b/doc/user/sconf.in @@ -124,7 +124,7 @@ Note that you can choose to terminate the build if a given header file doesn't exist, - or you can modify the contstruction environment + or you can modify the construction environment based on the existence of a header file. </para> diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml index df530fe..163db3b 100644 --- a/doc/user/sconf.xml +++ b/doc/user/sconf.xml @@ -124,7 +124,7 @@ Note that you can choose to terminate the build if a given header file doesn't exist, - or you can modify the contstruction environment + or you can modify the construction environment based on the existence of a header file. </para> diff --git a/doc/user/simple.in b/doc/user/simple.in index b468f9a..3382f86 100644 --- a/doc/user/simple.in +++ b/doc/user/simple.in @@ -508,7 +508,7 @@ Because we want this User's Guide to focus on what &SCons; is actually doing, - we're going use the &Q; option + we're going to use the &Q; option to remove these messages from the output of all the remaining examples in this Guide. diff --git a/doc/user/simple.xml b/doc/user/simple.xml index c5ef430..4e4ff0e 100644 --- a/doc/user/simple.xml +++ b/doc/user/simple.xml @@ -542,7 +542,7 @@ Because we want this User's Guide to focus on what &SCons; is actually doing, - we're going use the &Q; option + we're going to use the &Q; option to remove these messages from the output of all the remaining examples in this Guide. diff --git a/doc/user/sourcecode.xml b/doc/user/sourcecode.xml index 6cb4162..1818d8e 100644 --- a/doc/user/sourcecode.xml +++ b/doc/user/sourcecode.xml @@ -50,7 +50,6 @@ <screen> % <userinput>scons -Q</userinput> - bk get - bk get hello.c cc -o hello.o -c hello.c cc -o hello hello.o @@ -75,7 +74,6 @@ <screen> % <userinput>scons -Q</userinput> - cvs -d /usr/local/CVS co - cvs -d /usr/local/CVS co hello.c cc -o hello.o -c hello.c cc -o hello hello.o @@ -100,7 +98,6 @@ <screen> % <userinput>scons -Q</userinput> - co - co hello.c cc -o hello.o -c hello.c cc -o hello hello.o @@ -125,7 +122,6 @@ <screen> % <userinput>scons -Q</userinput> - sccs get - sccs get hello.c cc -o hello.o -c hello.c cc -o hello hello.o diff --git a/doc/user/troubleshoot.in b/doc/user/troubleshoot.in index 11f44dd..3e0bfdb 100644 --- a/doc/user/troubleshoot.in +++ b/doc/user/troubleshoot.in @@ -241,7 +241,7 @@ Although this is usually helpful and what you want, it might be frustrating if &SCons; doesn't set certain variables that you - expect to be sit. + expect to be set. In situations like this, it's sometimes helpful to use the construction environment &Dump; method @@ -292,6 +292,10 @@ In a real-life situation, the construction environments will likely contain a great many more variables. + Also note that we've massaged the example output above + to make the memory address of all objects a constant 0x700000. + In reality, you would see a different hexadecimal + number for each object. </para> diff --git a/doc/user/troubleshoot.xml b/doc/user/troubleshoot.xml index 6ec6185..ca5ace8 100644 --- a/doc/user/troubleshoot.xml +++ b/doc/user/troubleshoot.xml @@ -232,7 +232,7 @@ Although this is usually helpful and what you want, it might be frustrating if &SCons; doesn't set certain variables that you - expect to be sit. + expect to be set. In situations like this, it's sometimes helpful to use the construction environment &Dump; method @@ -261,7 +261,7 @@ <screen> % <userinput>scons</userinput> scons: Reading SConscript files ... - { 'BUILDERS': {'InstallAs': <function InstallAsBuilderWrapper at 0xb23a28>, 'Install': <function InstallBuilderWrapper at 0xb1b7d0>}, + { 'BUILDERS': {'InstallAs': <function InstallAsBuilderWrapper at 0x700000>, 'Install': <function InstallBuilderWrapper at 0x700000>}, 'CONFIGUREDIR': '#/.sconf_temp', 'CONFIGURELOG': '#/config.log', 'CPPSUFFIXES': [ '.c', @@ -284,13 +284,13 @@ '.spp', '.SPP'], 'DSUFFIXES': ['.d'], - 'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0xa1eb48>, - 'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0xa1eb90>, + 'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, 'ENV': {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}, - 'ESCAPE': <function escape at 0xb1fa28>, - 'File': <SCons.Defaults.Variable_Method_Caller instance at 0xa1ebd8>, + 'ESCAPE': <function escape at 0x700000>, + 'File': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, 'IDLSUFFIXES': ['.idl', '.IDL'], - 'INSTALL': <function copyFunc at 0xb23aa0>, + 'INSTALL': <function copyFunc at 0x700000>, 'LATEXSUFFIXES': ['.tex', '.ltx', '.latex'], 'LIBPREFIX': 'lib', 'LIBPREFIXES': '$LIBPREFIX', @@ -302,16 +302,16 @@ 'PLATFORM': 'posix', 'PROGPREFIX': '', 'PROGSUFFIX': '', - 'PSPAWN': <function piped_env_spawn at 0xb23230>, - 'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0xa1ec20>, + 'PSPAWN': <function piped_env_spawn at 0x700000>, + 'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, 'SCANNERS': [], 'SHELL': 'sh', 'SHLIBPREFIX': '$LIBPREFIX', 'SHLIBSUFFIX': '.so', 'SHOBJPREFIX': '$OBJPREFIX', 'SHOBJSUFFIX': '$OBJSUFFIX', - 'SPAWN': <function spawnvpe_spawn at 0xb1f7d0>, - 'TEMPFILE': <class SCons.Platform.TempFileMunge at 0xa4e170>, + 'SPAWN': <function spawnvpe_spawn at 0x700000>, + 'TEMPFILE': <class SCons.Platform.TempFileMunge at 0x700000>, 'TEMPFILEPREFIX': '@', 'TOOLS': ['install', 'install'], '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', @@ -319,9 +319,9 @@ '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', '__RPATH': '$_RPATH', - '_concat': <function _concat at 0xa3d398>, - '_defines': <function _defines at 0xa3d500>, - '_stripixes': <function _stripixes at 0xa3d488>} + '_concat': <function _concat at 0x700000>, + '_defines': <function _defines at 0x700000>, + '_stripixes': <function _stripixes at 0x700000>} scons: done reading SConscript files. scons: Building targets ... scons: `.' is up to date. @@ -338,9 +338,9 @@ <screen> C:\><userinput>scons</userinput> scons: Reading SConscript files ... - { 'BUILDERS': {'RES': <SCons.Builder.BuilderBase instance at 0xb39518>, 'Object': <SCons.Builder.CompositeBuilder instance at 0xb4a710>, 'InstallAs': <function InstallAsBuilderWrapper at 0xb45c08>, 'PCH': <SCons.Builder.BuilderBase instance at 0xb1cef0>, 'Install': <function InstallBuilderWrapper at 0xb1b7d0>, 'SharedObject': <SCons.Builder.CompositeBuilder instance at 0xb4aa28>, 'StaticObject': <SCons.Builder.CompositeBuilder instance at 0xb4a710>}, + { 'BUILDERS': {'RES': <SCons.Builder.BuilderBase instance at 0x700000>, 'Object': <SCons.Builder.CompositeBuilder instance at 0x700000>, 'InstallAs': <function InstallAsBuilderWrapper at 0x700000>, 'PCH': <SCons.Builder.BuilderBase instance at 0x700000>, 'Install': <function InstallBuilderWrapper at 0x700000>, 'SharedObject': <SCons.Builder.CompositeBuilder instance at 0x700000>, 'StaticObject': <SCons.Builder.CompositeBuilder instance at 0x700000>}, 'CC': 'cl', - 'CCCOM': <SCons.Action.FunctionAction instance at 0xb4c290>, + 'CCCOM': <SCons.Action.FunctionAction instance at 0x700000>, 'CCCOMFLAGS': '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS', 'CCFLAGS': ['/nologo'], 'CCPCHFLAGS': ['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'], @@ -375,19 +375,19 @@ 'CXXFILESUFFIX': '.cc', 'CXXFLAGS': ['$CCFLAGS', '$(', '/TP', '$)'], 'DSUFFIXES': ['.d'], - 'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0xa1eb48>, - 'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0xa1eb90>, + 'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, 'ENV': { 'INCLUDE': 'C:\\Program Files\\Microsoft Visual Studio/VC98\\include', 'LIB': 'C:\\Program Files\\Microsoft Visual Studio/VC98\\lib', 'PATH': 'C:\\Program Files\\Microsoft Visual Studio\\Common\\tools\\WIN95;C:\\Program Files\\Microsoft Visual Studio\\Common\\MSDev98\\bin;C:\\Program Files\\Microsoft Visual Studio\\Common\\tools;C:\\Program Files\\Microsoft Visual Studio/VC98\\bin', 'PATHEXT': '.COM;.EXE;.BAT;.CMD', 'SystemRoot': 'C:/WINDOWS'}, - 'ESCAPE': <function escape at 0xb24848>, - 'File': <SCons.Defaults.Variable_Method_Caller instance at 0xa1ebd8>, + 'ESCAPE': <function escape at 0x700000>, + 'File': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, 'IDLSUFFIXES': ['.idl', '.IDL'], 'INCPREFIX': '/I', 'INCSUFFIX': '', - 'INSTALL': <function copyFunc at 0xb45c80>, + 'INSTALL': <function copyFunc at 0x700000>, 'LATEXSUFFIXES': ['.tex', '.ltx', '.latex'], 'LIBPREFIX': '', 'LIBPREFIXES': ['$LIBPREFIX'], @@ -403,14 +403,14 @@ 'PLATFORM': 'win32', 'PROGPREFIX': '', 'PROGSUFFIX': '.exe', - 'PSPAWN': <function piped_spawn at 0xb20488>, + 'PSPAWN': <function piped_spawn at 0x700000>, 'RC': 'rc', 'RCCOM': '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES', 'RCFLAGS': [], - 'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0xa1ec20>, + 'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, 'SCANNERS': [], 'SHCC': '$CC', - 'SHCCCOM': <SCons.Action.FunctionAction instance at 0xb4c320>, + 'SHCCCOM': <SCons.Action.FunctionAction instance at 0x700000>, 'SHCCFLAGS': ['$CCFLAGS'], 'SHCFLAGS': ['$CFLAGS'], 'SHCXX': '$CXX', @@ -421,18 +421,18 @@ 'SHLIBSUFFIX': '.dll', 'SHOBJPREFIX': '$OBJPREFIX', 'SHOBJSUFFIX': '$OBJSUFFIX', - 'SPAWN': <function spawn at 0xb247d0>, + 'SPAWN': <function spawn at 0x700000>, 'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1, - 'TEMPFILE': <class SCons.Platform.TempFileMunge at 0xa4e170>, + 'TEMPFILE': <class SCons.Platform.TempFileMunge at 0x700000>, 'TEMPFILEPREFIX': '@', 'TOOLS': ['msvc', 'install', 'install'], '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', - '_concat': <function _concat at 0xa3d398>, - '_defines': <function _defines at 0xa3d500>, - '_stripixes': <function _stripixes at 0xa3d488>} + '_concat': <function _concat at 0x700000>, + '_defines': <function _defines at 0x700000>, + '_stripixes': <function _stripixes at 0x700000>} scons: done reading SConscript files. scons: Building targets ... scons: `.' is up to date. @@ -447,6 +447,10 @@ In a real-life situation, the construction environments will likely contain a great many more variables. + Also note that we've massaged the example output above + to make the memory address of all objects a constant 0x700000. + In reality, you would see a different hexadecimal + number for each object. </para> @@ -552,7 +556,6 @@ cc -o f3.o -c -I. f3.c cc -o prog f1.o f2.o f3.o +-. - +-- +-SConstruct +-f1.c +-f1.o @@ -659,31 +662,30 @@ H = no cache [E b ]+-. - [ ] +-- - [E ] +-SConstruct - [E ] +-f1.c + [E C ] +-SConstruct + [E C ] +-f1.c [E B C ] +-f1.o - [E ] | +-f1.c - [E ] | +-inc.h - [E ] +-f2.c + [E C ] | +-f1.c + [E C ] | +-inc.h + [E C ] +-f2.c [E B C ] +-f2.o - [E ] | +-f2.c - [E ] | +-inc.h - [E ] +-f3.c + [E C ] | +-f2.c + [E C ] | +-inc.h + [E C ] +-f3.c [E B C ] +-f3.o - [E ] | +-f3.c - [E ] | +-inc.h - [E ] +-inc.h + [E C ] | +-f3.c + [E C ] | +-inc.h + [E C ] +-inc.h [E B C ] +-prog [E B C ] +-f1.o - [E ] | +-f1.c - [E ] | +-inc.h + [E C ] | +-f1.c + [E C ] | +-inc.h [E B C ] +-f2.o - [E ] | +-f2.c - [E ] | +-inc.h + [E C ] | +-f2.c + [E C ] | +-inc.h [E B C ] +-f3.o - [E ] +-f3.c - [E ] +-inc.h + [E C ] +-f3.c + [E C ] +-inc.h </screen> <para> @@ -707,6 +709,13 @@ cc -o f3.o -c -I. f3.c cc -o prog f1.o f2.o f3.o +-. + +-f1.o + +-f2.o + +-f3.o + +-prog + +-f1.o + +-f2.o + +-f3.o </screen> <para> @@ -790,7 +799,6 @@ cc -o prog2.o -c -I. prog2.c cc -o prog2 prog2.o -L. -lfoo +-. - +-- +-SConstruct +-f1.c +-f1.o @@ -883,7 +891,6 @@ cc -o prog2.o -c -I. prog2.c cc -o prog2 prog2.o -L. -lfoo +-. - +-- +-SConstruct +-f1.c +-f1.o @@ -1109,9 +1116,10 @@ scons: *** Source `prog.c' not found, needed by target `prog.o'. Stop. scons: internal stack trace: File "bootstrap/src/engine/SCons/Job.py", line 114, in start + File "bootstrap/src/engine/SCons/Script/Main.py", line 157, in prepare File "bootstrap/src/engine/SCons/Taskmaster.py", line 169, in prepare - File "bootstrap/src/engine/SCons/Node/FS.py", line 2220, in prepare - File "bootstrap/src/engine/SCons/Node/__init__.py", line 819, in prepare + File "bootstrap/src/engine/SCons/Node/FS.py", line 2568, in prepare + File "bootstrap/src/engine/SCons/Node/__init__.py", line 349, in prepare </screen> <para> @@ -1168,17 +1176,22 @@ % <userinput>scons -Q --taskmastertrace=- prog</userinput> Taskmaster: 'prog': children: ['prog.o'] - waiting on unstarted children: + waiting on unfinished children: ['prog.o'] Taskmaster: 'prog.o': children: ['inc.h', 'prog.c'] + waiting on unfinished children: + ['inc.h', 'prog.c'] + Taskmaster: 'prog.c': evaluating prog.c + Taskmaster: 'inc.h': evaluating inc.h + Taskmaster: 'prog.o': children: + ['inc.h', 'prog.c'] evaluating prog.o cc -o prog.o -c -I. prog.c Taskmaster: 'prog': children: ['prog.o'] evaluating prog cc -o prog prog.o - Taskmaster: 'prog': already handled (executed) </screen> <para> |