Anonymous avatar Anonymous committed a757ca8

Merged revisions 2725-2865 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core

........
r2731 | stevenknight | 2008-04-01 09:22:37 -0700 (Tue, 01 Apr 2008) | 4 lines

Fix test/Interactive/version.py, which still had the old hard-coded
Copyright string, by moving the test copy of the Copyright string
into QMTest/TestSCons.py, where it's available to all test scripts.
........
r2732 | stevenknight | 2008-04-02 13:28:32 -0700 (Wed, 02 Apr 2008) | 3 lines

Issues 317, 323, 329: Ignore the -d, -e and -w options, which we're
not going to implement.
........
r2734 | stevenknight | 2008-04-05 07:50:49 -0700 (Sat, 05 Apr 2008) | 2 lines

Fix bootstrap.py for pre-2.3 versions of Python, which don't have __file__.
........
r2735 | stevenknight | 2008-04-05 07:54:44 -0700 (Sat, 05 Apr 2008) | 2 lines

Fix the non-breaking-hyphen regular expression(s) for Python 1.5.
........
r2736 | garyo | 2008-04-05 19:15:52 -0700 (Sat, 05 Apr 2008) | 1 line

Added Users Guide section for AddMethod.
........
r2737 | stevenknight | 2008-04-08 09:43:31 -0700 (Tue, 08 Apr 2008) | 3 lines

Don't raise strings as exceptions in the exception-handling unit tests.
That's now deprecated Python behavior.
........
r2738 | stevenknight | 2008-04-08 10:36:00 -0700 (Tue, 08 Apr 2008) | 5 lines

Address a serious inefficiency in Java builds by moving the pre-build
check for whether source files exist from the Node class to the Executor
class, so we only have to perform the check once when building a whole
bunch of targets from a whole bunch of sources.
........
r2739 | stevenknight | 2008-04-08 13:53:44 -0700 (Tue, 08 Apr 2008) | 2 lines

Add a backwards-compatibility version of the "itertools" module.
........
r2740 | stevenknight | 2008-04-08 14:12:05 -0700 (Tue, 08 Apr 2008) | 2 lines

Issue 1961: speed up SCons.Util.to_String*() functions. (Benoit Belley)
........
r2741 | stevenknight | 2008-04-08 14:15:36 -0700 (Tue, 08 Apr 2008) | 2 lines

Use the itertools.izip() method for some key Node.FS methods. (Benoit Belley)
........
r2742 | stevenknight | 2008-04-08 14:35:35 -0700 (Tue, 08 Apr 2008) | 2 lines

Issues 1961: use izip() instead of zip() where possible (Benoit Belley)
........
r2743 | stevenknight | 2008-04-08 14:48:08 -0700 (Tue, 08 Apr 2008) | 3 lines

Issue 1961: more efficient get_contents() implementation for Python
function Actions. (Benoit Belley)
........
r2744 | stevenknight | 2008-04-08 17:55:30 -0700 (Tue, 08 Apr 2008) | 3 lines

Issue 1961: make SCons.Node.* state variables global in Taskmaster.py so
we avoid unneceesary attribute fetches. (Benoit Belley)
........
r2745 | stevenknight | 2008-04-08 20:40:31 -0700 (Tue, 08 Apr 2008) | 2 lines

Issue 1961: Optimize the code in Node.get_binfo(). (Benoit Belley)
........
r2746 | stevenknight | 2008-04-08 21:05:17 -0700 (Tue, 08 Apr 2008) | 3 lines

Issue 1961: Enhance the backwards-compatibility sets() module with the
ability to compare sets. (Benoit Belley)
........
r2747 | stevenknight | 2008-04-08 22:11:20 -0700 (Tue, 08 Apr 2008) | 2 lines

Issue 1961: Optimize Executor.scan(). (Benoit Belley)
........
r2748 | stevenknight | 2008-04-08 22:17:55 -0700 (Tue, 08 Apr 2008) | 3 lines

Python 1.5 compatibility: use for p in paths.keys() for dictionaries.
(Benoit Belley)
........
r2749 | stevenknight | 2008-04-08 22:54:02 -0700 (Tue, 08 Apr 2008) | 10 lines

Issue 1961: additional build optimizations:
-- Make taskmastertrace output more useful and readable.
-- Move dependency cycle checking to avoid re-doing it.
-- Have Nodes use sets, not dictionaries, to track various things.
-- Eliminate intermediate function calls from fetching Node children.
-- Add a Task.needs_execute() method to avoid doing that check over and
over as part of needs_execute().
-- Remove the unused Node.found_includes attribute.
(Benoit Belley)
........
r2750 | stevenknight | 2008-04-09 14:47:44 -0700 (Wed, 09 Apr 2008) | 4 lines

Make target Java .class files depend *only* on the input .java files as
their sources when determining if they require rebuilding. This eliminates
O(NxM) checking for every single edge in a big, overly-connected DAG mesh.
........
r2751 | stevenknight | 2008-04-09 16:58:41 -0700 (Wed, 09 Apr 2008) | 2 lines

Remove 0.95 and 0.96* release notes.
........
r2752 | stevenknight | 2008-04-10 02:24:50 -0700 (Thu, 10 Apr 2008) | 2 lines

Issue 1956: Fix --debug=stree printing its tree twice. (Benoit Belley)
........
r2753 | stevenknight | 2008-04-10 02:33:28 -0700 (Thu, 10 Apr 2008) | 2 lines

Issue 1896: Add support for the GDC D language compiler. (Matthew Wesley)
........
r2754 | stevenknight | 2008-04-10 02:39:24 -0700 (Thu, 10 Apr 2008) | 2 lines

Fix tabs.
........
r2755 | stevenknight | 2008-04-10 02:41:50 -0700 (Thu, 10 Apr 2008) | 3 lines

Issue 1964: Fix passing variable names in a list to Return() (as
already documented in the man page!) (Mike Wake)
........
r2756 | stevenknight | 2008-04-10 02:55:40 -0700 (Thu, 10 Apr 2008) | 2 lines

Support the ability to download 2.6 candidate releases (e.g. 2.6a2).
........
r2757 | stevenknight | 2008-04-10 02:58:35 -0700 (Thu, 10 Apr 2008) | 3 lines

Issue 1669: Fix the ability to use LoadableModule() under MinGW.
(Johan Boule)
........
r2758 | stevenknight | 2008-04-10 03:03:15 -0700 (Thu, 10 Apr 2008) | 3 lines

Update the test/Interactive/tree.py script for Benoit's fix to
remove duplicate tree printing.
........
r2759 | stevenknight | 2008-04-10 06:43:44 -0700 (Thu, 10 Apr 2008) | 3 lines

Fix Tool/dmd.py when no D compiler is installed -- we don't want to
search for a path if the result is None.
........
r2760 | GregNoel | 2008-04-10 15:30:34 -0700 (Thu, 10 Apr 2008) | 1 line

Issue 2009: separate Debug.caller() by functionality
........
r2761 | stevenknight | 2008-04-11 04:47:25 -0700 (Fri, 11 Apr 2008) | 3 lines

Issue 1882: Add the scons.bat directory to %PATH% so it can find python.exe.
(Anatoly Techtonik)
........
r2762 | stevenknight | 2008-04-11 09:15:22 -0700 (Fri, 11 Apr 2008) | 4 lines

Issues 1835,1901: fix the ability to list a source file multiple
times for a target by making sure we only store unique entries in the
.sconsign file.
........
r2763 | stevenknight | 2008-04-11 10:58:26 -0700 (Fri, 11 Apr 2008) | 4 lines

Issue 1882: Fix earlier patch to scons.bat by adding ~dp0;~dp0.. to
the front of %PATH%, and only executing endlocal on NT-based systems.
(Anatoly Techtonik)
........
r2764 | stevenknight | 2008-04-11 13:06:29 -0700 (Fri, 11 Apr 2008) | 4 lines

Add a Variables object and {Bool,Envum,List,Package,Path}Variable()
functions as a first step towards eventually deprecating the
Options object and {Bool,Envum,List,Package,Path}Option() functions.
........
r2765 | stevenknight | 2008-04-11 18:13:53 -0700 (Fri, 11 Apr 2008) | 3 lines

Issue 1962: Capture a test case for ListActions that contain a
command-line string containing unicode, and Python FunctionAction.
........
r2766 | stevenknight | 2008-04-11 22:03:14 -0700 (Fri, 11 Apr 2008) | 3 lines

Issue 1933: expect .py files generated by the SWIG -python option
to be in the same (sub)directory as the target.
........
r2767 | stevenknight | 2008-04-12 06:41:57 -0700 (Sat, 12 Apr 2008) | 2 lines

Remove the SCons.Options package in favor of the new SCons.Variables package.
........
r2768 | stevenknight | 2008-04-12 13:33:52 -0700 (Sat, 12 Apr 2008) | 5 lines

Issue 1971: Move the incorporation of $CCFLAGS and $SHCCFLAGS directly
into the C++ command lines (${SHCXX,CXX}COM) instead of through indirect
expansion of $CXXFLAGS and $SHCXXFLAGS. This requires removing -fPIC
from the default setting of $SHCXXFLAGS under the GNU toolchain.
........
r2769 | stevenknight | 2008-04-13 07:01:27 -0700 (Sun, 13 Apr 2008) | 3 lines

Fix __all__ definitions in the Variables/*Variable.py file that were
cause epydoc to blow up when generating developer documentation.
........
r2770 | stevenknight | 2008-04-13 11:47:49 -0700 (Sun, 13 Apr 2008) | 3 lines

Add variables= keyword argument to Environment() creation as a first
step towards deprecating options=.
........
r2771 | stevenknight | 2008-04-13 11:54:19 -0700 (Sun, 13 Apr 2008) | 2 lines

Correct underscore-instead-of-hyphen misspellings in option names.
........
r2772 | bdbaddog | 2008-04-13 17:39:21 -0700 (Sun, 13 Apr 2008) | 3 lines

Changes to fix 15 tests which were failing on cygwin.
........
r2773 | GregNoel | 2008-04-13 22:31:07 -0700 (Sun, 13 Apr 2008) | 1 line

Various fixes to tests on Darwin using 1.5.2
........
r2774 | stevenknight | 2008-04-14 15:00:44 -0700 (Mon, 14 Apr 2008) | 2 lines

Python 1.5.2 fix in new test/SWIG/subdir.py script (use the -classic option).
........
r2775 | belley | 2008-04-14 18:02:40 -0700 (Mon, 14 Apr 2008) | 32 lines

Dont use KeyboardInterrupt to stop a build! [Issue 1907]

SCons would often hang after pressing Ctrl-C. I started investigating and I
realized that most of the Python libraries are not really safe with respect to
asynchronous exceptions. Although,there are enough try/finally blocks to handle
exceptions thrown synchronously by the library code, the Python libraries are
not always protected against exceptions being thrown asynchronously, such as a
KeyboardInterrupt being thrown at a completely random location.

For example, the function Queue.empty() does not protect its mutex with a
try/finally block. If the KeyboardInterrupt exception gets thrown while the
mutex is held, any further attempt to access the Queue will lead to dead-lock
(explaining why SCons hangs sometimes after pressing CTRL-C). Even the
threading.Condition condition variables are not async-exception safe. It
therefore seems a lost battle to try to stop a build by raising an exception.

Instead, I have implemented a signal handler that tells the Jobs (and its
associated Taskmaster) to stop the build. I have been careful to wait after the
.sconsign file has been written back to re-install the default SIGINT signal
handler that raises a KeyboardInterrupt exception.

This patch is submitted against changeset 2773 of branches/core. The
regression test suite has been run on RHEL4 using Pyhon 2.5.1 and
1.5.2. My team has been using an SCons build with this patch for a
while now on Windows, Linux and OSX.

See:
http://scons.tigris.org/issues/show_bug.cgi?id=1907

Benoit Belley
........
r2777 | cournape | 2008-04-14 20:11:56 -0700 (Mon, 14 Apr 2008) | 3 lines

Initialized merge tracking via "svnmerge" with revisions "1-2776" from
http://scons.tigris.org/svn/scons/branches/fortran_refactor
........
r2788 | stevenknight | 2008-04-14 22:09:27 -0700 (Mon, 14 Apr 2008) | 2 lines

Fix the print the "script" line in the --version output.
........
r2789 | stevenknight | 2008-04-14 22:18:27 -0700 (Mon, 14 Apr 2008) | 2 lines

Add a __COPYRIGHT__ line.
........
r2790 | stevenknight | 2008-04-14 22:20:39 -0700 (Mon, 14 Apr 2008) | 3 lines

Issue 2008: in checkpoint releases, use a '.' to separate (e.g.) 0.98.0
from 0d20080414.
........
r2817 | belley | 2008-04-15 06:44:21 -0700 (Tue, 15 Apr 2008) | 13 lines

TestSCons.up_to_date() should use match_re_dotall

I changed TestSCons.up_to_date() to use match_re_dotall instead of
match_exact. This is necessary so that I can call up_to_date() with
the TestSCons.deprecated_python_expr error message in one of my test.

Note that TestSCons.not_up_to_date() is already using match_re_dotall.

Ran the test suite on both Python 2.5.1 and 1.5.2.

Benoit
........
r2818 | belley | 2008-04-15 12:10:52 -0700 (Tue, 15 Apr 2008) | 10 lines

Improved the multiple-parents.py test to also tests the following
cases:

d) Some children are ignored
e) Some children are pre-requesites
f) Some sources are missing

The test still passes. No extra bug were found.
........
r2850 | stevenknight | 2008-04-16 11:15:24 -0700 (Wed, 16 Apr 2008) | 4 lines

Fix problems with the __del__() method referencing other module functions
through global variables, which can get deleted out from under us at
shutdown.
........
r2851 | stevenknight | 2008-04-16 11:17:07 -0700 (Wed, 16 Apr 2008) | 4 lines

Fix use of --interactive with -u/-U/-D and VariantDir() by making the
method that cleans Node states between interactive commands aware of
the alter_targets() method that tells us about an associated VariantDir().
........

Comments (0)

Files changed (163)

QMTest/TestSCons.py

 
 default_version = '0.98.0'
 
+copyright_years = '2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008'
+
 SConsVersion = '0.98.0'
 if SConsVersion == '__' + 'VERSION' + '__':
     SConsVersion = default_version
                 arguments = options + " " + arguments
         kw['arguments'] = arguments
         kw['stdout'] = self.wrap_stdout(read_str = read_str, build_str = s)
-        kw['match'] = self.match_exact
+        kw['stdout'] = string.replace(kw['stdout'],'\n','\\n')
+        kw['stdout'] = string.replace(kw['stdout'],'.','\\.')
+        kw['match'] = self.match_re_dotall
         apply(self.run, [], kw)
 
     def not_up_to_date(self, options = None, arguments = None, **kw):
             time.sleep(1.0)
             waited = waited + 1.0
 
+    def get_alt_cpp_suffix(self):
+        """
+        Many CXX tests have this same logic.
+        They all needed to determine if the current os supports
+        files with .C and .c as different files or not
+        in which case they are instructed to use .cpp instead of .C
+        """
+        if not case_sensitive_suffixes('.c','.C'):
+            alt_cpp_suffix = '.cpp'
+        else:
+            alt_cpp_suffix = '.C'
+        return alt_cpp_suffix
+    
+
 # In some environments, $AR will generate a warning message to stderr
 # if the library doesn't previously exist and is being created.  One
 # way to fix this is to tell AR to be quiet (sometimes the 'c' flag),
 # See the README file for an overview of how SCons is built and tested.
 #
 
-# When this gets changed, you also need to change test/option-v.py
-# so it looks for the right string.
+# When this gets changed, you must also change the copyright_years string
+# in QMTest/TestSCons.py so the test scripts look for the right string.
 copyright_years = '2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008'
 
 # This gets inserted into the man pages to reflect the month of release.
         checkpoint = time.strftime('d%Y%m%d', time.localtime(time.time()))
     elif checkpoint == 'r':
         checkpoint = 'r' + revision
-    version = version + checkpoint
+    version = version + '.' + checkpoint
 
 svn_status = None
 svn_status_lines = []

bin/install-python.sh

 }
 
 for VERSION in $VERSIONS; do
+    DIR=`expr "$VERSION" : '\(...\)'`
     PYTHON=Python-${VERSION}
 
     TAR_GZ=${PYTHON}.tgz
         if test ! -d ${DOWNLOADS}; then
             Command mkdir ${DOWNLOADS}
         fi
-        Command "( cd ${DOWNLOADS} && wget ${DOWNLOADS_URL}/${VERSION}/${TAR_GZ} )"
+        Command "( cd ${DOWNLOADS} && wget ${DOWNLOADS_URL}/${DIR}/${TAR_GZ} )"
     fi
 
     Command tar zxf ${DOWNLOADS}/${TAR_GZ}
         ${PRINT} cd ..
     )
 
-    Command rm -rf ${Python}
+    Command rm -rf ${PYTHON}
 done
 """
 
 bootstrap_dir = 'bootstrap'
-script_dir = os.path.split(__file__)[0]
+try:
+    script_dir = os.path.split(__file__)[0]
+except NameError:
+    # Pre-2.3 versions of Python don't have __file__.
+    script_dir = os.path.split(sys.argv[0])[0]
+    if not script_dir:
+        script_dir = os.getcwd()
+    elif not os.path.is_abs(script_dir):
+        script_dir = os.path.join(os.getcwd(), script_dir)
 if script_dir:
     bootstrap_dir = os.path.join(script_dir, bootstrap_dir)
 pass_through_args = []
 
     epydoc_commands = [
         Delete('$OUTDIR'),
-        '$EPYDOC $EPYDOCFLAGS --output $OUTDIR --docformat=restructuredText --name SCons --url http://www.scons.org/ $SOURCES',
+        '$EPYDOC $EPYDOCFLAGS --debug --output $OUTDIR --docformat=restructuredText --name SCons --url http://www.scons.org/ $SOURCES',
         Touch('$TARGET'),
     ]
 
 .TP 6
 .B cache_debug
 .TP 6
-which corresponds to --cache_debug;
+which corresponds to --cache-debug;
 .TP 6
 .B cache_disable
-which corresponds to --cache_disable;
+which corresponds to --cache-disable;
 .TP 6
 .B cache_force
-which corresponds to --cache_force;
+which corresponds to --cache-force;
 .TP 6
 .B cache_show
-which corresponds to --cache_show;
+which corresponds to --cache-show;
 .TP 6
 .B clean
 which corresponds to -c, --clean and --remove;
 env = conf.Finish() 
 .EE
 
-.SS Construction Variable Options
-
-Often when building software, various options need to be specified at build
-time that are not known when the SConstruct/SConscript files are
-written. For example, libraries needed for the build may be in non-standard
+.SS Command-Line Construction Variables
+
+Often when building software,
+some variables must be specified at build time.
+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 an Options object for overridding construction variables
+provides a
+.B Variables
+object to support overriding 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 ])
-This creates an Options object that will read construction variables from
+To create a Variables object, call the Variables() function:
+
+.TP
+.RI Variables([ files "], [" args ])
+This creates a Variables object that will read construction variables from
 the file or list of filenames specified in
 .IR files .
 If no files are specified,
 Example:
 
 .ES
-opts = Options('custom.py')
-opts = Options('overrides.py', ARGUMENTS)
-opts = Options(None, {FOO:'expansion', BAR:7})
-.EE
-
-Options objects have the following methods:
+vars = Variables('custom.py')
+vars = Variables('overrides.py', ARGUMENTS)
+vars = Variables(None, {FOO:'expansion', BAR:7})
+.EE
+
+Variables objects have the following methods:
 
 .TP
 .RI Add( key ", [" help ", " default ", " validator ", " converter ])
-This adds a customizable construction variable to the Options object. 
+This adds a customizable construction variable to the Variables object. 
 .I key
 is the name of the variable. 
 .I help 
 Examples:
 
 .ES
-opts.Add('CC', 'The C compiler')
+vars.Add('CC', 'The C compiler')
 
 def validate_color(key, val, env):
     if not val in ['red', 'blue', 'yellow']:
         raise "Invalid color value '%s'" % val
-opts.Add('COLOR', validator=valid_color)
-.EE
-
-.TP
-.RI AddOptions( list )
+vars.Add('COLOR', validator=valid_color)
+.EE
+
+.TP
+.RI AddVariables( list )
 A wrapper script that adds
 multiple customizable construction variables
-to an Options object.
+to a Variables object.
 .I list
 is a list of tuple or list objects
 that contain the arguments
 method.
 
 .ES
-opt.AddOptions(
+opt.AddVariables(
        ('debug', '', 0),
        ('CC', 'The C compiler'),
        ('VALIDATE', 'An option for testing validation',
 with the customized construction variables.
 Any specified variables that are
 .I not
-configured for the Options object
+configured for the Variables object
 will be saved and may be
 retrieved with the
-.BR UnknownOptions ()
+.BR UnknownVariables ()
 method, below.
 
 Normally this method is not called directly,
-but is called indirectly by passing the Options object to
+but is called indirectly by passing the Variables object to
 the Environment() function:
 
 .ES
-env = Environment(options=opts)
+env = Environment(variables=vars)
 .EE
 
 .IP
 The text file(s) that were specified
-when the Options object was created
+when the Variables 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.
 .EE
 
 .TP
-.RI UnknownOptions( )
+.RI UnknownVariables( )
 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
+with which the Variables object was initialized,
+but for which the Variables object was
 not configured.
 
 .ES
-env = Environment(options=opts)
-for key, value in opts.UnknownOptions():
+env = Environment(variables=vars)
+for key, value in vars.UnknownVariables():
     print "unknown variable:  %s=%s" % (key, value)
 .EE
 
 .TP
 .RI Save( filename ", " env )
-This saves the currently set options into a script file named  
+This saves the currently set variables into a script file named  
 .I filename
 that can be used on the next invocation to automatically load the current
-settings.  This method combined with the Options method can be used to
-support caching of options between runs.
+settings.  This method combined with the Variables method can be used to
+support caching of variables between runs.
 
 .ES
 env = Environment()
-opts = Options(['options.cache', 'custom.py'])
-opts.Add(...)
-opts.Update(env)
-opts.Save('options.cache', env)
+vars = Variables(['variables.cache', 'custom.py'])
+vars.Add(...)
+vars.Update(env)
+vars.Save('variables.cache', env)
 .EE
 
 .TP
 function).
 
 .ES
-Help(opts.GenerateHelpText(env))
-Help(opts.GenerateHelpText(env, sort=cmp))
-.EE
-
-.TP
-.RI FormatOptionHelpText( env ", " opt ", " help ", " default ", " actual )
+Help(vars.GenerateHelpText(env))
+Help(vars.GenerateHelpText(env, sort=cmp))
+.EE
+
+.TP
+.RI FormatVariableHelpText( env ", " opt ", " help ", " default ", " actual )
 This method returns a formatted string
 containing the printable help text
 for one option.
 def my_format(env, opt, help, default, actual):
     fmt = "\n%s: default=%s actual=%s (%s)\n"
     return fmt % (opt, default. actual, help)
-opts.FormatOptionHelpText = my_format
-.EE
-
-To make it more convenient to work with customizable Options,
+vars.FormatVariableHelpText = my_format
+.EE
+
+To make it more convenient to work with customizable Variables,
 .B scons
 provides a number of functions
 that make it easy to set up
-various types of Options:
-
-.TP
-.RI BoolOption( key ", " help ", " default )
+various types of Variables:
+
+.TP
+.RI BoolVariable( key ", " help ", " default )
 Return a tuple of arguments
 to set up a Boolean option.
 The option will use
 as false.
 
 .TP
-.RI EnumOption( key ", " help ", " default ", " allowed_values ", [" map ", " ignorecase ])
+.RI EnumVariable( key ", " help ", " default ", " allowed_values ", [" map ", " ignorecase ])
 Return a tuple of arguments
 to set up an option
 whose value may be one
 converted to lower case.
 
 .TP
-.RI ListOption( key ", " help ", " default ", " names ", [", map ])
+.RI ListVariable( key ", " help ", " default ", " names ", [", map ])
 Return a tuple of arguments
 to set up an option
 whose value may be one or more
 list.
 
 .TP
-.RI PackageOption( key ", " help ", " default )
+.RI PackageVariable( key ", " help ", " default )
 Return a tuple of arguments
 to set up an option
 whose value is a path name
 to disable use of the specified option.
 
 .TP
-.RI PathOption( key ", " help ", " default ", [" validator ])
+.RI PathVariable( key ", " help ", " default ", [" validator ])
 Return a tuple of arguments
 to set up an option
 whose value is expected to be a path name.
 is acceptable.
 SCons supplies the
 following ready-made validators:
-.BR PathOption.PathExists
+.BR PathVariable.PathExists
 (the default),
 which verifies that the specified path exists;
-.BR PathOption.PathIsFile ,
+.BR PathVariable.PathIsFile ,
 which verifies that the specified path is an existing file;
-.BR PathOption.PathIsDir ,
+.BR PathVariable.PathIsDir ,
 which verifies that the specified path is an existing directory;
-.BR PathOption.PathIsDirCreate ,
+.BR PathVariable.PathIsDirCreate ,
 which verifies that the specified path is a directory
 and will create the specified directory if the path does not exist;
 and
-.BR PathOption.PathAccept ,
+.BR PathVariable.PathAccept ,
 which simply accepts the specific path name argument without validation,
 and which is suitable if you want your users
 to be able to specify a directory path that will be
 function,
 which must take three arguments
 .RI ( key ,
-the name of the options variable to be set;
+the name of the variable to be set;
 .IR val ,
 the specified value being checked;
 and
 .RE
 These functions make it
 convenient to create a number
-of options with consistent behavior
+of variables with consistent behavior
 in a single call to the
-.B AddOptions
+.B AddVariables
 method:
 
 .ES
-opts.AddOptions(
-    BoolOption('warnings', 'compilation with -Wall and similiar', 1),
-    EnumOption('debug', 'debug output and symbols', 'no'
+vars.AddVariables(
+    BoolVariable('warnings', 'compilation with -Wall and similiar', 1),
+    EnumVariable('debug', 'debug output and symbols', 'no'
                allowed_values=('yes', 'no', 'full'),
                map={}, ignorecase=0),  # case sensitive
-    ListOption('shared',
+    ListVariable('shared',
                'libraries to build as shared libraries',
                'all',
                names = list_of_libs),
-    PackageOption('x11',
+    PackageVariable('x11',
                   'use X11 installed here (yes = search some places)',
                   'yes'),
-    PathOption('qtdir', 'where the root of Qt is installed', qtdir),
-    PathOption('foopath', 'where the foo library is installed', foopath,
-               PathOption.PathIsDir),
+    PathVariable('qtdir', 'where the root of Qt is installed', qtdir),
+    PathVariable('foopath', 'where the foo library is installed', foopath,
+               PathVariable.PathIsDir),
 
 )
 .EE
 line or in the file custom.py. 
 
 .ES
-opts = Options('custom.py')
-opts.Add('CC', 'The C compiler.')
-env = Environment(options=opts)
-Help(opts.GenerateHelpText(env))
+vars = Variables('custom.py')
+vars.Add('CC', 'The C compiler.')
+env = Environment(variables=vars)
+Help(vars.GenerateHelpText(env))
 .EE
 
 The user could specify the C compiler on the command line:
 <!ENTITY AddPostAction "<function>AddPostAction</function>">
 <!ENTITY AddPreAction "<function>AddPreAction</function>">
 <!ENTITY AddOptions "<function>AddOptions</function>">
+<!ENTITY AddVariables "<function>AddVariables</function>">
 <!ENTITY Alias "<function>Alias</function>">
 <!ENTITY Aliases "<function>Aliases</function>">
 <!ENTITY AlwaysBuild "<function>AlwaysBuild</function>">
 <!ENTITY AppendENVPath "<function>AppendENVPath</function>">
 <!ENTITY AppendUnique "<function>AppendUnique</function>">
 <!ENTITY BoolOption "<function>BoolOption</function>">
+<!ENTITY BoolVariable "<function>BoolVariable</function>">
 <!ENTITY Build "<function>Build</function>">
 <!ENTITY CacheDir "<function>CacheDir</function>">
 <!ENTITY Chmod "<function>Chmod</function>">
 <!ENTITY Dump "<function>Dump</function>">
 <!ENTITY Entry "<function>Entry</function>">
 <!ENTITY EnumOption "<function>EnumOption</function>">
+<!ENTITY EnumVariable "<function>EnumVariable</function>">
 <!ENTITY Environment "<function>Environment</function>">
 <!ENTITY Execute "<function>Execute</function>">
 <!ENTITY Export "<function>Export</function>">
 <!ENTITY InstallAs "<function>InstallAs</function>">
 <!ENTITY Link "<function>Link</function>">
 <!ENTITY ListOption "<function>ListOption</function>">
+<!ENTITY ListVariable "<function>ListVariable</function>">
 <!ENTITY Local "<function>Local</function>">
 <!ENTITY Mkdir "<function>Mkdir</function>">
 <!ENTITY Module "<function>Module</function>">
 <!ENTITY NoCache "<function>NoCache</function>">
 <!ENTITY Objects "<function>Objects</function>">
 <!ENTITY Options "<function>Options</function>">
+<!ENTITY Variables "<function>Variables</function>">
 <!ENTITY PackageOption "<function>PackageOption</function>">
+<!ENTITY PackageVariable "<function>PackageVariable</function>">
 <!ENTITY ParseConfig "<function>ParseConfig</function>">
 <!ENTITY PathOption "<function>PathOption</function>">
 <!ENTITY PathOption_PathAccept "<function>PathOption.PathAccept</function>">
 <!ENTITY PathOption_PathIsDir "<function>PathOption.PathIsDir</function>">
 <!ENTITY PathOption_PathIsDirCreate "<function>PathOption.PathIsDirCreate</function>">
 <!ENTITY PathOption_PathIsFile "<function>PathOption.PathIsFile</function>">
+<!ENTITY PathVariable "<function>PathVariable</function>">
+<!ENTITY PathVariable_PathAccept "<function>PathVariable.PathAccept</function>">
+<!ENTITY PathVariable_PathExists "<function>PathVariable.PathExists</function>">
+<!ENTITY PathVariable_PathIsDir "<function>PathVariable.PathIsDir</function>">
+<!ENTITY PathVariable_PathIsDirCreate "<function>PathVariable.PathIsDirCreate</function>">
+<!ENTITY PathVariable_PathIsFile "<function>PathVariable.PathIsFile</function>">
 <!ENTITY Precious "<function>Precious</function>">
 <!ENTITY Prepend "<function>Prepend</function>">
 <!ENTITY PrependENVPath "<function>PrependENVPath</function>">

doc/user/MANIFEST

 actions.xml
+add-method.xml
 alias.xml
 ant.xml
 builders.xml
+# __COPYRIGHT__
+
+When adding a new file, add it to main.xml and MANIFEST.
+
+To build the .xml files from the .in files:
+  scons -D . BUILDDOC=1
+
+Writing examples: here's a simple template.
+
+ <scons_example name="Foo">
+   <file name="SConstruct">
+    env = Environment()
+    print env.Dump("CC")
+   </file>
+ </scons_example>
+
+ <scons_output example="Foo">
+    <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>

doc/user/add-method.in

+<!--
+
+  __COPYRIGHT__
+
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+  KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+  <para>
+
+  The env.AddMethod(function, [name]) function is used to add a method
+  to an environment.  It's typically used to add a "pseudo-builder" or
+  wrap up a call to multiple builders.  In the first example, we want
+  to install the program into the standard bin dir, but also copy it
+  into a local install/bin dir that might be used to build a package
+  from.
+
+  </para>
+
+  <scons_example name="ex1">
+     <file name="SConstruct" printme="1">
+     def install_in_bin_dirs(env, source):
+         """Install source in both bin dirs"""
+         i1 = env.Install("$BIN", source)
+         i2 = env.Install("$LOCALBIN", source)
+         return [i1[0], i2][0] # Return a list, like a normal builder
+     env = Environment(BIN='/usr/bin', LOCALBIN='#install/bin')
+     env.AddMethod(install_in_bin_dirs, "InstallInBinDirs")
+     env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs     
+     </file>
+     <file name="hello.c">
+     int main() { printf("Hello, world!\n"); }
+     </file>
+  </scons_example>
+
+  <para>
+  This produces the following:
+  </para>
+
+  <scons_output example="ex1">
+    <scons_output_command>scons -Q</scons_output_command>
+  </scons_output>
+
+  <para>
+
+  It also gives more flexibility in parsing arguments than you can get
+  with a builder.  The next example shows a pseudo-builder with a
+  named argument that modifies the filename, and a separate argument
+  for the resource file (rather than having the builder figure it out
+  by file extension).  Also this example demonstrates using the global
+  AddMethod function to add a method to the global Environment class,
+  so it will be used in all subsequently created environments.
+
+  </para>
+
+  <scons_example name="ex2">
+     <file name="SConstruct" printme="1">
+     import sys;
+     def BuildTestProg(env, testfile, resourcefile, testdir="tests"):
+         """Build the test program;
+         prepends "test_" to src and target, and puts target into testdir."""
+         srcfile="test_%s.c"%testfile
+         if sys.platform=='win32':
+             target="%s/test_%s$EXESUFFIX"%(testdir,[testfile, resourcefile])
+         else:
+             target="%s/test_%s$EXESUFFIX"%(testdir,testfile)
+         p = env.Program(target, srcfile)
+         return p
+     AddMethod(Environment, BuildTestProg)
+
+     # Now use it
+     env=Environment()
+     env.BuildTestProg('stuff', resourcefile='res.rc')
+     </file>
+     <file name="test_stuff.c">
+     int main() { printf("Hello, world!\n"); }
+     </file>
+  </scons_example>
+
+  <para>
+  This produces the following (on Linux, anyway; Windows would include the
+  resource file):
+  </para>
+
+  <scons_output example="ex2">
+    <scons_output_command>scons -Q</scons_output_command>
+  </scons_output>
+

doc/user/add-method.xml

+<!--
+
+  __COPYRIGHT__
+
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+  KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+  <para>
+
+  The env.AddMethod(function, [name]) function is used to add a method
+  to an environment.  It's typically used to add a "pseudo-builder" or
+  wrap up a call to multiple builders.  In the first example, we want
+  to install the program into the standard bin dir, but also copy it
+  into a local install/bin dir that might be used to build a package
+  from.
+
+  </para>
+
+  <programlisting>
+     def install_in_bin_dirs(env, source):
+         """Install source in both bin dirs"""
+         i1 = env.Install("$BIN", source)
+         i2 = env.Install("$LOCALBIN", source)
+         return [i1[0], i2][0] # Return a list, like a normal builder
+     env = Environment(BIN='/usr/bin', LOCALBIN='#install/bin')
+     env.AddMethod(install_in_bin_dirs, "InstallInBinDirs")
+     env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs     
+  </programlisting>
+
+  <para>
+  This produces the following:
+  </para>
+
+  <screen>
+    % <userinput>scons -Q</userinput>
+    cc -o hello.o -c hello.c
+    cc -o hello hello.o
+    Install file: "hello" as "install/bin/hello"
+  </screen>
+
+  <para>
+
+  It also gives more flexibility in parsing arguments than you can get
+  with a builder.  The next example shows a pseudo-builder with a
+  named argument that modifies the filename, and a separate argument
+  for the resource file (rather than having the builder figure it out
+  by file extension).  Also this example demonstrates using the global
+  AddMethod function to add a method to the global Environment class,
+  so it will be used in all subsequently created environments.
+
+  </para>
+
+  <programlisting>
+     import sys
+     def BuildTestProg(env, testfile, resourcefile, testdir="tests"):
+         """Build the test program;
+         prepends "test_" to src and target, and puts target into testdir."""
+         srcfile="test_%s.c"%testfile
+         if sys.platform=='win32':
+             target="%s/test_%s$EXESUFFIX"%(testdir,[testfile, resourcefile])
+         else:
+             target="%s/test_%s$EXESUFFIX"%(testdir,testfile)
+         p = env.Program(target, srcfile)
+         return p
+     AddMethod(Environment, BuildTestProg)
+
+     # Now use it
+     env=Environment()
+     env.BuildTestProg('stuff', resourcefile='res.rc')
+  </programlisting>
+
+  <para>
+  This produces the following (on Linux, anyway; Windows would include the
+  resource file):
+  </para>
+
+  <screen>
+    % <userinput>scons -Q</userinput>
+    cc -o test_stuff.o -c test_stuff.c
+    cc -o tests/test_stuff test_stuff.o
+  </screen>
+
     <!ENTITY builders-built-in SYSTEM "builders-built-in.xml">
     <!ENTITY builders-commands SYSTEM "builders-commands.xml">
     <!ENTITY builders-writing SYSTEM "builders-writing.xml">
+    <!ENTITY add-method SYSTEM "add-method.xml">
     <!ENTITY caching SYSTEM "caching.xml">
     <!ENTITY command-line SYSTEM "command-line.xml">
     <!ENTITY copyright SYSTEM "copyright.xml">
 
   XXX Progress()
 
-  XXX AddMethod()
-
   XXX - - diskcheck=
 
   XXX site_scons
     &builders-commands;
   </chapter>
 
+  <chapter id="chap-add-method">
+    <title>Pseudo-Builders:  the AddMethod function</title>
+    &add-method;
+  </chapter>
+
   <!--
 
   XXX Action()

doc/user/main.xml

     <!ENTITY builders-built-in SYSTEM "builders-built-in.xml">
     <!ENTITY builders-commands SYSTEM "builders-commands.xml">
     <!ENTITY builders-writing SYSTEM "builders-writing.xml">
+    <!ENTITY add-method SYSTEM "add-method.xml">
     <!ENTITY caching SYSTEM "caching.xml">
     <!ENTITY command-line SYSTEM "command-line.xml">
     <!ENTITY copyright SYSTEM "copyright.xml">
 
   XXX Progress()
 
-  XXX AddMethod()
-
   XXX - - diskcheck=
 
   XXX site_scons
     &builders-commands;
   </chapter>
 
+  <chapter id="chap-add-method">
+    <title>Pseudo-Builders:  the AddMethod function</title>
+    &add-method;
+  </chapter>
+
   <!--
 
   XXX Action()
 
 
 
+RELEASE X.XX - XXX
+
+  From Benoit Belley:
+
+  - Speed up the SCons.Util.to_string*() functions.
+
+  - Optimize various Node intialization and calculations.
+
+  - Optimize Executor scanning code.
+
+  - Optimize Taskmaster execution, including dependency-cycle checking.
+
+  - Fix the --debug=stree option so it prints its tree once, not twice.
+
+  From Johan Boul�:
+
+  - Fix the ability to use LoadableModule() under MinGW.
+
+  From Steven Knight:
+
+  - Make the -d, -e, -w and --no-print-directory options "Ignored for
+    compatibility."  (We're not going to implement them.)
+
+  - Fix a serious inefficiency in how SCons checks for whether any source
+    files are missing when a Builder call creates many targets from many
+    input source files.
+
+  - In Java projects, make the target .class files depend only on the
+    specific source .java files where the individual classes are defined.
+
+  - Don't store duplicate source file entries  in the .sconsign file so
+    we don't endlessly rebuild the target(s) for no reason.
+
+  - Add a Variables object as the first step towards deprecating the
+    Options object name.  Similarly, add BoolVariable(), EnumVariable(),
+    ListVariable(), PackageVariable() and PathVariable() functions
+    as first steps towards replacing BoolOption(), EnumOption(),
+    ListOption(), PackageOption() and PathOption().
+
+  - Change the options= keyword argument to the Environment() function
+    to variables=, to avoid confusion with SCons command-line options.
+    Continue supporting the options= keyword for backwards compatibility.
+
+  - When $SWIGFLAGS contains the -python flag, expect the generated .py
+    file to be in the same (sub)directory as the target.
+
+  - When compiling C++ files, allow $CCFLAGS settings to show up on the
+    command line even when $CXXFLAGS has been redefined.
+
+  - Fix --interactive with -u/-U/-D when a VariantDir() is used.
+
+  From Anatoly Techtonik:
+
+  - Have the scons.bat file add the script execution directory to its
+    local %PATH% on Windows, so the Python executable can be found.
+
+  From Mike Wake:
+
+  - Fix passing variable names as a list to the Return() function.
+
+  From Matthew Wesley:
+
+  - Add support for the GDC 'D' language compiler.
+
+
+
 RELEASE 0.98 - Sun, 30 Mar 2008 23:33:05 -0700
 
   From Benoit Belley:
 
 
 
-RELEASE 0.98 - Sun, 30 Mar 2008 23:33:05 -0700
+RELEASE 0.98.1 - XXX
 
-  This is the ninth beta release of SCons.  Please consult the
-  CHANGES.txt file for a list of specific changes since last release.
+  This is an update to the ninth beta release of SCons.  Please consult
+  the CHANGES.txt file for a list of specific changes since last release.
+
+  Please note the following important changes since release 0.98:
+
+    --  SCONS NO LONGER SETS THE GNU TOOLCHAIN -fPIC FLAG IN $SHCXXFLAGS
+
+        The GNU toolchain support in previous versions of SCons would
+        add the -fPIC flag to the $SHCXXFLAGS construction variable.
+        The -fPIC flag has been now been removed from the default
+        $SHCXXFLAGS setting.  Instead, the $SHCXXCOM construction variable
+        (the default SCons command line for compiling shared objects
+        from C++ source files) has been changed to add the $SHCCFLAGS
+        variable, which contains the -fPIC flag.
+
+        This change was made in order to make the behavior of the default
+        C++ compilation line including $SHCCFLAGS consistent with the
+        default C compilation line including $CCFLAGS.
+
+        This change should have no impact on configurations that use
+        the default $SHCXXCOM command line.  It may have an impact on
+        configurations that were using the default $SHCXXFLAGS value
+        *without* the $SHCCFLAGS variable to get the -fPIC flag into a
+        custom command line.  You can fix these by adding the $SHCCFLAGS
+        to the custom command line.
+
+        Adding $SHCCFLAGS is backwards compatible with older SCons
+        releases, although it might cause the -fPIC flag to be repeated
+        on the command line if you execute it on an older version of
+        SCons that sets -fPIC in both the $SHCCLAFGS and $SHCXXFLAGS
+        variables.  Duplicating the -fPIC flag on the g++ command line
+        will not cause any compilation problems, but the change to the
+        command line may cause SCons to rebuild object files.
 
   Please note the following important changes since release 0.97.0d20071212:
 
         might cause a compatibility issue if a script or other utility
         looks for an exact match of the previous text.
 
-  Please note the following important changes since release 0.96.93:
+  Please note the following planned, future changes:
 
-    --  THE --debug=memoizer OPTION NOW REQUIRES PYTHON 2.2 OR LATER
+    --  THE Options OBJECT AND RELATED FUNCTIONS WILL BE DEPRECATED
 
-        The --debug=memoizer option now prints a warning message and
-        does nothing if SCons is run on a version of Python that does
-        not support metaclasses (earlier than Python 2.2).
+        The Options object is being replaced by a new Variables
+        object, which uses a new Variables.AddVariable() method
+        where the previous interface used Options.AddOptions().
 
-    --  THE --debug=nomemoizer OPTION DOES NOTHING AND IS NOW DEPRECATED
+        Similarly, the following utility functions are being replaced
+        by the following similarly-named functions:
 
-        The --debug=nomemoizer no longer does anything and instead
-        now generates a warning message about being deprecated.  The
-        --debug=nomemoizer will be removed completely in a future release.
+                BoolOption()            BoolVariable()
+                EnumOption()            EnumVariable()
+                ListOption()            ListVariable()
+                PackageOption()         PackageVariable()
+                PathOption()            PathVariable()
 
-  Please note the following important changes since release 0.96.91:
+        And also related, the options= keyword argument when creating
+        construction environments with the Environment() functions is
+        being replaced with a variables= keyword argument.
 
-    --  /opt/bin AND /sw/bin ADDED TO DEFAULT EXECUTION PATH VARIABLES
+        In some future release a deprecation warning will be added to
+        existing uses of the Options object, its methods, the above
+        utility functions, and the options= keyword argument of the
+        Environment() function.  At some point after the deprecation
+        warning is added, the Options object, related functions and
+        options= keyword argument will be removed entirely.
 
-        On all POSIX systems, the default execution PATH variable has had
-        the /opt/bin directory added after the /usr/local/bin directory
-        and before /bin and /usr/bin directories.  This may cause SCons
-        to find and/or use different compilers, linkers, etc., if you
-        have any same-named utilities installed in /opt/bin that SCons
-        previously found in /bin or /usr/bin.
+        You can prepare for this by changing all your uses of the Options
+        object and related functions to the Variables object and the new
+        function names, and changing any uses of the options= keyword
+        argument to variables=.
 
-        On Mac OS X (Darwin) systems, the /sw/bin directory has been added
-        to the end of the default execution PATH.  This may cause SCons
-        to find compilers, linkers and other utilities it previously did
-        not, although it should not otherwise change existing behavior.
+        NOTE:  CONVERTING TO USING THE NEW Variables OBJECT OR THE
+        RELATED *Variable() FUNCTIONS, OR USING THE NEW variable=
+        KEYWORD ARGUMENT, IS NOT BACKWARDS COMPATIBLE TO VERSIONS OF
+        SCons BEFORE 0.98.  YOUR SConscript FILES WILL NOT WORK ON
+        EARLIER VERSIONS OF SCons AFTER MAKING THIS CHANGE.
 
-    --  Configure.Checklib() ARGUMENTS HAVE CHANGED TO MATCH DOCUMENTATION
+        If you change SConscript files in software that you make available
+        for download or otherwise distribute, other users may try to
+        build your software with an earlier version of SCons that does
+        not have the Variables object or related *Variable() functions.
+        We recommend preparing for this in one of two ways:
 
-        The order of the arguments to the Configure.CheckLib() function
-        has changed to put the "autoadd" keyword argument last, matching
-        the documentation in the man page.  This could cause problems
-        for any calls to Configure.Checklib() that were relying on the
-        order of the arguments.  Specifying all arguments as keyword
-        arguments will work on both older and newer versions of SCons.
+            --  Make your SConscript files backwards-compatible by
+                modifying your calls with  Python try:-except: blocks
+                as follows:
 
-    --  env.subst() NO LONGER EXPANDS $TARGET, $SOURCES, etc. BY DEFAULT
+                    try:
+                        vars = Variables('custom.py', ARGUMENTS)
+                        vars.AddVariables(
+                            BoolVariable('WARNINGS', 'cmopile with -Wall', 1),
+                            EnumVariable('DEBUG', 'debug version', 'no'
+                                       allowed_values=('yes', 'no', 'full'),
+                                       map={}, ignorecase=0),
+                            ListVariable('SHAREDLIBS',
+                                         'libraries to build shared',
+                                         'all',
+                                         names = list_of_libs),
+                            PackageVariable('X11',
+                                            'use X11 from here',
+                                            '/usr/bin/X11'),
+                            PathVariable('QTDIR', 'root of Qt', qtdir),
+                        )
+                    except NameError:
+                        vars = Options('custom.py', ARGUMENTS)
+                        vars.AddOptions(
+                            BoolOption('WARNINGS', 'cmopile with -Wall', 1),
+                            EnumOption('DEBUG', 'debug version', 'no'
+                                       allowed_values=('yes', 'no', 'full'),
+                                       map={}, ignorecase=0),
+                            ListOption('SHAREDLIBS',
+                                       'libraries to build shared',
+                                       'all',
+                                       names = list_of_libs),
+                            PackageOption('X11',
+                                          'use X11 from here',
+                                          '/usr/bin/X11'),
+                            PathOption('QTDIR', 'root of Qt', qtdir),
+                        )
 
-        Calls to the env.subst() method to interpolate construction
-        variables in strings no longer automatically expand the special
-        variables $TARGET, $TARGETS, $SOURCE and $SOURCES.  The keyword
-        variables "target" and "source" must now be set to the lists
-        of target and source files to be used in expansion of those
-        variables, when desired.
+                Additionally, you can check for availability of the new
+                variables= keyword argument as follows:
 
-        This is most likely necessary for any env.subst() calls within
-        a Python function being used as an SCons action for a Builder:
+                    try:
+                        env = Environment(variables=vars)
+                    except TypeError:
+                        env = Environment(options=vars)
 
-            def build_it(env, target, source):
-                env.subst('$STRING', target=targets, source=sources)
-            MyBuilder = Builder(action=build_it)
+                (Note that we plan to maintain the existing Options object
+                name for some time, to ensure backwards compatibility,
+                so in practice it may be easier to just continue to use
+                the old name until you're reasonably sure you won't have
+                people trying to build your software with versions of
+                SCons earlier than 0.98.1.)
 
-        The "target" and "source" keyword arguments are backwards
-        compatible and can be added to SConscript files without breaking
-        builds on systems using older SCons releases.
+            --  Use the EnsureSConsVersion() function to provide a
+                descriptive error message if your SConscript files
+                are executed by an earlier version of SCons:
 
-    --  INTERNAL FUNCTIONS AND CLASSES HAVE MOVED FROM SCons.Util
-
-        All internal functions and classes related to string substitution
-        have been moved out of the SCons.Util module into their own
-        SCons.Subst module.  The following classes have been moved:
-
-                Literal
-                SpecialAttrWrapper
-                NLWrapper
-                Targets_or_Sources
-                Target_or_Source
-
-        And the following functions have moved:
-
-                quote_spaces()
-                escape_list()
-                subst_dict()
-                scons_subst()
-                scons_subst_list()
-                scons_subst_once()
-
-        If your SConscript files have been using any of these function
-        directly from the SCons.Util module (which they ultimately should
-        not be!), you will need to modify them.
-
-  Please note the following important changes since release 0.96.90:
-
-    --  SIGNATURES ARE NOW STORED IN AN SConsignFile() BY DEFAULT,
-        CAUSING LIKELY REBUILDS; SPECIAL NOTE CONCERNING INTERACTION
-        WITH REPOSITORIES
-
-        The default behavior has been changed to store signature
-        information in a single .sconsign.dblite file in the top-level
-        SConstruct file.  This will cause rebuilds on upgrade to 0.97,
-        unless you were already calling the SConsignFile() function in
-        your SConscript files.
-
-        The previous default behavior was to store signature information
-        in a .sconsign file in each directory that contained target
-        files that SCons knew about.  The old behavior may be preserved
-        by specifying:
-
-              SConsignFile(None)
-
-        in any SConscript file.
-
-        If you are using the Repository feature, and are not already
-        using the SConsignFile() function in your build, you *must*
-        add "SConsignFile(None)" to your build configuration to keep
-        interoperating with an existing Repository that uses the old
-        behavior of a .sconsign file in each directory.  Alternatively,
-        you can rebuild the Repository with the new default behavior.
-
-    --  OTHER SIGNATURE CHANGES WILL CAUSE LIKELY REBUILDS AFTER UPGRADE
-
-        This release adds several changes to the signature mechanism that
-        will cause SCons to rebuild most configurations after upgrading
-        (and when switching back to an earlier release from 0.97).
-        These changes are:
-
-          --  NORMALIZED PATHS IN SConsignFile() DATABASES ON WINDOWS
-
-              When using an SConsignFile() database, instead of
-              individual .sconsign files in each directory, the path
-              names are stored in normalized form with / (forward slash)
-              separating the elements.  This may cause rebuilds when
-              upgrading to SCons 0.97 on Windows systems with hierarchical
-              build configurations.
-
-          --  STORED DEPENDENCY PATHS ARE NOW RELATIVE TO THE TARGET
-
-              SCons used to store the paths of all source files and
-              dependencies relative to the top-level SConstruct directory.
-              It now stores them relative to the directory of the
-              associated target file.  This makes it possible to use
-              content signatures to subdivide a dependency tree without
-              causing unnecessary rebuilds due to an intermediate file in
-              one build being treated as a source file in a nother build.
-
-              This is a step towards making it possible to write a
-              hierarchy of SConstruct files that allow developers
-              to build just one portion of a tree wherever there's an
-              SConstruct file.  (Note that this would still require some
-              specific code at the top of each SConstruct file, but we
-              hope to make this an easier/more naturally supported thing
-              in the future.)
-
-          --  PYTHON FUNCTION ACTION SIGNATURES HAVE CHANGED TO AVOID
-              FUTURE REBUILDS AND REBUILDS BETWEEN PYTHON VERSIONS
-
-              SCons Actions for Python functions use the function's
-              byte code to generate their signature.  The byte code
-              in older versions of Python includes indications of the
-              line numbers at which the function's code appeared in
-              its original source file, which means that changes in the
-              location of an otherwise unmodified Python function would
-              trigger rebuilds.  The line number byte codes are now
-              removed from the signature, which will cause any targets
-              built by Python function Actions (including various
-              pre-supplied SCons Actions) to be rebuilt.
-
-          --  REMOVED CONVERSION FROM PRE-0.96 .sconsign FORMATS
-
-              Because this release involves so many other signature
-              changes that cause rebuilds, the support for automatically
-              converting signature information from .sconsign files
-              written by SCons versions prior to 0.96 has been removed.
-
-          --  ORDER OF -o FLAGS ON CERTAIN LINK COMMAND LINES HAS CHANGED
-
-              The -o flag that specifies an output file has been moved
-              on certain linker command lines to place it consistently
-              right after the link command itself.  This will cause
-              recompilation of target files created by these changed
-              lines.
-
-    --  F95 AND F90 COMPILERS ARE NOW PREFERRED OVER F77
-
-        SCons now searches for Fortran 95 and Fortran 90 compilers first
-        in preference to Fortran 77.  This may result in a different
-        Fortran compiler being used by default, although as Fortran 95 and
-        Fortran 90 are backwards compatible with Fortran 77, this should
-        not cause problems for standards-compliant Fortran programs.
-        On systems that have multiple versions of Fortran installed,
-        the Fortran 77 compiler may be explicitly selected by specifying
-        it when creating the construction environment:
-
-            env = Environment(tools = ['default', 'f77'])
-
-    --  SOLARIS DEFAULT SHARED OBJECT PREFIXES AND SUFFIXES HAVE CHANGED
-
-        On Solaris, SCons now builds shared objects from C and C++ source
-        files with a default prefix of "so_" and a default suffix of ".o".
-        The previous default suffix of ".os" caused problems when trying
-        to use SCons with Sun WorkShop.
-
-    --  CACHED Configure() RESULTS ARE STORED IN A DIFFERENT FILE
-
-        The Configure() subsystem now stores its cached results in a
-        different file.  This may cause configuration tests to be re-run
-        the first time after you install 0.97.
-
-    --  setup.py INSTALLS VERSION-NUMBERED SCRIPTS AND DIRS BY DEFAULT
-
-        The setup.py script has been changed to always install SCons in
-        a version-numbered directory (e.g. /usr/local/lib/scons-0.97
-        or D:\Python23\scons-0.97) and with a version-numbered script
-        name (scons-0.97) in addition to the usual installation of an
-        "scons" script name.  A number of new setup.py options allow
-        control over what does or does not get installed, and where.
-        See the README.txt or README files for additional information.
-
-    --  setup.py NOW INSTALLS MAN PAGES ON UNIX AND Linux SYSTEMS
-
-        The SCons setup.py script now installs the "scons.1" and
-        "sconsign.1" man pages on UNIX and Linux systems.  A
-        new --no-install-man
-
-    --  BUILDERS RETURN A LIST-LIKE OBJECT, NOT A REGULAR LIST
-
-        Builder calls now return an object that behaves like a list
-        (and which provides some other functionality), not an underlying
-        Python list.  In general, this should not cause any problems,
-        although it introduces a subtle change in the following behavior:
-
-                obj += env.Object('foo.c')
-
-        If "obj" is a regular Python list, Python will no longer update
-        the "obj" in place, because the return value from env.Object()
-        is no longer the same type.  Python will instead allocate a
-        new object and assign the local variable "obj" to it.  If "obj"
-        is defined in an SConscript file that calls another SConscript
-        file containing the above code, "obj" in the first SConscript
-        file will not contain the object file nodes created by the
-        env.Object() call.
-
-        You can guarantee that a list will be updated in place regardless
-        of which SConscript file defines it and which adds to it by
-        using the list extend() method as follows:
-
-                obj.extend(env.Object('foo.c'))
-
-  Please note the following important changes since release 0.96.1:
-
-    --  DIRECTORY TREES ARE NO LONGER AUTOMATICALLY SCANNED FOR CHANGES
-
-        Custom builders and Command() calls that accept directories as
-        source arguments no longer scan entire on-disk directory trees by
-        default.  This means that their targets will not be automatically
-        rebuilt if a file changes on disk *unless* SCons already knows
-        about the file from a specific Builder or File() call.  Note that
-        the targets will still be rebuilt correctly if a file changes
-        that SCons already knows about due to a Builder or other call.
-
-        The existing behavior of scanning on-disk directory trees for
-        any changed file can be maintained by passing the new DirScanner
-        global directory scanner as the source_scanner keyword argument
-        to the Builder call:
-
-            bld = Builder("build < $SOURCE > $TARGET",
-                          source_scanner = DirScanner)
-
-        The same keyword argument can also be supplied to any Command()
-        calls that need to scan directory trees on-disk for changed files:
-
-            env.Command("archive.out", "directory",
-                        "archiver -o $TARGET $SOURCE",
-                        source_scanner = DirScanner)
-
-        This change was made because scanning directories by default
-        could cause huge slowdowns if a configurable directory like /usr
-        or /usr/local was passed as the source to a Builder or Command()
-        call, in which case SCons would scan the entire directory tree.
-
-    --  ParseConfig() METHOD ADDS LIBRARY FILE NAMES TO THE $LIBS VARIABLE
-
-        The ParseConfig() method now adds library file names returned
-        by the specified *-config command to the $LIBS construction
-        variable, instead of returning them (the same way it handles
-        the -l option).
-
-    --  ParseConfig() METHOD DOESN'T ADD DUPLICATES TO CONSTRUCTION VARIABLES
-
-        By default, the ParseConfig() method now avoids adding duplicate
-        entries to construction variables.  The old behavior may be
-        specified using a new "unique=0" keyword argument.
-
-    --  WINDOWS %TEMP% and %TMP% VARIABLES ARE PROPAGATED AUTOMATICALLY
-
-        The %TEMP% and %TMP% external environment variables are now
-        propagated automatically to the command execution environment on
-        Windows systems.
-
-    --  OUTPUT OF Configure() SUBSYSTEM CHANGED SLIGHTLY
-
-        The Configure() subsystem now reports tests results as "yes" and
-        "no" instead of "ok" and "failed."  This might interfere with any
-        scripts that automatically parse the Configure() output from SCons.
-
-    --  VISUAL STUDIO ATL AND MFC DIRECTORIES NOT ADDED BY DEFAULT
-
-        When compiling with Microsoft Visual Studio, SCons no longer
-        adds the ATL and MFC directories to the INCLUDE and LIB
-        environment variables by default.  If you want these directories
-        included in your environment variables, you should now set the
-        $MSVS_USE_MFC_DIRS *construction* variable when initializing
-        your environment:
-
-            env = Environment(MSVS_USE_MFC_DIRS = 1)
-
-    --  DEPRECATED GLOBAL FUNCTIONS HAVE BEEN REMOVED
-
-        The following deprecated global functions have been removed:
-        ParseConfig(), SetBuildSignatureType(), SetContentSignatureType(),
-        SetJobs() and GetJobs().
-
-    --  DEPRECATED "validater" KEYWORD HAS BEEN REMOVED
-
-        The deprecated "validater" keyword to the Options.Add() method
-        has been removed.
-
-  Please note the following important changes since release 0.95:
-
-    --  BUILDERS NOW ALWAYS RETURN A LIST OF TARGETS
-
-        All Builder calls (both built-in like Program(), Library(),
-        etc. and customer Builders) now always return a list of target
-        Nodes.   If the Builder only builds one target, the Builder
-        call will now return a list containing that target Node, not
-        the target Node itself as it used to do.
-
-        This change should be invisibile to most normal uses of the
-        return values from Builder calls.  It will cause an error if the
-        SConscript file was performing some direct manipulation of the
-        returned Node value.  For example, an attempt to print the name
-        of a target returned by the Object() Builder:
-
-              target = Object('foo.c')
-              # OLD WAY
-              print target
-
-        Will now need to access the first element in the list returned by
-        the Object() call:
-
-              target = Object('foo.c')
-              # NEW WAY
-              print target[0]
-
-        This change was introduced to make the data type returned by Builder
-        calls consistent (always a list), regardless of platform or number
-        of returned targets.
-
-    --  DEFAULT SConsignFile() DATABASE SCHEME HAS CHANGED
-
-        The SConsignFile() function now uses an internally-supplied
-        SCons.dblite module as the default DB scheme for the .sconsign file.
-        If you are using the SConsignFile() function without an explicitly
-        specified dbm_module argument, this will cause all of your targets
-        to be recompiled the first time you use SCons 0.96.  To preserve the
-        previous behavior, specify the "anydbm" module explicitly:
-
-            import anydbm
-            SConsignFile('.sconsign_file_name', anydbm)
-
-    --  INTERNAL .sconsign FILE FORMAT HAS CHANGED
-
-        The internal format of .sconsign files has been changed.  This might
-        cause warnings about "ignoring corrupt .sconsign files" and rebuilds
-        when you use SCons 0.96 for the first time in a tree that was
-        previously built with SCons 0.95 or earlier.
-
-    --  INTERFACE CHANGE OF scan_check FUNCTION TO CUSTOM SCANNERS
-
-        The scan_check function that can be supplied to a custom Scanner now
-        must take two arguments, the Node to be checked and a construction
-        environment.  It previously only used the Node as an argument.
-
-    --  DEFAULT SCANNERS NO LONGER HEED INTERNAL Scanner.add_skey() METHOD
-
-        The internal Scanner.add_skey() method no longer works for the
-        default scanners, which now use construction variables to hold their
-        lists of suffixes.  If you had a custom Tool specification that was
-        reaching into the internals in this way to add a suffix to one of
-        the following scanner, you must now add the suffix to a construction
-        environment through which you plan to call the scanner, as follows:
-
-            CScan.add_skey('.x')       => env.Append(CPPSUFFIXES = ['.x'])
-            DScan.add_skey('.x')       => env.Append(DSUFFIXES = ['.x'])
-            FortranScan.add_skey('.x') => env.Append(FORTRANSUFFIXES = ['.x'])
-
-    --  KEYWORD ARGUMENTS TO Builder() HAVE BEEN REMOVED
-
-        The "node_factory" and "scanner" keyword arguments to the Builder()
-        function have been removed.  In their place, the separate and more
-        flexible "target_factory," "source_factory," "target_scanner" and
-        "source scanner" keywords should be used instead.
-
-    --  ALL-DIGIT FILE "EXTENSIONS" ARE NOW PART OF THE FILE BASENAME
-
-        SCons now treats file "extensions" that contain all digits (for
-        example, "file.123") as part of the file basename, for easier
-        handling of version numbers in the names of shared libraries
-        and other files.  Builders will now add their file extensions to
-        file names specified with all-digit extensions.  If you need to
-        generate a file with an all-digit extension using a Builder that
-        adds a file extension, you can preserve the previous behavior by
-        wrapping the file name in a File() call.
-
-    --  Append()/Prepend() METHODS CHANGED WHEN USING UserList OBJECTS
-
-        The behavior of the env.Append() and env.Prepend() methods has
-        changed when appending a string value to a UserList, or vice versa.
-        They now behave like normal Python addition of a string to
-        a UserList.  Given an initialization and an env.Append() call like:
-
-            env = Environment(VAR1=UserList(['foo']), VAR2='foo')
-            env.Append(VAR1='bar', VAR2=UserList(['bar'])
-
-        The resulting values of $VAR1 and $VAR2 will now be ['foo', 'b',
-        'a', 'r'] and ['f', 'o', 'o', 'bar'], respectively.  This is because
-        Python UserList objects treat strings as sequences of letters when
-        adding them to the value of the UserList.
-
-        The old behavior of yielding $VAR1 and $VAR2 values of ['foo',
-        'bar'] when either variable is a UserList object now requires that
-        the string variables be enclosed in a list:
-
-            env = Environment(VAR1=UserList(['foo']), VAR2=['foo'])
-            env.Append(VAR1='bar', VAR2=UserList(['bar']))
-
-        Note that the SCons behavior when appending to normal lists has
-        *not* changed, and the behavior of all of the default values that
-        SCons uses to initialize all construction variables has *not*
-        changed.  This change *only* affects any cases where you explicitly
-        use UserList objects to initialize or append to a variable.
-
-  Please note the following planned, future changes:
+                    EnsureSConsVersion(0, 98, 1)
 
     --  THE BuildDir() METHOD AND FUNCTION WILL BE DEPRECATED
 

src/engine/MANIFEST.in

 SCons/Builder.py
 SCons/compat/__init__.py
 SCons/compat/_scons_hashlib.py
+SCons/compat/_scons_itertools.py
 SCons/compat/_scons_optparse.py
 SCons/compat/_scons_sets.py
 SCons/compat/_scons_sets15.py
 SCons/Node/Alias.py
 SCons/Node/FS.py
 SCons/Node/Python.py
-SCons/Options/__init__.py
-SCons/Options/BoolOption.py
-SCons/Options/EnumOption.py
-SCons/Options/ListOption.py
-SCons/Options/PackageOption.py
-SCons/Options/PathOption.py
+SCons/Options.py
 SCons/PathList.py
 SCons/Platform/__init__.py
 SCons/Platform/aix.py
 SCons/Tool/yacc.py
 SCons/Tool/zip.py
 SCons/Util.py
+SCons/Variables/__init__.py
+SCons/Variables/BoolVariable.py
+SCons/Variables/EnumVariable.py
+SCons/Variables/ListVariable.py
+SCons/Variables/PackageVariable.py
+SCons/Variables/PathVariable.py
 SCons/Warnings.py

src/engine/SCons/Action.py

         except AttributeError:
             contents = self.funccontents
 
-        return contents + env.subst(string.join(map(lambda v: '${'+v+'}',
-                                                    self.varlist)))
+        result = [contents]
+        for v in self.varlist:
+            result.append(env.subst('${'+v+'}'))
+
+        return string.join(result, '')
 
     def get_implicit_deps(self, target, source, env):
         return []

src/engine/SCons/ActionTests.py

             expect_nonexecutable = 1
         elif sys.platform == 'cygwin':
             expect_nonexistent = 127
-            expect_nonexecutable = 127
+            # Newer cygwin seems to return 126 for following
+            expect_nonexecutable_file = 126
+            expect_nonexecutable_dir  = 127
         else:
             expect_nonexistent = 127
-            expect_nonexecutable = 126
+            expect_nonexecutable_file = 126
+            expect_nonexecutable_dir  = 126
 
         # Test that a nonexistent command returns 127
         act = SCons.Action.CommandAction(python + "_no_such_command_")
         dir, tail = os.path.split(python)
         act = SCons.Action.CommandAction(dir)
         r = act([], [], env.Clone(out = outfile))
-        assert r.status == expect_nonexecutable, r.status
+        assert r.status == expect_nonexecutable_file, r.status
 
         # Test that trying to execute a non-executable file returns 126
         act = SCons.Action.CommandAction(outfile)
         r = act([], [], env.Clone(out = outfile))
-        assert r.status == expect_nonexecutable, r.status
+        assert r.status == expect_nonexecutable_dir, r.status
 
         act = SCons.Action.CommandAction('%s %s 1' % (_python_, exit_py))
         r = act([], [], env)

src/engine/SCons/Debug.py

             res = resource.getrusage(resource.RUSAGE_SELF)
             return res[4]
 
-
-
-caller_dicts = {}
-
-def caller(*backlist):
+# returns caller's stack
+def caller_stack(*backlist):
     import traceback
     if not backlist:
         backlist = [0]
     result = []
     for back in backlist:
         tb = traceback.extract_stack(limit=3+back)
-        key = tb[1][:3]
-        try:
-            entry = caller_dicts[key]
-        except KeyError:
-            entry = caller_dicts[key] = {}
         key = tb[0][:3]
-        entry[key] = entry.get(key, 0) + 1
         result.append('%s:%d(%s)' % func_shorten(key))
     return result
 
+caller_bases = {}
+caller_dicts = {}
+
+# trace a caller's stack
+def caller_trace(back=0):
+    import traceback
+    tb = traceback.extract_stack(limit=3+back)
+    tb.reverse()
+    callee = tb[1][:3]
+    caller_bases[callee] = caller_bases.get(callee, 0) + 1
+    for caller in tb[2:]:
+        caller = callee + caller[:3]
+        try:
+            entry = caller_dicts[callee]
+        except KeyError:
+            caller_dicts[callee] = entry = {}
+        entry[caller] = entry.get(caller, 0) + 1
+        callee = caller
+
+# print a single caller and its callers, if any
+def _dump_one_caller(key, file, level=0):
+    l = []
+    for c,v in caller_dicts[key].items():
+        l.append((-v,c))
+    l.sort()
+    leader = '      '*level
+    for v,c in l:
+        file.write("%s  %6d %s:%d(%s)\n" % ((leader,-v) + func_shorten(c[-3:])))
+        if caller_dicts.has_key(c):
+            _dump_one_caller(c, file, level+1)
+
+# print each call tree
 def dump_caller_counts(file=sys.stdout):
-    keys = caller_dicts.keys()
+    keys = caller_bases.keys()
     keys.sort()
     for k in keys:
-        file.write("Callers of %s:%d(%s):\n" % func_shorten(k))
-        counts = caller_dicts[k]
-        callers = counts.keys()
-        callers.sort()
-        for c in callers:
-            #file.write("    counts[%s] = %s\n" % (c, counts[c]))
-            t = ((counts[c],) + func_shorten(c))
-            file.write("    %6d %s:%d(%s)\n" % t)
+        file.write("Callers of %s:%d(%s), %d calls:\n"
+                    % (func_shorten(k) + (caller_bases[k],)))
+        _dump_one_caller(k, file)
 
 shorten_list = [
     ( '/scons/SCons/',          1),
         if i >= 0:
             if t[1]:
                 i = i + len(t[0])
-            f = f[i:]
-            break
-    return (f,)+func_tuple[1:]
-
+            return (f[i:],)+func_tuple[1:]
+    return func_tuple
 
 
 TraceFP = {}

src/engine/SCons/Environment.py

                  platform=None,
                  tools=None,
                  toolpath=None,
-                 options=None,
+                 variables=None,
                  parse_flags = None,
                  **kw):
         """
         self._dict['PLATFORM'] = str(platform)
         platform(self)
 
-        # Apply the passed-in variables and customizable options to the
+        # Apply the passed-in and customizable variables to the
         # environment before calling the tools, because they may use
         # some of them during initialization.
+        if kw.has_key('options'):
+            # Backwards compatibility:  they may stll be using the
+            # old "options" keyword.
+            variables = kw['options']
+            del kw['options']
         apply(self.Replace, (), kw)
         keys = kw.keys()
-        if options:
-            keys = keys + options.keys()
-            options.Update(self)
+        if variables:
+            keys = keys + variables.keys()
+            variables.Update(self)
 
         save = {}
         for k in keys:
                 tools = ['default']
         apply_tools(self, tools, toolpath)
 
-        # Now restore the passed-in variables and customized options
+        # Now restore the passed-in and customized variables
         # to the environment, since the values the user set explicitly
         # should override any values set by the tools.
         for key, val in save.items():

src/engine/SCons/EnvironmentTests.py

         assert not env1.has_key('__env__')
         assert not env2.has_key('__env__')
 
-    def test_options(self):
-        """Test that options only get applied once."""
+    def test_variables(self):
+        """Test that variables only get applied once."""
         class FakeOptions:
             def __init__(self, key, val):
                 self.calls = 0
                 self.calls = self.calls + 1
 
         o = FakeOptions('AAA', 'fake_opt')
-        env = Environment(options=o, AAA='keyword_arg')
+        env = Environment(variables=o, AAA='keyword_arg')
         assert o.calls == 1, o.calls
         assert env['AAA'] == 'fake_opt', env['AAA']
 

src/engine/SCons/Executor.py

             self.sources_need_sorting = False
         return self.sources
 
+    def prepare(self):
+        """
+        Preparatory checks for whether this Executor can go ahead
+        and (try to) build its targets.
+        """
+        for s in self.get_sources():
+            if s.missing():
+                msg = "Source `%s' not found, needed by target `%s'."
+                raise SCons.Errors.StopError, msg % (s, self.targets[0])
+
     def add_pre_action(self, action):
         self.pre_actions.append(action)
 
         This essentially short-circuits an N*M scan of the sources for
         each individual target, which is a hell of a lot more efficient.
         """
-        map(lambda N: N.disambiguate(), node_list)
+        env = self.get_build_env()
 
-        env = self.get_build_env()
-        select_specific_scanner = lambda t: (t[0], t[1].select(t[0]))
-        remove_null_scanners = lambda t: not t[1] is None
-        add_scanner_path = lambda t, s=self: \
-                                  (t[0], t[1], s.get_build_scanner_path(t[1]))
+        deps = []
         if scanner:
-            scanner_list = map(lambda n, s=scanner: (n, s), node_list)
+            for node in node_list:
+                node.disambiguate()
+                scanner = scanner.select(node)
+                if not scanner:
+                    continue
+                path = self.get_build_scanner_path(scanner)
+                deps.extend(node.get_implicit_deps(env, scanner, path))
         else:
             kw = self.get_kw()
-            get_initial_scanners = lambda n, e=env, kw=kw: \
-                                          (n, n.get_env_scanner(e, kw))
-            scanner_list = map(get_initial_scanners, node_list)
-            scanner_list = filter(remove_null_scanners, scanner_list)
-
-        scanner_list = map(select_specific_scanner, scanner_list)
-        scanner_list = filter(remove_null_scanners, scanner_list)
-        scanner_path_list = map(add_scanner_path, scanner_list)
-
-        deps = []
-        for node, scanner, path in scanner_path_list:
-            deps.extend(node.get_implicit_deps(env, scanner, path))
+            for node in node_list:
+                node.disambiguate()
+                scanner = node.get_env_scanner(env, kw)
+                if not scanner:
+                    continue
+                scanner = scanner.select(node)
+                if not scanner:
+                    continue
+                path = self.get_build_scanner_path(scanner)
+                deps.extend(node.get_implicit_deps(env, scanner, path))
 
         deps.extend(self.get_implicit_deps())
 
         for tgt in self.targets:
             tgt.add_to_implicit(deps)
 
-    def get_missing_sources(self):
-        """
-        """
-        return filter(lambda s: s.missing(), self.get_sources())
-
     def _get_unignored_sources_key(self, ignore=()):
         return tuple(ignore)
 
         return None
     def cleanup(self):
         pass
+    def prepare(self):
+        pass

src/engine/SCons/ExecutorTests.py

         x.get_sources()
         assert x.sources == ['s1', 's2', 's3', 's4'], x.sources
 
+    def test_prepare(self):
+        """Test the Executor's prepare() method"""
+        env = MyEnvironment()
+        t1 = MyNode('t1')
+        s1 = MyNode('s1')
+        s2 = MyNode('s2')
+        s3 = MyNode('s3')
+        x = SCons.Executor.Executor('b', env, [{}], [t1], [s1, s2, s3])
+
+        s2.missing_val = True
+
+        try:
+            r = x.prepare()
+        except SCons.Errors.StopError, e:
+            assert str(e) == "Source `s2' not found, needed by target `t1'.", e
+        else:
+            raise AssertionError, "did not catch expected StopError: %s" % r
+
     def test_add_pre_action(self):
         """Test adding pre-actions to an Executor"""
         x = SCons.Executor.Executor('b', 'e', 'o', 't', ['s1', 's2'])
         assert t1.implicit == ['scanner-s1', 'scanner-s2'], t1.implicit
         assert t2.implicit == ['scanner-s1', 'scanner-s2'], t2.implicit
 
-    def test_get_missing_sources(self):
-        """Test the ability to check if any sources are missing"""
-        env = MyEnvironment()
-        targets = [MyNode('t')]
-        sources = [MyNode('s1'), MyNode('s2')]
-        x = SCons.Executor.Executor('b', env, [{}], targets, sources)
-        sources[0].missing_val = 1
-        missing = x.get_missing_sources()
-        assert missing == [sources[0]], missing
-
     def test_get_unignored_sources(self):
         """Test fetching the unignored source list"""
         env = MyEnvironment()

src/engine/SCons/Job.py

 
 import SCons.compat
 
+import os
+import signal
+
 
 # The default stack size (in kilobytes) of the threads used to execute
 # jobs in parallel.
 
 default_stack_size = 256
 
+interrupt_msg = 'Build interrupted.'
 
 class Jobs:
     """An instance of this class initializes N jobs, and provides
             self.job = Serial(taskmaster)
             self.num_jobs = 1
 
-    def run(self):
-        """run the job"""
+        self.job.interrupted = False
+
+    def run(self, postfunc=lambda: None):
+        """Run the jobs.
+
+        postfunc() will be invoked after the jobs has run. It will be
+        invoked even if the jobs are interrupted by a keyboard
+        interrupt (well, in fact by a signal such as either SIGINT,
+        SIGTERM or SIGHUP). The execution of postfunc() is protected
+        against keyboard interrupts and is guaranteed to run to
+        completion."""
+        self._setup_sig_handler()
         try:
             self.job.start()
-        except KeyboardInterrupt:
-            # mask any further keyboard interrupts so that scons
-            # can shutdown cleanly:
-            # (this only masks the keyboard interrupt for Python,
-            #  child processes can still get the keyboard interrupt)
-            import signal
-            signal.signal(signal.SIGINT, signal.SIG_IGN)
-            raise
+        finally:
+            postfunc()
+            self._reset_sig_handler()
 
-    def cleanup(self):
-        self.job.cleanup()