Support 'from SConsScript import *' to allow Python modules imported by SConscript...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 8 Jan 2005 22:38:53 +0000 (22:38 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 8 Jan 2005 22:38:53 +0000 (22:38 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1211 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/MANIFEST.in
src/engine/SCons/Script/Main.py [new file with mode: 0644]
src/engine/SCons/Script/SConscript.py
src/engine/SCons/Script/__init__.py
src/engine/SCons/Tool/mslink.py
src/engine/SCons/Tool/msvs.py
test/NodeOps.py
test/Script-import.py [new file with mode: 0644]
test/option--profile.py

index 7b34e8aef03f16ff30c8d0949e8800bd42cb377e..9fc5a6a12cbd1052bd5dc52e8f2e88441d4ab80b 100644 (file)
@@ -1257,6 +1257,15 @@ environment that consists of the tools and values that
 .B scons
 has determined are appropriate for the local system.
 
+Builder methods that can be called without an explicit
+environment may be called from custom Python modules that you
+import into an SConscript file by adding the following
+to the Python module:
+
+.ES
+from SCons.Script import *
+.EE
+
 All builder methods return a list of Nodes
 that represent the target or targets that will be built.
 A
@@ -2203,6 +2212,14 @@ environment it looks like:
 If you can call the functionality in both ways,
 then both forms are listed.
 
+Global functions may be called from custom Python modules that you
+import into an SConscript file by adding the following
+to the Python module:
+
+.ES
+from SCons.Script import *
+.EE
+
 Except where otherwise noted,
 the same-named
 construction environment method
@@ -4280,6 +4297,13 @@ In addition to the global functions and methods,
 supports a number of Python variables
 that can be used in SConscript files
 to affect how you want the build to be performed.
+These variables may be accessed from custom Python modules that you
+import into an SConscript file by adding the following
+to the Python module:
+
+.ES
+from SCons.Script import *
+.EE
 
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
index e13fa39753845e520527a4199a3946876b5b618e..fb98cce021361b17773d43cc925620fa69616f55 100644 (file)
@@ -170,6 +170,10 @@ RELEASE 0.97 - XXX
     duplicate entries from multiple calls.  Add a "unique" keyword
     argument to allow the old behavior to be specified.
 
+  - Allow the library modules imported by an SConscript file to get at
+    all of the normally-available global functions and variables by saying
+    "from SCons.Script import *".
+
   From Wayne Lee:
 
   - Avoid "maximum recursion limit" errors when removing $(-$) pairs
index 133ccade148603e078efe92cec9248468da1239e..5c10caef94e219fa7c5e38d55eb93035f10facd5 100644 (file)
@@ -43,6 +43,7 @@ SCons/Scanner/IDL.py
 SCons/Scanner/Prog.py
 SCons/SConf.py
 SCons/SConsign.py
+SCons/Script/Main.py
 SCons/Script/SConscript.py
 SCons/Script/__init__.py
 SCons/Sig/__init__.py
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
new file mode 100644 (file)
index 0000000..1bd6939
--- /dev/null
@@ -0,0 +1,1144 @@
+"""SCons.Script
+
+This file implements the main() function used by the scons script.
+
+Architecturally, this *is* the scons script, and will likely only be
+called from the external "scons" wrapper.  Consequently, anything here
+should not be, or be considered, part of the build engine.  If it's
+something that we expect other software to want to use, it should go in
+some other module.  If it's specific to the "scons" script invocation,
+it goes here.
+
+"""
+
+#
+# __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.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import os.path
+import random
+import string
+import sys
+import time
+import traceback
+
+# Strip the script directory from sys.path() so on case-insensitive
+# (WIN32) systems Python doesn't think that the "scons" script is the
+# "SCons" package.  Replace it with our own version directory so, if
+# if they're there, we pick up the right version of the build engine
+# modules.
+#sys.path = [os.path.join(sys.prefix,
+#                         'lib',
+#                         'scons-%d' % SCons.__version__)] + sys.path[1:]
+
+import SCons.Debug
+import SCons.Defaults
+import SCons.Environment
+import SCons.Errors
+import SCons.Job
+import SCons.Node
+import SCons.Node.FS
+from SCons.Optik import OptionParser, SUPPRESS_HELP, OptionValueError
+import SCons.SConf
+import SCons.Sig
+import SCons.Taskmaster
+import SCons.Util
+import SCons.Warnings
+
+#
+display = SCons.Util.display
+progress_display = SCons.Util.DisplayEngine()
+
+# Task control.
+#
+class BuildTask(SCons.Taskmaster.Task):
+    """An SCons build task."""
+    def display(self, message):
+        display('scons: ' + message)
+
+    def execute(self):
+        target = self.targets[0]
+        if target.get_state() == SCons.Node.up_to_date:
+            if self.top and target.has_builder():
+                display("scons: `%s' is up to date." % str(self.node))
+        elif target.has_builder() and not hasattr(target.builder, 'status'):
+            if print_time:
+                start_time = time.time()
+            SCons.Taskmaster.Task.execute(self)
+            if print_time:
+                finish_time = time.time()
+                global command_time
+                command_time = command_time+finish_time-start_time
+                print "Command execution time: %f seconds"%(finish_time-start_time)
+
+    def do_failed(self, status=2):
+        global exit_status
+        if ignore_errors:
+            SCons.Taskmaster.Task.executed(self)
+        elif keep_going_on_error:
+            SCons.Taskmaster.Task.fail_continue(self)
+            exit_status = status
+        else:
+            SCons.Taskmaster.Task.fail_stop(self)
+            exit_status = status
+            
+    def executed(self):
+        t = self.targets[0]
+        if self.top and not t.has_builder() and not t.side_effect:
+            if not t.exists():
+                sys.stderr.write("scons: *** Do not know how to make target `%s'." % t)
+                if not keep_going_on_error:
+                    sys.stderr.write("  Stop.")
+                sys.stderr.write("\n")
+                self.do_failed()
+            else:
+                print "scons: Nothing to be done for `%s'." % t
+                SCons.Taskmaster.Task.executed(self)
+        else:
+            SCons.Taskmaster.Task.executed(self)
+
+    def failed(self):
+        # Handle the failure of a build task.  The primary purpose here
+        # is to display the various types of Errors and Exceptions
+        # appropriately.
+        status = 2
+        exc_info = self.exc_info()
+        try:
+            t, e, tb = exc_info
+        except ValueError:
+            t, e = exc_info
+            tb = None
+        if t is None:
+            # The Taskmaster didn't record an exception for this Task;
+            # see if the sys module has one.
+            t, e = sys.exc_info()[:2]
+
+        if t == SCons.Errors.BuildError:
+            fname = e.node
+            if SCons.Util.is_List(e.node):
+                fname = string.join(map(str, e.node), ', ')
+            sys.stderr.write("scons: *** [%s] %s\n" % (fname, e.errstr))
+            if e.errstr == 'Exception':
+                traceback.print_exception(e.args[0], e.args[1], e.args[2])
+        elif t == SCons.Errors.ExplicitExit:
+            status = e.status
+            sys.stderr.write("scons: *** [%s] Explicit exit, status %s\n" % (e.node, e.status))
+        else:
+            if e is None:
+                e = t
+            s = str(e)
+            if t == SCons.Errors.StopError and not keep_going_on_error:
+                s = s + '  Stop.'
+            sys.stderr.write("scons: *** %s\n" % s)
+
+            if tb and print_stacktrace:
+                sys.stderr.write("scons: internal stack trace:\n")
+                traceback.print_tb(tb, file=sys.stderr)
+
+        self.do_failed(status)
+
+        self.exc_clear()
+
+    def postprocess(self):
+        if self.top:
+            t = self.targets[0]
+            if print_tree:
+                print
+                SCons.Util.print_tree(t, get_all_children)
+            if print_stree:
+                print
+                SCons.Util.print_tree(t, get_all_children, showtags=2)
+            if print_dtree:
+                print
+                SCons.Util.print_tree(t, get_derived_children)
+            if print_includes:
+                tree = t.render_include_tree()
+                if tree:
+                    print
+                    print tree
+        SCons.Taskmaster.Task.postprocess(self)
+
+    def make_ready(self):
+        """Make a task ready for execution"""
+        SCons.Taskmaster.Task.make_ready(self)
+        if self.out_of_date and print_explanations:
+            explanation = self.out_of_date[0].explain()
+            if explanation:
+                sys.stdout.write("scons: " + explanation)
+
+class CleanTask(SCons.Taskmaster.Task):
+    """An SCons clean task."""
+    def show(self):
+        if (self.targets[0].has_builder() or self.targets[0].side_effect) \
+           and not os.path.isdir(str(self.targets[0])):
+            display("Removed " + str(self.targets[0]))
+        if SCons.Environment.CleanTargets.has_key(self.targets[0]):
+            files = SCons.Environment.CleanTargets[self.targets[0]]
+            for f in files:
+                SCons.Util.fs_delete(str(f), 0)
+
+    def remove(self):
+        if self.targets[0].has_builder() or self.targets[0].side_effect:
+            for t in self.targets:
+                try:
+                    removed = t.remove()
+                except OSError, e:
+                    print "scons: Could not remove '%s':" % str(t), e.strerror
+                else:
+                    if removed:
+                        display("Removed " + str(t))
+        if SCons.Environment.CleanTargets.has_key(self.targets[0]):
+            files = SCons.Environment.CleanTargets[self.targets[0]]
+            for f in files:
+                SCons.Util.fs_delete(str(f))
+
+    execute = remove
+
+    # Have the taskmaster arrange to "execute" all of the targets, because
+    # we'll figure out ourselves (in remove() or show() above) whether
+    # anything really needs to be done.
+    make_ready = SCons.Taskmaster.Task.make_ready_all
+
+    def prepare(self):
+        pass
+
+class QuestionTask(SCons.Taskmaster.Task):
+    """An SCons task for the -q (question) option."""
+    def prepare(self):
+        pass
+    
+    def execute(self):
+        if self.targets[0].get_state() != SCons.Node.up_to_date:
+            global exit_status
+            exit_status = 1
+            self.tm.stop()
+
+    def executed(self):
+        pass
+
+# Global variables
+
+keep_going_on_error = 0
+print_count = 0
+print_dtree = 0
+print_explanations = 0
+print_includes = 0
+print_objects = 0
+print_stacktrace = 0
+print_stree = 0
+print_time = 0
+print_tree = 0
+memory_stats = None
+ignore_errors = 0
+sconscript_time = 0
+command_time = 0
+exit_status = 0 # exit status, assume success by default
+profiling = 0
+repositories = []
+num_jobs = 1 # this is modifed by SConscript.SetJobs()
+
+# utility functions
+
+def get_all_children(node): return node.all_children()
+
+def get_derived_children(node):
+    children = node.all_children(None)
+    return filter(lambda x: x.has_builder(), children)
+
+def _scons_syntax_error(e):
+    """Handle syntax errors. Print out a message and show where the error
+    occurred.
+    """
+    etype, value, tb = sys.exc_info()
+    lines = traceback.format_exception_only(etype, value)
+    for line in lines:
+        sys.stderr.write(line+'\n')
+    sys.exit(2)
+
+def find_deepest_user_frame(tb):
+    """
+    Find the deepest stack frame that is not part of SCons.
+
+    Input is a "pre-processed" stack trace in the form
+    returned by traceback.extract_tb() or traceback.extract_stack()
+    """
+    
+    tb.reverse()
+
+    # find the deepest traceback frame that is not part
+    # of SCons:
+    for frame in tb:
+        filename = frame[0]
+        if string.find(filename, os.sep+'SCons'+os.sep) == -1:
+            return frame
+    return tb[0]
+
+def _scons_user_error(e):
+    """Handle user errors. Print out a message and a description of the
+    error, along with the line number and routine where it occured. 
+    The file and line number will be the deepest stack frame that is
+    not part of SCons itself.
+    """
+    etype, value, tb = sys.exc_info()
+    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
+    sys.stderr.write("\nscons: *** %s\n" % value)
+    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
+    sys.exit(2)
+
+def _scons_user_warning(e):
+    """Handle user warnings. Print out a message and a description of
+    the warning, along with the line number and routine where it occured.
+    The file and line number will be the deepest stack frame that is
+    not part of SCons itself.
+    """
+    etype, value, tb = sys.exc_info()
+    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
+    sys.stderr.write("\nscons: warning: %s\n" % e)
+    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
+
+def _scons_internal_warning(e):
+    """Slightly different from _scons_user_warning in that we use the
+    *current call stack* rather than sys.exc_info() to get our stack trace.
+    This is used by the warnings framework to print warnings."""
+    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack())
+    sys.stderr.write("\nscons: warning: %s\n" % e[0])
+    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
+
+def _scons_internal_error():
+    """Handle all errors but user errors. Print out a message telling
+    the user what to do in this case and print a normal trace.
+    """
+    print 'internal error'
+    traceback.print_exc()
+    sys.exit(2)
+
+def _varargs(option, parser):
+    value = None
+    if parser.rargs:
+        arg = parser.rargs[0]
+        if arg[0] != "-":
+            value = arg
+            del parser.rargs[0]
+    return value
+
+def _setup_warn(arg):
+    """The --warn option.  An argument to this option
+    should be of the form <warning-class> or no-<warning-class>.
+    The warning class is munged in order to get an actual class
+    name from the SCons.Warnings module to enable or disable.
+    The supplied <warning-class> is split on hyphens, each element
+    is captialized, then smushed back together.  Then the string
+    "SCons.Warnings." is added to the front and "Warning" is added
+    to the back to get the fully qualified class name.
+
+    For example, --warn=deprecated will enable the
+    SCons.Warnings.DeprecatedWarning class.
+
+    --warn=no-dependency will disable the
+    SCons.Warnings.DependencyWarning class.
+
+    As a special case, --warn=all and --warn=no-all
+    will enable or disable (respectively) the base
+    class of all warnings, which is SCons.Warning.Warning."""
+
+    elems = string.split(string.lower(arg), '-')
+    enable = 1
+    if elems[0] == 'no':
+        enable = 0
+        del elems[0]
+
+    if len(elems) == 1 and elems[0] == 'all':
+        class_name = "Warning"
+    else:
+        def _capitalize(s):
+            if s[:5] == "scons":
+                return "SCons" + s[5:]
+            else:
+                return string.capitalize(s)
+        class_name = string.join(map(_capitalize, elems), '') + "Warning"
+    try:
+        clazz = getattr(SCons.Warnings, class_name)
+    except AttributeError:
+        sys.stderr.write("No warning type: '%s'\n" % arg)
+    else:
+        if enable:
+            SCons.Warnings.enableWarningClass(clazz)
+        else:
+            SCons.Warnings.suppressWarningClass(clazz)
+
+def _SConstruct_exists(dirname=''):
+    """This function checks that an SConstruct file exists in a directory.
+    If so, it returns the path of the file. By default, it checks the
+    current directory.
+    """
+    global repositories
+    for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
+        sfile = os.path.join(dirname, file)
+        if os.path.isfile(sfile):
+            return sfile
+        if not os.path.isabs(sfile):
+            for rep in repositories:
+                if os.path.isfile(os.path.join(rep, sfile)):
+                    return sfile
+    return None
+
+def _set_globals(options):
+    global repositories, keep_going_on_error, ignore_errors
+    global print_count, print_dtree
+    global print_explanations, print_includes
+    global print_objects, print_stacktrace, print_stree
+    global print_time, print_tree
+    global memory_outf, memory_stats
+
+    if options.repository:
+        repositories.extend(options.repository)
+    keep_going_on_error = options.keep_going
+    try:
+        if options.debug:
+            if options.debug == "count":
+                print_count = 1
+            elif options.debug == "dtree":
+                print_dtree = 1
+            elif options.debug == "explain":
+                print_explanations = 1
+            elif options.debug == "findlibs":
+                SCons.Scanner.Prog.print_find_libs = "findlibs"
+            elif options.debug == "includes":
+                print_includes = 1
+            elif options.debug == "memory":
+                memory_stats = []
+                memory_outf = sys.stdout
+            elif options.debug == "objects":
+                print_objects = 1
+            elif options.debug == "presub":
+                SCons.Action.print_actions_presub = 1
+            elif options.debug == "stacktrace":
+                print_stacktrace = 1
+            elif options.debug == "stree":
+                print_stree = 1
+            elif options.debug == "time":
+                print_time = 1
+            elif options.debug == "tree":
+                print_tree = 1
+    except AttributeError:
+        pass
+    ignore_errors = options.ignore_errors
+
+def _create_path(plist):
+    path = '.'
+    for d in plist:
+        if os.path.isabs(d):
+            path = d
+        else:
+            path = path + '/' + d
+    return path
+
+
+class OptParser(OptionParser):
+    def __init__(self):
+        import __main__
+        import SCons
+        parts = ["SCons by Steven Knight et al.:\n"]
+        try:
+            parts.append("\tscript: v%s.%s, %s, by %s on %s\n" % (__main__.__version__,
+                                                                  __main__.__build__,
+                                                                  __main__.__date__,
+                                                                  __main__.__developer__,
+                                                                  __main__.__buildsys__))
+        except KeyboardInterrupt:
+            raise
+        except:
+            # On win32 there is no scons.py, so there is no __main__.__version__,
+            # hence there is no script version.
+            pass 
+        parts.append("\tengine: v%s.%s, %s, by %s on %s\n" % (SCons.__version__,
+                                                              SCons.__build__,
+                                                              SCons.__date__,
+                                                              SCons.__developer__,
+                                                              SCons.__buildsys__))
+        parts.append("__COPYRIGHT__")
+        OptionParser.__init__(self, version=string.join(parts, ''),
+                              usage="usage: scons [OPTION] [TARGET] ...")
+
+        # options ignored for compatibility
+        def opt_ignore(option, opt, value, parser):
+            sys.stderr.write("Warning:  ignoring %s option\n" % opt)
+        self.add_option("-b", "-m", "-S", "-t", "--no-keep-going", "--stop",
+                        "--touch", action="callback", callback=opt_ignore,
+                        help="Ignored for compatibility.")
+
+        self.add_option('-c', '--clean', '--remove', action="store_true",
+                        dest="clean",
+                        help="Remove specified targets and dependencies.")
+
+        self.add_option('-C', '--directory', type="string", action = "append",
+                        metavar="DIR",
+                        help="Change to DIR before doing anything.")
+
+        self.add_option('--cache-disable', '--no-cache',
+                        action="store_true", dest='cache_disable', default=0,
+                        help="Do not retrieve built targets from CacheDir.")
+
+        self.add_option('--cache-force', '--cache-populate',
+                        action="store_true", dest='cache_force', default=0,
+                        help="Copy already-built targets into the CacheDir.")
+
+        self.add_option('--cache-show',
+                        action="store_true", dest='cache_show', default=0,
+                        help="Print build actions for files from CacheDir.")
+
+        config_options = ["auto", "force" ,"cache"]
+
+        def opt_config(option, opt, value, parser, c_options=config_options):
+            if value in c_options:
+                parser.values.config = value
+            else:
+                raise OptionValueError("Warning:  %s is not a valid config type" % value)
+        self.add_option('--config', action="callback", type="string",
+                        callback=opt_config, nargs=1, dest="config",
+                        metavar="MODE", default="auto",
+                        help="Controls Configure subsystem: "
+                             "%s." % string.join(config_options, ", "))
+
+        def opt_not_yet(option, opt, value, parser):
+            sys.stderr.write("Warning:  the %s option is not yet implemented\n" % opt)
+            sys.exit(0)
+        self.add_option('-d', action="callback",
+                        callback=opt_not_yet,
+                        help = "Print file dependency information.")
+        
+        self.add_option('-D', action="store_const", const=2, dest="climb_up",
+                        help="Search up directory tree for SConstruct,       "
+                             "build all Default() targets.")
+
+        debug_options = ["count", "dtree", "explain", "findlibs",
+                         "includes", "memory", "objects",
+                         "pdb", "presub", "stacktrace", "stree",
+                         "time", "tree"]
+
+        def opt_debug(option, opt, value, parser, debug_options=debug_options):
+            if value in debug_options:
+                parser.values.debug = value
+            else:
+                raise OptionValueError("Warning:  %s is not a valid debug type" % value)
+        self.add_option('--debug', action="callback", type="string",
+                        callback=opt_debug, nargs=1, dest="debug",
+                        metavar="TYPE",
+                        help="Print various types of debugging information: "
+                             "%s." % string.join(debug_options, ", "))
+
+        def opt_duplicate(option, opt, value, parser):
+            if not value in SCons.Node.FS.Valid_Duplicates:
+                raise OptionValueError("`%s' is not a valid duplication style." % value)
+            parser.values.duplicate = value
+            # Set the duplicate style right away so it can affect linking
+            # of SConscript files.
+            SCons.Node.FS.set_duplicate(value)
+        self.add_option('--duplicate', action="callback", type="string",
+                        callback=opt_duplicate, nargs=1, dest="duplicate",
+                        help="Set the preferred duplication methods. Must be one of "
+                        + string.join(SCons.Node.FS.Valid_Duplicates, ", "))
+
+        self.add_option('-f', '--file', '--makefile', '--sconstruct',
+                        action="append", nargs=1,
+                        help="Read FILE as the top-level SConstruct file.")
+
+        self.add_option('-h', '--help', action="store_true", default=0,
+                        dest="help_msg",
+                        help="Print defined help message, or this one.")
+
+        self.add_option("-H", "--help-options",
+                        action="help",
+                        help="Print this message and exit.")
+
+        self.add_option('-i', '--ignore-errors', action="store_true",
+                        default=0, dest='ignore_errors',
+                        help="Ignore errors from build actions.")
+
+        self.add_option('-I', '--include-dir', action="append",
+                        dest='include_dir', metavar="DIR",
+                        help="Search DIR for imported Python modules.")
+
+        self.add_option('--implicit-cache', action="store_true",
+                        dest='implicit_cache',
+                        help="Cache implicit dependencies")
+
+        self.add_option('--implicit-deps-changed', action="store_true",
+                        default=0, dest='implicit_deps_changed',
+                        help="Ignore cached implicit dependencies.")
+        self.add_option('--implicit-deps-unchanged', action="store_true",
+                        default=0, dest='implicit_deps_unchanged',
+                        help="Ignore changes in implicit dependencies.")
+
+        def opt_j(option, opt, value, parser):
+            value = int(value)
+            parser.values.num_jobs = value
+        self.add_option('-j', '--jobs', action="callback", type="int",
+                        callback=opt_j, metavar="N",
+                        help="Allow N jobs at once.")
+
+        self.add_option('-k', '--keep-going', action="store_true", default=0,
+                        dest='keep_going',
+                        help="Keep going when a target can't be made.")
+
+        self.add_option('--max-drift', type="int", action="store",
+                        dest='max_drift', metavar="N",
+                        help="Set maximum system clock drift to N seconds.")
+
+        self.add_option('-n', '--no-exec', '--just-print', '--dry-run',
+                        '--recon', action="store_true", dest='noexec',
+                        default=0, help="Don't build; just print commands.")
+
+        def opt_profile(option, opt, value, parser):
+            global profiling
+            if not profiling:
+                profiling = 1
+                import profile
+                profile.run('SCons.Script.Main.main()', value)
+                sys.exit(exit_status)
+        self.add_option('--profile', nargs=1, action="callback",
+                        callback=opt_profile, type="string", dest="profile",
+                        metavar="FILE",
+                        help="Profile SCons and put results in FILE.")
+
+        self.add_option('-q', '--question', action="store_true", default=0,
+                        help="Don't build; exit status says if up to date.")
+
+        self.add_option('-Q', dest='no_progress', action="store_true",
+                        default=0,
+                        help="Suppress \"Reading/Building\" progress messages.")
+
+        self.add_option('--random', dest="random", action="store_true",
+                        default=0, help="Build dependencies in random order.")
+
+        self.add_option('-s', '--silent', '--quiet', action="store_true",
+                        default=0, help="Don't print commands.")
+
+        self.add_option('-u', '--up', '--search-up', action="store_const",
+                        dest="climb_up", default=0, const=1,
+                        help="Search up directory tree for SConstruct,       "
+                             "build targets at or below current directory.")
+        self.add_option('-U', action="store_const", dest="climb_up",
+                        default=0, const=3,
+                        help="Search up directory tree for SConstruct,       "
+                             "build Default() targets from local SConscript.")
+
+        self.add_option("-v", "--version",
+                        action="version",
+                        help="Print the SCons version number and exit.")
+
+        self.add_option('--warn', '--warning', nargs=1, action="store",
+                        metavar="WARNING-SPEC",
+                        help="Enable or disable warnings.")
+
+        self.add_option('-Y', '--repository', nargs=1, action="append",
+                        help="Search REPOSITORY for source and target files.")
+
+        self.add_option('-e', '--environment-overrides', action="callback",
+                        callback=opt_not_yet,
+                        # help="Environment variables override makefiles."
+                        help=SUPPRESS_HELP)
+        self.add_option('-l', '--load-average', '--max-load', action="callback",
+                        callback=opt_not_yet, type="int", dest="load_average",
+                        # action="store",
+                        # help="Don't start multiple jobs unless load is below "
+                        #      "LOAD-AVERAGE."
+                        # type="int",
+                        help=SUPPRESS_HELP)
+        self.add_option('--list-derived', action="callback",
+                        callback=opt_not_yet,
+                        # help="Don't build; list files that would be built."
+                        help=SUPPRESS_HELP)
+        self.add_option('--list-actions', action="callback",
+                        callback=opt_not_yet,
+                        # help="Don't build; list files and build actions."
+                        help=SUPPRESS_HELP)
+        self.add_option('--list-where', action="callback",
+                        callback=opt_not_yet,
+                        # help="Don't build; list files and where defined."
+                        help=SUPPRESS_HELP)
+        self.add_option('-o', '--old-file', '--assume-old', action="callback",
+                        callback=opt_not_yet, type="string", dest="old_file",
+                        # help = "Consider FILE to be old; don't rebuild it."
+                        help=SUPPRESS_HELP)
+        self.add_option('--override', action="callback", dest="override",
+                        callback=opt_not_yet, type="string",
+                        # help="Override variables as specified in FILE."
+                        help=SUPPRESS_HELP)
+        self.add_option('-p', action="callback",
+                        callback=opt_not_yet,
+                        # help="Print internal environments/objects."
+                        help=SUPPRESS_HELP)
+        self.add_option('-r', '-R', '--no-builtin-rules',
+                        '--no-builtin-variables', action="callback",
+                        callback=opt_not_yet,
+                        # help="Clear default environments and variables."
+                        help=SUPPRESS_HELP)
+        self.add_option('-w', '--print-directory', action="callback",
+                        callback=opt_not_yet,
+                        # help="Print the current directory."
+                        help=SUPPRESS_HELP)
+        self.add_option('--no-print-directory', action="callback",
+                        callback=opt_not_yet,
+                        # help="Turn off -w, even if it was turned on implicitly."
+                        help=SUPPRESS_HELP)
+        self.add_option('--write-filenames', action="callback",
+                        callback=opt_not_yet, type="string", dest="write_filenames",
+                        # help="Write all filenames examined into FILE."
+                        help=SUPPRESS_HELP)
+        self.add_option('-W', '--what-if', '--new-file', '--assume-new',
+                        dest="new_file",
+                        action="callback", callback=opt_not_yet, type="string",
+                        # help="Consider FILE to be changed."
+                        help=SUPPRESS_HELP)
+        self.add_option('--warn-undefined-variables', action="callback",
+                        callback=opt_not_yet,
+                        # help="Warn when an undefined variable is referenced."
+                        help=SUPPRESS_HELP)
+
+    def parse_args(self, args=None, values=None):
+        opt, arglist = OptionParser.parse_args(self, args, values)
+        if opt.implicit_deps_changed or opt.implicit_deps_unchanged:
+            opt.implicit_cache = 1
+        return opt, arglist
+
+class SConscriptSettableOptions:
+    """This class wraps an OptParser instance and provides
+    uniform access to options that can be either set on the command
+    line or from a SConscript file. A value specified on the command
+    line always overrides a value set in a SConscript file.
+    Not all command line options are SConscript settable, and the ones
+    that are must be explicitly added to settable dictionary and optionally
+    validated and coerced in the set() method."""
+    
+    def __init__(self, options):
+        self.options = options
+
+        # This dictionary stores the defaults for all the SConscript
+        # settable options, as well as indicating which options
+        # are SConscript settable. 
+        self.settable = {'num_jobs':1,
+                         'max_drift':SCons.Sig.default_max_drift,
+                         'implicit_cache':0,
+                         'clean':0,
+                         'duplicate':'hard-soft-copy'}
+
+    def get(self, name):
+        if not self.settable.has_key(name):
+            raise SCons.Error.UserError, "This option is not settable from a SConscript file: %s"%name
+        if hasattr(self.options, name) and getattr(self.options, name) is not None:
+            return getattr(self.options, name)
+        else:
+            return self.settable[name]
+
+    def set(self, name, value):
+        if not self.settable.has_key(name):
+            raise SCons.Error.UserError, "This option is not settable from a SConscript file: %s"%name
+
+        if name == 'num_jobs':
+            try:
+                value = int(value)
+                if value < 1:
+                    raise ValueError
+            except ValueError:
+                raise SCons.Errors.UserError, "A positive integer is required: %s"%repr(value)
+        elif name == 'max_drift':
+            try:
+                value = int(value)
+            except ValueError:
+                raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
+        elif name == 'duplicate':
+            try:
+                value = str(value)
+            except ValueError:
+                raise SCons.Errors.UserError, "A string is required: %s"%repr(value)
+            if not value in SCons.Node.FS.Valid_Duplicates:
+                raise SCons.Errors.UserError, "Not a valid duplication style: %s" % value
+            # Set the duplicate stye right away so it can affect linking
+            # of SConscript files.
+            SCons.Node.FS.set_duplicate(value)
+
+        self.settable[name] = value
+    
+
+def _main(args, parser):
+    targets = []
+    fs = SCons.Node.FS.default_fs
+
+    # Enable deprecated warnings by default.
+    SCons.Warnings._warningOut = _scons_internal_warning
+    SCons.Warnings.enableWarningClass(SCons.Warnings.CorruptSConsignWarning)
+    SCons.Warnings.enableWarningClass(SCons.Warnings.DeprecatedWarning)
+    SCons.Warnings.enableWarningClass(SCons.Warnings.DuplicateEnvironmentWarning)
+    SCons.Warnings.enableWarningClass(SCons.Warnings.MissingSConscriptWarning)
+    SCons.Warnings.enableWarningClass(SCons.Warnings.NoParallelSupportWarning)
+    # This is good for newbies, and hopefully most everyone else too.
+    SCons.Warnings.enableWarningClass(SCons.Warnings.MisleadingKeywordsWarning)
+
+    global ssoptions
+    ssoptions = SConscriptSettableOptions(options)
+
+    _set_globals(options)
+    SCons.Node.implicit_cache = options.implicit_cache
+    SCons.Node.implicit_deps_changed = options.implicit_deps_changed
+    SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
+    if options.warn:
+        _setup_warn(options.warn)
+    if options.noexec:
+        SCons.SConf.dryrun = 1
+        SCons.Action.execute_actions = None
+        CleanTask.execute = CleanTask.show
+    if options.question:
+        SCons.SConf.dryrun = 1
+    SCons.SConf.SetCacheMode(options.config)
+    SCons.SConf.SetProgressDisplay(progress_display)
+
+    if options.no_progress or options.silent:
+        progress_display.set_mode(0)
+    if options.silent:
+        display.set_mode(0)
+    if options.silent:
+        SCons.Action.print_actions = None
+    if options.cache_disable:
+        def disable(self): pass
+        fs.CacheDir = disable
+    if options.cache_force:
+        fs.cache_force = 1
+    if options.cache_show:
+        fs.cache_show = 1
+    if options.directory:
+        cdir = _create_path(options.directory)
+        try:
+            os.chdir(cdir)
+        except OSError:
+            sys.stderr.write("Could not change directory to %s\n" % cdir)
+
+    xmit_args = []
+    for a in args:
+        if '=' in a:
+            xmit_args.append(a)
+        else:
+            targets.append(a)
+    SCons.Script._Add_Arguments(xmit_args)
+    SCons.Script._Add_Targets(targets)
+
+    target_top = None
+    if options.climb_up:
+        target_top = '.'  # directory to prepend to targets
+        script_dir = os.getcwd()  # location of script
+        while script_dir and not _SConstruct_exists(script_dir):
+            script_dir, last_part = os.path.split(script_dir)
+            if last_part:
+                target_top = os.path.join(last_part, target_top)
+            else:
+                script_dir = ''
+        if script_dir:
+            display("scons: Entering directory `%s'" % script_dir)
+            os.chdir(script_dir)
+        else:
+            raise SCons.Errors.UserError, "No SConstruct file found."
+
+    fs.set_toplevel_dir(os.getcwd())
+
+    scripts = []
+    if options.file:
+        scripts.extend(options.file)
+    if not scripts:
+        sfile = _SConstruct_exists()
+        if sfile:
+            scripts.append(sfile)
+
+    if options.help_msg:
+        if not scripts:
+            # There's no SConstruct, but they specified -h.
+            # Give them the options usage now, before we fail
+            # trying to read a non-existent SConstruct file.
+            parser.print_help()
+            sys.exit(0)
+
+    if not scripts:
+        raise SCons.Errors.UserError, "No SConstruct file found."
+
+    if scripts[0] == "-":
+        d = fs.getcwd()
+    else:
+        d = fs.File(scripts[0]).dir
+    fs.set_SConstruct_dir(d)
+
+    class Unbuffered:
+        def __init__(self, file):
+            self.file = file
+        def write(self, arg):
+            self.file.write(arg)
+            self.file.flush()
+        def __getattr__(self, attr):
+            return getattr(self.file, attr)
+
+    sys.stdout = Unbuffered(sys.stdout)
+
+    if options.include_dir:
+        sys.path = options.include_dir + sys.path
+
+    global repositories
+    for rep in repositories:
+        fs.Repository(rep)
+
+    if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
+
+    progress_display("scons: Reading SConscript files ...")
+
+    start_time = time.time()
+    try:
+        for script in scripts:
+            SCons.Script._SConscript._SConscript(fs, script)
+    except SCons.Errors.StopError, e:
+        # We had problems reading an SConscript file, such as it
+        # couldn't be copied in to the BuildDir.  Since we're just
+        # reading SConscript files and haven't started building
+        # things yet, stop regardless of whether they used -i or -k
+        # or anything else.
+        global exit_status
+        sys.stderr.write("scons: *** %s  Stop.\n" % e)
+        exit_status = 2
+        sys.exit(exit_status)
+    global sconscript_time
+    sconscript_time = time.time() - start_time
+    SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
+    progress_display("scons: done reading SConscript files.")
+
+    # Tell the Node.FS subsystem that we're all done reading the
+    # SConscript files and calling Repository() and BuildDir() and the
+    # like, so it can go ahead and start memoizing the string values of
+    # file system nodes.
+    SCons.Node.FS.save_strings(1)
+
+    if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
+
+    fs.chdir(fs.Top)
+
+    if options.help_msg:
+        help_text = SCons.Script.help_text
+        if help_text is None:
+            # They specified -h, but there was no Help() inside the
+            # SConscript files.  Give them the options usage.
+            parser.print_help(sys.stdout)
+        else:
+            print help_text
+            print "Use scons -H for help about command-line options."
+        sys.exit(0)
+
+    # Now that we've read the SConscripts we can set the options
+    # that are SConscript settable:
+    SCons.Node.implicit_cache = ssoptions.get('implicit_cache')
+    SCons.Node.FS.set_duplicate(ssoptions.get('duplicate'))
+
+    lookup_top = None
+    if targets:
+        # They specified targets on the command line, so if they
+        # used -u, -U or -D, we have to look up targets relative
+        # to the top, but we build whatever they specified.
+        if target_top:
+            lookup_top = fs.Dir(target_top)
+            target_top = None
+    else:
+        # There are no targets specified on the command line,
+        # so if they used -u, -U or -D, we may have to restrict
+        # what actually gets built.
+        d = None
+        if target_top:
+            if options.climb_up == 1:
+                # -u, local directory and below
+                target_top = fs.Dir(target_top)
+                lookup_top = target_top
+            elif options.climb_up == 2:
+                # -D, all Default() targets
+                target_top = None
+                lookup_top = None
+            elif options.climb_up == 3:
+                # -U, local SConscript Default() targets
+                target_top = fs.Dir(target_top)
+                def check_dir(x, target_top=target_top):
+                    if hasattr(x, 'cwd') and not x.cwd is None:
+                        cwd = x.cwd.srcnode()
+                        return cwd == target_top
+                    else:
+                        # x doesn't have a cwd, so it's either not a target,
+                        # or not a file, so go ahead and keep it as a default
+                        # target and let the engine sort it out:
+                        return 1                
+                d = filter(check_dir, SCons.Script.DEFAULT_TARGETS)
+                SCons.Script.DEFAULT_TARGETS[:] = d
+                target_top = None
+                lookup_top = None
+
+        targets = SCons.Script._Get_Default_Targets(d, fs)
+
+    if not targets:
+        sys.stderr.write("scons: *** No targets specified and no Default() targets found.  Stop.\n")
+        sys.exit(2)
+
+    def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
+        if isinstance(x, SCons.Node.Node):
+            node = x
+        else:
+            node = SCons.Node.Alias.default_ans.lookup(x)
+            if node is None:
+                node = fs.Entry(x, directory=ltop, create=1)
+        if ttop and not node.is_under(ttop):
+            if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
+                node = ttop
+            else:
+                node = None
+        return node
+
+    nodes = filter(lambda x: x is not None, map(Entry, targets))
+
+    task_class = BuildTask     # default action is to build targets
+    opening_message = "Building targets ..."
+    closing_message = "done building targets."
+    if keep_going_on_error:
+        failure_message = "done building targets (errors occurred during build)."
+    else:
+        failure_message = "building terminated because of errors."
+    if options.question:
+        task_class = QuestionTask
+    try:
+        if ssoptions.get('clean'):
+            task_class = CleanTask
+            opening_message = "Cleaning targets ..."
+            closing_message = "done cleaning targets."
+            if keep_going_on_error:
+                closing_message = "done cleaning targets (errors occurred during clean)."
+            else:
+                failure_message = "cleaning terminated because of errors."
+    except AttributeError:
+        pass
+
+    SCons.Environment.CalculatorArgs['max_drift'] = ssoptions.get('max_drift')
+
+    if options.random:
+        def order(dependencies):
+            """Randomize the dependencies."""
+            # This is cribbed from the implementation of
+            # random.shuffle() in Python 2.X.
+            d = dependencies
+            for i in xrange(len(d)-1, 0, -1):
+                j = int(random.random() * (i+1))
+                d[i], d[j] = d[j], d[i]
+            return d
+    else:
+        def order(dependencies):
+            """Leave the order of dependencies alone."""
+            return dependencies
+
+    progress_display("scons: " + opening_message)
+    taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order)
+
+    nj = ssoptions.get('num_jobs')
+    jobs = SCons.Job.Jobs(nj, taskmaster)
+    if nj > 1 and jobs.num_jobs == 1:
+        msg = "parallel builds are unsupported by this version of Python;\n" + \
+              "\tignoring -j or num_jobs option.\n"
+        SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
+
+    if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
+
+    try:
+        jobs.run()
+    finally:
+        if exit_status:
+            progress_display("scons: " + failure_message)
+        else:
+            progress_display("scons: " + closing_message)
+        if not options.noexec:
+            SCons.SConsign.write()
+
+    if not memory_stats is None:
+        memory_stats.append(SCons.Debug.memory())
+        when = [
+            'before SConscript files',
+            'after SConscript files',
+            'before building',
+            'after building',
+        ]
+        for i in xrange(len(when)):
+            memory_outf.write('Memory %s:  %d\n' % (when[i], memory_stats[i]))
+
+    if print_count:
+        SCons.Debug.countLoggedInstances('*')
+
+    if print_objects:
+        SCons.Debug.listLoggedInstances('*')
+        #SCons.Debug.dumpLoggedInstances('*')
+
+def _exec_main():
+    all_args = sys.argv[1:]
+    try:
+        all_args = string.split(os.environ['SCONSFLAGS']) + all_args
+    except KeyError:
+            # it's OK if there's no SCONSFLAGS
+            pass
+    parser = OptParser()
+    global options
+    options, args = parser.parse_args(all_args)
+    if options.debug == "pdb":
+        import pdb
+        pdb.Pdb().runcall(_main, args, parser)
+    else:
+        _main(args, parser)
+
+def main():
+    global exit_status
+    
+    try:
+       _exec_main()
+    except SystemExit, s:
+        if s:
+            exit_status = s
+    except KeyboardInterrupt:
+        print "Build interrupted."
+        sys.exit(2)
+    except SyntaxError, e:
+        _scons_syntax_error(e)
+    except SCons.Errors.InternalError:
+        _scons_internal_error()
+    except SCons.Errors.UserError, e:
+        _scons_user_error(e)
+    except:
+        # An exception here is likely a builtin Python exception Python
+        # code in an SConscript file.  Show them precisely what the
+        # problem was and where it happened.
+        SCons.Script._SConscript.SConscript_exception()
+        sys.exit(2)
+
+    if print_time:
+        total_time = time.time()-SCons.Script.start_time
+        scons_time = total_time-sconscript_time-command_time
+        print "Total build time: %f seconds"%total_time
+        print "Total SConscript file execution time: %f seconds"%sconscript_time
+        print "Total SCons execution time: %f seconds"%scons_time
+        print "Total command execution time: %f seconds"%command_time
+
+    sys.exit(exit_status)
index 30f6933d80964dc9212fbb08a8cfd49cb511c8ad..e30a97954dbff7d6d165047689650859b55894dc 100644 (file)
@@ -42,7 +42,7 @@ import SCons.Node.FS
 import SCons.Options
 import SCons.Platform
 import SCons.SConf
-import SCons.Script
+import SCons.Script.Main
 import SCons.Tool
 import SCons.Util
 
@@ -57,30 +57,7 @@ import UserList
 
 launch_dir = os.path.abspath(os.curdir)
 
-help_text = None
-
-def HelpFunction(text):
-    global help_text
-    if help_text is None:
-        help_text = text
-    else:
-        help_text = help_text + text
-
-Arguments = {}
-ArgList = []
-CommandLineTargets = []
-DefaultCalled = None
-DefaultTargets = []
-GlobalDict = {}
-
-class TargetList(UserList.UserList):
-    def _do_nothing(self, *args, **kw):
-        pass
-    def _add_Default(self, list):
-        self.extend(list)
-    def _clear(self):
-        del self[:]
-BuildTargets = TargetList()
+GlobalDict = None
 
 # global exports set by Export():
 global_exports = {}
@@ -88,29 +65,21 @@ global_exports = {}
 # chdir flag
 sconscript_chdir = 1
 
-# will be set to 1, if we are reading a SConscript
-sconscript_reading = 0
-
-def _scons_add_args(alist):
-    for arg in alist:
-        a, b = string.split(arg, '=', 1)
-        Arguments[a] = b
-        ArgList.append((a, b))
-
-def _scons_add_targets(tlist):
-    if tlist:
-        CommandLineTargets.extend(tlist)
-        BuildTargets.extend(tlist)
-        BuildTargets._add_Default = BuildTargets._do_nothing
-        BuildTargets._clear = BuildTargets._do_nothing
-
 def get_calling_namespaces():
     """Return the locals and globals for the function that called
-    into this module in the current callstack."""
+    into this module in the current call stack."""
     try: 1/0
     except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
 
-    while frame.f_globals.get("__name__") == __name__: frame = frame.f_back
+    # Find the first frame that *isn't* from this file.  This means
+    # that we expect all of the SCons frames that implement an Export()
+    # or SConscript() call to be in this file, so that we can identify
+    # the first non-Script.SConscript frame as the user's local calling
+    # environment, and the locals and globals dictionaries from that
+    # frame as the calling namespaces.  See the comment below preceding
+    # the DefaultEnvironmentCall block for even more explanation.
+    while frame.f_globals.get("__name__") == __name__:
+        frame = frame.f_back
 
     return frame.f_locals, frame.f_globals
 
@@ -136,7 +105,6 @@ def compute_exports(exports):
 
     return retval
 
-
 class Frame:
     """A frame on the SConstruct/SConscript call stack"""
     def __init__(self, exports, sconscript):
@@ -151,7 +119,7 @@ class Frame:
             self.sconscript = SCons.Node.FS.default_fs.File(str(sconscript))
 
 # the SConstruct/SConscript call stack:
-stack = []
+call_stack = []
 
 # For documentation on the methods in this file, see the scons man-page
 
@@ -160,14 +128,14 @@ def Return(*vars):
     try:
         for var in vars:
             for v in string.split(var):
-                retval.append(stack[-1].globals[v])
+                retval.append(call_stack[-1].globals[v])
     except KeyError, x:
         raise SCons.Errors.UserError, "Return of non-existent variable '%s'"%x
 
     if len(retval) == 1:
-        stack[-1].retval = retval[0]
+        call_stack[-1].retval = retval[0]
     else:
-        stack[-1].retval = tuple(retval)
+        call_stack[-1].retval = tuple(retval)
 
 
 stack_bottom = '% Stack boTTom %' # hard to define a variable w/this name :)
@@ -180,13 +148,12 @@ def _SConscript(fs, *files, **kw):
     # evaluate each SConscript file
     results = []
     for fn in files:
-        stack.append(Frame(exports,fn))
+        call_stack.append(Frame(exports,fn))
         old_sys_path = sys.path
         try:
-            global sconscript_reading
-            sconscript_reading = 1
+            SCons.Script.sconscript_reading = 1
             if fn == "-":
-                exec sys.stdin in stack[-1].globals
+                exec sys.stdin in call_stack[-1].globals
             else:
                 if isinstance(fn, SCons.Node.Node):
                     f = fn
@@ -246,16 +213,16 @@ def _SConscript(fs, *files, **kw):
                     # exceptions that occur when processing this
                     # SConscript can base the printed frames at this
                     # level and not show SCons internals as well.
-                    stack[-1].globals.update({stack_bottom:1})
-                    exec _file_ in stack[-1].globals
+                    call_stack[-1].globals.update({stack_bottom:1})
+                    exec _file_ in call_stack[-1].globals
                 else:
                     SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning,
                              "Ignoring missing SConscript '%s'" % f.path)
 
         finally:
-            sconscript_reading = 0
+            SCons.Script.sconscript_reading = 0
             sys.path = old_sys_path
-            frame = stack.pop()
+            frame = call_stack.pop()
             try:
                 fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
             except OSError:
@@ -414,30 +381,13 @@ class SConsEnvironment(SCons.Environment.Base):
     #
 
     def Configure(self, *args, **kw):
-        if not SCons.Script.SConscript.sconscript_reading:
+        if not SCons.Script.sconscript_reading:
             raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
         kw['_depth'] = kw.get('_depth', 0) + 1
         return apply(SCons.Environment.Base.Configure, (self,)+args, kw)
 
     def Default(self, *targets):
-        global DefaultCalled
-        global DefaultTargets
-        DefaultCalled = 1
-        for t in targets:
-            if t is None:
-                # Delete the elements from the list in-place, don't
-                # reassign an empty list to DefaultTargets, so that the
-                # DEFAULT_TARGETS variable will still point to the
-                # same object we point to.
-                del DefaultTargets[:]
-                BuildTargets._clear()
-            elif isinstance(t, SCons.Node.Node):
-                DefaultTargets.append(t)
-                BuildTargets._add_Default([t])
-            else:
-                nodes = self.arg2nodes(t, self.fs.Entry)
-                DefaultTargets.extend(nodes)
-                BuildTargets._add_Default(nodes)
+        SCons.Script._Set_Default_Targets(self, targets)
 
     def EnsureSConsVersion(self, major, minor):
         """Exit abnormally if the SCons version is not late enough."""
@@ -470,25 +420,28 @@ class SConsEnvironment(SCons.Environment.Base):
 
     def GetOption(self, name):
         name = self.subst(name)
-        return SCons.Script.ssoptions.get(name)
+        return SCons.Script.Main.ssoptions.get(name)
 
     def Help(self, text):
         text = self.subst(text, raw=1)
-        HelpFunction(text)
+        SCons.Script.HelpFunction(text)
 
     def Import(self, *vars):
         try:
+            frame = call_stack[-1]
+            globals = frame.globals
+            exports = frame.exports
             for var in vars:
                 var = self.Split(var)
                 for v in var:
                     if v == '*':
-                        stack[-1].globals.update(global_exports)
-                        stack[-1].globals.update(stack[-1].exports)
+                        globals.update(global_exports)
+                        globals.update(exports)
                     else:
-                        if stack[-1].exports.has_key(v):
-                            stack[-1].globals[v] = stack[-1].exports[v]
+                        if exports.has_key(v):
+                            globals[v] = exports[v]
                         else:
-                            stack[-1].globals[v] = global_exports[v]
+                            globals[v] = global_exports[v]
         except KeyError,x:
             raise SCons.Errors.UserError, "Import of non-existent variable '%s'"%x
 
@@ -523,23 +476,34 @@ class SConsEnvironment(SCons.Environment.Base):
 
     def SetOption(self, name, value):
         name = self.subst(name)
-        SCons.Script.ssoptions.set(name, value)
+        SCons.Script.Main.ssoptions.set(name, value)
 
 #
 #
 #
 SCons.Environment.Environment = SConsEnvironment
 
-def Options(files=None, args=Arguments):
-    return SCons.Options.Options(files, args)
-
 def Configure(*args, **kw):
-    if not SCons.Script.SConscript.sconscript_reading:
+    if not SCons.Script.sconscript_reading:
         raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
     kw['_depth'] = 1
     return apply(SCons.SConf.SConf, args, kw)
 
+# It's very important that the DefaultEnvironmentCall() class stay in this
+# file, with the get_calling_namespaces() function, the compute_exports()
+# function, the Frame class and the SConsEnvironment.Export() method.
+# These things make up the calling stack leading up to the actual global
+# Export() or SConscript() call that the user issued.  We want to allow
+# users to export local variables that they define, like so:
+#
+#       def func():
+#           x = 1
+#           Export('x')
 #
+# To support this, the get_calling_namespaces() function assumes that
+# the *first* stack frame that's not from this file is the local frame
+# for the Export() or SConscript() call.
+
 _DefaultEnvironmentProxy = None
 
 def get_DefaultEnvironmentProxy():
@@ -565,86 +529,6 @@ class DefaultEnvironmentCall:
         method = getattr(proxy, self.method_name)
         return apply(method, args, kw)
 
-# The list of global functions to add to the SConscript name space
-# that end up calling corresponding methods or Builders in the
-# DefaultEnvironment().
-GlobalDefaultEnvironmentFunctions = [
-    # Methods from the SConsEnvironment class, above.
-    'Default',
-    'EnsurePythonVersion',
-    'EnsureSConsVersion',
-    'Exit',
-    'Export',
-    'GetLaunchDir',
-    'GetOption',
-    'Help',
-    'Import',
-    'SConscript',
-    'SConscriptChdir',
-    'SetOption',
-
-    # Methods from the Environment.Base class.
-    'AddPostAction',
-    'AddPreAction',
-    'Alias',
-    'AlwaysBuild',
-    'BuildDir',
-    'CacheDir',
-    'Clean',
-    'Command',
-    'Depends',
-    'Dir',
-    'Execute',
-    'File',
-    'FindFile',
-    'Flatten',
-    'GetBuildPath',
-    'Ignore',
-    'Install',
-    'InstallAs',
-    'Literal',
-    'Local',
-    'ParseDepends',
-    'Precious',
-    'Repository',
-    'SConsignFile',
-    'SideEffect',
-    'SourceCode',
-    'SourceSignatures',
-    'Split',
-    'TargetSignatures',
-    'Value',
-]
-
-GlobalDefaultBuilders = [
-    # Supported builders.
-    'CFile',
-    'CXXFile',
-    'DVI',
-    'Jar',
-    'Java',
-    'JavaH',
-    'Library',
-    'M4',
-    'MSVSProject',
-    'Object',
-    'PCH',
-    'PDF',
-    'PostScript',
-    'Program',
-    'RES',
-    'RMIC',
-    'SharedLibrary',
-    'SharedObject',
-    'StaticLibrary',
-    'StaticObject',
-    'Tar',
-    'TypeLibrary',
-    'Zip',
-]
-
-for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
-    GlobalDict[name] = DefaultEnvironmentCall(name)
 
 def BuildDefaultGlobals():
     """
@@ -652,45 +536,15 @@ def BuildDefaultGlobals():
     SConstruct and SConscript files.
     """
 
-    globals = {
-        # Global functions that don't get executed through the
-        # default Environment.
-        'Action'                : SCons.Action.Action,
-        'BoolOption'            : SCons.Options.BoolOption,
-        'Builder'               : SCons.Builder.Builder,
-        'Configure'             : Configure,
-        'EnumOption'            : SCons.Options.EnumOption,
-        'Environment'           : SCons.Environment.Environment,
-        'ListOption'            : SCons.Options.ListOption,
-        'Options'               : Options,
-        'PackageOption'         : SCons.Options.PackageOption,
-        'PathOption'            : SCons.Options.PathOption,
-        'Platform'              : SCons.Platform.Platform,
-        'Return'                : Return,
-        'Scanner'               : SCons.Scanner.Base,
-        'Tool'                  : SCons.Tool.Tool,
-        'WhereIs'               : SCons.Util.WhereIs,
-
-        # Action factories.
-        'Chmod'                 : SCons.Defaults.Chmod,
-        'Copy'                  : SCons.Defaults.Copy,
-        'Delete'                : SCons.Defaults.Delete,
-        'Mkdir'                 : SCons.Defaults.Mkdir,
-        'Move'                  : SCons.Defaults.Move,
-        'Touch'                 : SCons.Defaults.Touch,
-
-        # Other variables we provide.
-        'ARGUMENTS'             : Arguments,
-        'ARGLIST'               : ArgList,
-        'BUILD_TARGETS'         : BuildTargets,
-        'COMMAND_LINE_TARGETS'  : CommandLineTargets,
-        'DEFAULT_TARGETS'       : DefaultTargets,
-    }
-
-    # Functions we might still convert to Environment methods.
-    globals['CScan']             = SCons.Defaults.CScan
-    globals['DefaultEnvironment'] = SCons.Defaults.DefaultEnvironment
-
-    globals.update(GlobalDict)
-
-    return globals
+    global GlobalDict
+    if GlobalDict is None:
+        GlobalDict = {}
+
+        import SCons.Script
+        d = SCons.Script.__dict__
+        def not_a_module(m, d=d, mtype=type(SCons.Script)):
+             return type(d[m]) != mtype
+        for m in filter(not_a_module, dir(SCons.Script)):
+             GlobalDict[m] = d[m]
+
+    return GlobalDict.copy()
index 71c2f039f89376fbe1500aa092b432431de5184a..d6d49122e939557274580ec28f60584f320e6315 100644 (file)
@@ -39,1114 +39,209 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 import time
 start_time = time.time()
 
-import os
-import os.path
-import random
 import string
-import sys
-import traceback
+import UserList
 
-# Strip the script directory from sys.path() so on case-insensitive
-# (WIN32) systems Python doesn't think that the "scons" script is the
-# "SCons" package.  Replace it with our own version directory so, if
-# if they're there, we pick up the right version of the build engine
-# modules.
-#sys.path = [os.path.join(sys.prefix,
-#                         'lib',
-#                         'scons-%d' % SCons.__version__)] + sys.path[1:]
-
-import SCons.Debug
-import SCons.Defaults
+import SCons.Action
+import SCons.Builder
 import SCons.Environment
-import SCons.Errors
-import SCons.Job
-import SCons.Node
-import SCons.Node.FS
-from SCons.Optik import OptionParser, SUPPRESS_HELP, OptionValueError
-import SCons.Script.SConscript
-import SCons.Sig
-import SCons.Taskmaster
+import SCons.Options
+import SCons.Platform
+import SCons.Scanner
+import SCons.SConf
+import SCons.Tool
 import SCons.Util
-import SCons.Warnings
-
-#
-display = SCons.Util.display
-progress_display = SCons.Util.DisplayEngine()
-
-# Task control.
-#
-class BuildTask(SCons.Taskmaster.Task):
-    """An SCons build task."""
-    def display(self, message):
-        display('scons: ' + message)
-
-    def execute(self):
-        target = self.targets[0]
-        if target.get_state() == SCons.Node.up_to_date:
-            if self.top and target.has_builder():
-                display("scons: `%s' is up to date." % str(self.node))
-        elif target.has_builder() and not hasattr(target.builder, 'status'):
-            if print_time:
-                start_time = time.time()
-            SCons.Taskmaster.Task.execute(self)
-            if print_time:
-                finish_time = time.time()
-                global command_time
-                command_time = command_time+finish_time-start_time
-                print "Command execution time: %f seconds"%(finish_time-start_time)
-
-    def do_failed(self, status=2):
-        global exit_status
-        if ignore_errors:
-            SCons.Taskmaster.Task.executed(self)
-        elif keep_going_on_error:
-            SCons.Taskmaster.Task.fail_continue(self)
-            exit_status = status
-        else:
-            SCons.Taskmaster.Task.fail_stop(self)
-            exit_status = status
-            
-    def executed(self):
-        t = self.targets[0]
-        if self.top and not t.has_builder() and not t.side_effect:
-            if not t.exists():
-                sys.stderr.write("scons: *** Do not know how to make target `%s'." % t)
-                if not keep_going_on_error:
-                    sys.stderr.write("  Stop.")
-                sys.stderr.write("\n")
-                self.do_failed()
-            else:
-                print "scons: Nothing to be done for `%s'." % t
-                SCons.Taskmaster.Task.executed(self)
-        else:
-            SCons.Taskmaster.Task.executed(self)
-
-    def failed(self):
-        # Handle the failure of a build task.  The primary purpose here
-        # is to display the various types of Errors and Exceptions
-        # appropriately.
-        status = 2
-        exc_info = self.exc_info()
-        try:
-            t, e, tb = exc_info
-        except ValueError:
-            t, e = exc_info
-            tb = None
-        if t is None:
-            # The Taskmaster didn't record an exception for this Task;
-            # see if the sys module has one.
-            t, e = sys.exc_info()[:2]
-
-        if t == SCons.Errors.BuildError:
-            fname = e.node
-            if SCons.Util.is_List(e.node):
-                fname = string.join(map(str, e.node), ', ')
-            sys.stderr.write("scons: *** [%s] %s\n" % (fname, e.errstr))
-            if e.errstr == 'Exception':
-                traceback.print_exception(e.args[0], e.args[1], e.args[2])
-        elif t == SCons.Errors.ExplicitExit:
-            status = e.status
-            sys.stderr.write("scons: *** [%s] Explicit exit, status %s\n" % (e.node, e.status))
-        else:
-            if e is None:
-                e = t
-            s = str(e)
-            if t == SCons.Errors.StopError and not keep_going_on_error:
-                s = s + '  Stop.'
-            sys.stderr.write("scons: *** %s\n" % s)
-
-            if tb and print_stacktrace:
-                sys.stderr.write("scons: internal stack trace:\n")
-                traceback.print_tb(tb, file=sys.stderr)
-
-        self.do_failed(status)
-
-        self.exc_clear()
-
-    def postprocess(self):
-        if self.top:
-            t = self.targets[0]
-            if print_tree:
-                print
-                SCons.Util.print_tree(t, get_all_children)
-            if print_stree:
-                print
-                SCons.Util.print_tree(t, get_all_children, showtags=2)
-            if print_dtree:
-                print
-                SCons.Util.print_tree(t, get_derived_children)
-            if print_includes:
-                tree = t.render_include_tree()
-                if tree:
-                    print
-                    print tree
-        SCons.Taskmaster.Task.postprocess(self)
-
-    def make_ready(self):
-        """Make a task ready for execution"""
-        SCons.Taskmaster.Task.make_ready(self)
-        if self.out_of_date and print_explanations:
-            explanation = self.out_of_date[0].explain()
-            if explanation:
-                sys.stdout.write("scons: " + explanation)
-
-class CleanTask(SCons.Taskmaster.Task):
-    """An SCons clean task."""
-    def show(self):
-        if (self.targets[0].has_builder() or self.targets[0].side_effect) \
-           and not os.path.isdir(str(self.targets[0])):
-            display("Removed " + str(self.targets[0]))
-        if SCons.Environment.CleanTargets.has_key(self.targets[0]):
-            files = SCons.Environment.CleanTargets[self.targets[0]]
-            for f in files:
-                SCons.Util.fs_delete(str(f), 0)
-
-    def remove(self):
-        if self.targets[0].has_builder() or self.targets[0].side_effect:
-            for t in self.targets:
-                try:
-                    removed = t.remove()
-                except OSError, e:
-                    print "scons: Could not remove '%s':" % str(t), e.strerror
-                else:
-                    if removed:
-                        display("Removed " + str(t))
-        if SCons.Environment.CleanTargets.has_key(self.targets[0]):
-            files = SCons.Environment.CleanTargets[self.targets[0]]
-            for f in files:
-                SCons.Util.fs_delete(str(f))
-
-    execute = remove
-
-    # Have the taskmaster arrange to "execute" all of the targets, because
-    # we'll figure out ourselves (in remove() or show() above) whether
-    # anything really needs to be done.
-    make_ready = SCons.Taskmaster.Task.make_ready_all
-
-    def prepare(self):
-        pass
-
-class QuestionTask(SCons.Taskmaster.Task):
-    """An SCons task for the -q (question) option."""
-    def prepare(self):
-        pass
-    
-    def execute(self):
-        if self.targets[0].get_state() != SCons.Node.up_to_date:
-            global exit_status
-            exit_status = 1
-            self.tm.stop()
-
-    def executed(self):
-        pass
-
-# Global variables
-
-keep_going_on_error = 0
-print_count = 0
-print_dtree = 0
-print_explanations = 0
-print_includes = 0
-print_objects = 0
-print_stacktrace = 0
-print_stree = 0
-print_time = 0
-print_tree = 0
-memory_stats = None
-ignore_errors = 0
-sconscript_time = 0
-command_time = 0
-exit_status = 0 # exit status, assume success by default
-profiling = 0
-repositories = []
-num_jobs = 1 # this is modifed by SConscript.SetJobs()
-
-# utility functions
-
-def get_all_children(node): return node.all_children()
-
-def get_derived_children(node):
-    children = node.all_children(None)
-    return filter(lambda x: x.has_builder(), children)
-
-def _scons_syntax_error(e):
-    """Handle syntax errors. Print out a message and show where the error
-    occurred.
-    """
-    etype, value, tb = sys.exc_info()
-    lines = traceback.format_exception_only(etype, value)
-    for line in lines:
-        sys.stderr.write(line+'\n')
-    sys.exit(2)
-
-def find_deepest_user_frame(tb):
-    """
-    Find the deepest stack frame that is not part of SCons.
-
-    Input is a "pre-processed" stack trace in the form
-    returned by traceback.extract_tb() or traceback.extract_stack()
-    """
-    
-    tb.reverse()
-
-    # find the deepest traceback frame that is not part
-    # of SCons:
-    for frame in tb:
-        filename = frame[0]
-        if string.find(filename, os.sep+'SCons'+os.sep) == -1:
-            return frame
-    return tb[0]
-
-def _scons_user_error(e):
-    """Handle user errors. Print out a message and a description of the
-    error, along with the line number and routine where it occured. 
-    The file and line number will be the deepest stack frame that is
-    not part of SCons itself.
-    """
-    etype, value, tb = sys.exc_info()
-    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
-    sys.stderr.write("\nscons: *** %s\n" % value)
-    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
-    sys.exit(2)
-
-def _scons_user_warning(e):
-    """Handle user warnings. Print out a message and a description of
-    the warning, along with the line number and routine where it occured.
-    The file and line number will be the deepest stack frame that is
-    not part of SCons itself.
-    """
-    etype, value, tb = sys.exc_info()
-    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
-    sys.stderr.write("\nscons: warning: %s\n" % e)
-    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
-
-def _scons_internal_warning(e):
-    """Slightly different from _scons_user_warning in that we use the
-    *current call stack* rather than sys.exc_info() to get our stack trace.
-    This is used by the warnings framework to print warnings."""
-    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack())
-    sys.stderr.write("\nscons: warning: %s\n" % e[0])
-    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
-
-def _scons_internal_error():
-    """Handle all errors but user errors. Print out a message telling
-    the user what to do in this case and print a normal trace.
-    """
-    print 'internal error'
-    traceback.print_exc()
-    sys.exit(2)
-
-def _varargs(option, parser):
-    value = None
-    if parser.rargs:
-        arg = parser.rargs[0]
-        if arg[0] != "-":
-            value = arg
-            del parser.rargs[0]
-    return value
-
-def _setup_warn(arg):
-    """The --warn option.  An argument to this option
-    should be of the form <warning-class> or no-<warning-class>.
-    The warning class is munged in order to get an actual class
-    name from the SCons.Warnings module to enable or disable.
-    The supplied <warning-class> is split on hyphens, each element
-    is captialized, then smushed back together.  Then the string
-    "SCons.Warnings." is added to the front and "Warning" is added
-    to the back to get the fully qualified class name.
-
-    For example, --warn=deprecated will enable the
-    SCons.Warnings.DeprecatedWarning class.
-
-    --warn=no-dependency will disable the
-    SCons.Warnings.DependencyWarning class.
-
-    As a special case, --warn=all and --warn=no-all
-    will enable or disable (respectively) the base
-    class of all warnings, which is SCons.Warning.Warning."""
-
-    elems = string.split(string.lower(arg), '-')
-    enable = 1
-    if elems[0] == 'no':
-        enable = 0
-        del elems[0]
-
-    if len(elems) == 1 and elems[0] == 'all':
-        class_name = "Warning"
-    else:
-        def _capitalize(s):
-            if s[:5] == "scons":
-                return "SCons" + s[5:]
-            else:
-                return string.capitalize(s)
-        class_name = string.join(map(_capitalize, elems), '') + "Warning"
-    try:
-        clazz = getattr(SCons.Warnings, class_name)
-    except AttributeError:
-        sys.stderr.write("No warning type: '%s'\n" % arg)
-    else:
-        if enable:
-            SCons.Warnings.enableWarningClass(clazz)
-        else:
-            SCons.Warnings.suppressWarningClass(clazz)
-
-def _SConstruct_exists(dirname=''):
-    """This function checks that an SConstruct file exists in a directory.
-    If so, it returns the path of the file. By default, it checks the
-    current directory.
-    """
-    global repositories
-    for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
-        sfile = os.path.join(dirname, file)
-        if os.path.isfile(sfile):
-            return sfile
-        if not os.path.isabs(sfile):
-            for rep in repositories:
-                if os.path.isfile(os.path.join(rep, sfile)):
-                    return sfile
-    return None
-
-def _set_globals(options):
-    global repositories, keep_going_on_error, ignore_errors
-    global print_count, print_dtree
-    global print_explanations, print_includes
-    global print_objects, print_stacktrace, print_stree
-    global print_time, print_tree
-    global memory_outf, memory_stats
-
-    if options.repository:
-        repositories.extend(options.repository)
-    keep_going_on_error = options.keep_going
-    try:
-        if options.debug:
-            if options.debug == "count":
-                print_count = 1
-            elif options.debug == "dtree":
-                print_dtree = 1
-            elif options.debug == "explain":
-                print_explanations = 1
-            elif options.debug == "findlibs":
-                SCons.Scanner.Prog.print_find_libs = "findlibs"
-            elif options.debug == "includes":
-                print_includes = 1
-            elif options.debug == "memory":
-                memory_stats = []
-                memory_outf = sys.stdout
-            elif options.debug == "objects":
-                print_objects = 1
-            elif options.debug == "presub":
-                SCons.Action.print_actions_presub = 1
-            elif options.debug == "stacktrace":
-                print_stacktrace = 1
-            elif options.debug == "stree":
-                print_stree = 1
-            elif options.debug == "time":
-                print_time = 1
-            elif options.debug == "tree":
-                print_tree = 1
-    except AttributeError:
-        pass
-    ignore_errors = options.ignore_errors
-
-def _create_path(plist):
-    path = '.'
-    for d in plist:
-        if os.path.isabs(d):
-            path = d
-        else:
-            path = path + '/' + d
-    return path
-
-
-class OptParser(OptionParser):
-    def __init__(self):
-        import __main__
-        import SCons
-        parts = ["SCons by Steven Knight et al.:\n"]
-        try:
-            parts.append("\tscript: v%s.%s, %s, by %s on %s\n" % (__main__.__version__,
-                                                                  __main__.__build__,
-                                                                  __main__.__date__,
-                                                                  __main__.__developer__,
-                                                                  __main__.__buildsys__))
-        except KeyboardInterrupt:
-            raise
-        except:
-            # On win32 there is no scons.py, so there is no __main__.__version__,
-            # hence there is no script version.
-            pass 
-        parts.append("\tengine: v%s.%s, %s, by %s on %s\n" % (SCons.__version__,
-                                                              SCons.__build__,
-                                                              SCons.__date__,
-                                                              SCons.__developer__,
-                                                              SCons.__buildsys__))
-        parts.append("__COPYRIGHT__")
-        OptionParser.__init__(self, version=string.join(parts, ''),
-                              usage="usage: scons [OPTION] [TARGET] ...")
-
-        # options ignored for compatibility
-        def opt_ignore(option, opt, value, parser):
-            sys.stderr.write("Warning:  ignoring %s option\n" % opt)
-        self.add_option("-b", "-m", "-S", "-t", "--no-keep-going", "--stop",
-                        "--touch", action="callback", callback=opt_ignore,
-                        help="Ignored for compatibility.")
-
-        self.add_option('-c', '--clean', '--remove', action="store_true",
-                        dest="clean",
-                        help="Remove specified targets and dependencies.")
-
-        self.add_option('-C', '--directory', type="string", action = "append",
-                        metavar="DIR",
-                        help="Change to DIR before doing anything.")
-
-        self.add_option('--cache-disable', '--no-cache',
-                        action="store_true", dest='cache_disable', default=0,
-                        help="Do not retrieve built targets from CacheDir.")
-
-        self.add_option('--cache-force', '--cache-populate',
-                        action="store_true", dest='cache_force', default=0,
-                        help="Copy already-built targets into the CacheDir.")
-
-        self.add_option('--cache-show',
-                        action="store_true", dest='cache_show', default=0,
-                        help="Print build actions for files from CacheDir.")
-
-        config_options = ["auto", "force" ,"cache"]
-
-        def opt_config(option, opt, value, parser, c_options=config_options):
-            if value in c_options:
-                parser.values.config = value
-            else:
-                raise OptionValueError("Warning:  %s is not a valid config type" % value)
-        self.add_option('--config', action="callback", type="string",
-                        callback=opt_config, nargs=1, dest="config",
-                        metavar="MODE", default="auto",
-                        help="Controls Configure subsystem: "
-                             "%s." % string.join(config_options, ", "))
-
-        def opt_not_yet(option, opt, value, parser):
-            sys.stderr.write("Warning:  the %s option is not yet implemented\n" % opt)
-            sys.exit(0)
-        self.add_option('-d', action="callback",
-                        callback=opt_not_yet,
-                        help = "Print file dependency information.")
-        
-        self.add_option('-D', action="store_const", const=2, dest="climb_up",
-                        help="Search up directory tree for SConstruct,       "
-                             "build all Default() targets.")
-
-        debug_options = ["count", "dtree", "explain", "findlibs",
-                         "includes", "memory", "objects",
-                         "pdb", "presub", "stacktrace", "stree",
-                         "time", "tree"]
-
-        def opt_debug(option, opt, value, parser, debug_options=debug_options):
-            if value in debug_options:
-                parser.values.debug = value
-            else:
-                raise OptionValueError("Warning:  %s is not a valid debug type" % value)
-        self.add_option('--debug', action="callback", type="string",
-                        callback=opt_debug, nargs=1, dest="debug",
-                        metavar="TYPE",
-                        help="Print various types of debugging information: "
-                             "%s." % string.join(debug_options, ", "))
-
-        def opt_duplicate(option, opt, value, parser):
-            if not value in SCons.Node.FS.Valid_Duplicates:
-                raise OptionValueError("`%s' is not a valid duplication style." % value)
-            parser.values.duplicate = value
-            # Set the duplicate style right away so it can affect linking
-            # of SConscript files.
-            SCons.Node.FS.set_duplicate(value)
-        self.add_option('--duplicate', action="callback", type="string",
-                        callback=opt_duplicate, nargs=1, dest="duplicate",
-                        help="Set the preferred duplication methods. Must be one of "
-                        + string.join(SCons.Node.FS.Valid_Duplicates, ", "))
-
-        self.add_option('-f', '--file', '--makefile', '--sconstruct',
-                        action="append", nargs=1,
-                        help="Read FILE as the top-level SConstruct file.")
-
-        self.add_option('-h', '--help', action="store_true", default=0,
-                        dest="help_msg",
-                        help="Print defined help message, or this one.")
-
-        self.add_option("-H", "--help-options",
-                        action="help",
-                        help="Print this message and exit.")
-
-        self.add_option('-i', '--ignore-errors', action="store_true",
-                        default=0, dest='ignore_errors',
-                        help="Ignore errors from build actions.")
-
-        self.add_option('-I', '--include-dir', action="append",
-                        dest='include_dir', metavar="DIR",
-                        help="Search DIR for imported Python modules.")
-
-        self.add_option('--implicit-cache', action="store_true",
-                        dest='implicit_cache',
-                        help="Cache implicit dependencies")
-
-        self.add_option('--implicit-deps-changed', action="store_true",
-                        default=0, dest='implicit_deps_changed',
-                        help="Ignore cached implicit dependencies.")
-        self.add_option('--implicit-deps-unchanged', action="store_true",
-                        default=0, dest='implicit_deps_unchanged',
-                        help="Ignore changes in implicit dependencies.")
-
-        def opt_j(option, opt, value, parser):
-            value = int(value)
-            parser.values.num_jobs = value
-        self.add_option('-j', '--jobs', action="callback", type="int",
-                        callback=opt_j, metavar="N",
-                        help="Allow N jobs at once.")
-
-        self.add_option('-k', '--keep-going', action="store_true", default=0,
-                        dest='keep_going',
-                        help="Keep going when a target can't be made.")
-
-        self.add_option('--max-drift', type="int", action="store",
-                        dest='max_drift', metavar="N",
-                        help="Set maximum system clock drift to N seconds.")
-
-        self.add_option('-n', '--no-exec', '--just-print', '--dry-run',
-                        '--recon', action="store_true", dest='noexec',
-                        default=0, help="Don't build; just print commands.")
-
-        def opt_profile(option, opt, value, parser):
-            global profiling
-            if not profiling:
-                profiling = 1
-                import profile
-                profile.run('SCons.Script.main()', value)
-                sys.exit(exit_status)
-        self.add_option('--profile', nargs=1, action="callback",
-                        callback=opt_profile, type="string", dest="profile",
-                        metavar="FILE",
-                        help="Profile SCons and put results in FILE.")
-
-        self.add_option('-q', '--question', action="store_true", default=0,
-                        help="Don't build; exit status says if up to date.")
-
-        self.add_option('-Q', dest='no_progress', action="store_true",
-                        default=0,
-                        help="Suppress \"Reading/Building\" progress messages.")
-
-        self.add_option('--random', dest="random", action="store_true",
-                        default=0, help="Build dependencies in random order.")
-
-        self.add_option('-s', '--silent', '--quiet', action="store_true",
-                        default=0, help="Don't print commands.")
-
-        self.add_option('-u', '--up', '--search-up', action="store_const",
-                        dest="climb_up", default=0, const=1,
-                        help="Search up directory tree for SConstruct,       "
-                             "build targets at or below current directory.")
-        self.add_option('-U', action="store_const", dest="climb_up",
-                        default=0, const=3,
-                        help="Search up directory tree for SConstruct,       "
-                             "build Default() targets from local SConscript.")
-
-        self.add_option("-v", "--version",
-                        action="version",
-                        help="Print the SCons version number and exit.")
-
-        self.add_option('--warn', '--warning', nargs=1, action="store",
-                        metavar="WARNING-SPEC",
-                        help="Enable or disable warnings.")
-
-        self.add_option('-Y', '--repository', nargs=1, action="append",
-                        help="Search REPOSITORY for source and target files.")
-
-        self.add_option('-e', '--environment-overrides', action="callback",
-                        callback=opt_not_yet,
-                        # help="Environment variables override makefiles."
-                        help=SUPPRESS_HELP)
-        self.add_option('-l', '--load-average', '--max-load', action="callback",
-                        callback=opt_not_yet, type="int", dest="load_average",
-                        # action="store",
-                        # help="Don't start multiple jobs unless load is below "
-                        #      "LOAD-AVERAGE."
-                        # type="int",
-                        help=SUPPRESS_HELP)
-        self.add_option('--list-derived', action="callback",
-                        callback=opt_not_yet,
-                        # help="Don't build; list files that would be built."
-                        help=SUPPRESS_HELP)
-        self.add_option('--list-actions', action="callback",
-                        callback=opt_not_yet,
-                        # help="Don't build; list files and build actions."
-                        help=SUPPRESS_HELP)
-        self.add_option('--list-where', action="callback",
-                        callback=opt_not_yet,
-                        # help="Don't build; list files and where defined."
-                        help=SUPPRESS_HELP)
-        self.add_option('-o', '--old-file', '--assume-old', action="callback",
-                        callback=opt_not_yet, type="string", dest="old_file",
-                        # help = "Consider FILE to be old; don't rebuild it."
-                        help=SUPPRESS_HELP)
-        self.add_option('--override', action="callback", dest="override",
-                        callback=opt_not_yet, type="string",
-                        # help="Override variables as specified in FILE."
-                        help=SUPPRESS_HELP)
-        self.add_option('-p', action="callback",
-                        callback=opt_not_yet,
-                        # help="Print internal environments/objects."
-                        help=SUPPRESS_HELP)
-        self.add_option('-r', '-R', '--no-builtin-rules',
-                        '--no-builtin-variables', action="callback",
-                        callback=opt_not_yet,
-                        # help="Clear default environments and variables."
-                        help=SUPPRESS_HELP)
-        self.add_option('-w', '--print-directory', action="callback",
-                        callback=opt_not_yet,
-                        # help="Print the current directory."
-                        help=SUPPRESS_HELP)
-        self.add_option('--no-print-directory', action="callback",
-                        callback=opt_not_yet,
-                        # help="Turn off -w, even if it was turned on implicitly."
-                        help=SUPPRESS_HELP)
-        self.add_option('--write-filenames', action="callback",
-                        callback=opt_not_yet, type="string", dest="write_filenames",
-                        # help="Write all filenames examined into FILE."
-                        help=SUPPRESS_HELP)
-        self.add_option('-W', '--what-if', '--new-file', '--assume-new',
-                        dest="new_file",
-                        action="callback", callback=opt_not_yet, type="string",
-                        # help="Consider FILE to be changed."
-                        help=SUPPRESS_HELP)
-        self.add_option('--warn-undefined-variables', action="callback",
-                        callback=opt_not_yet,
-                        # help="Warn when an undefined variable is referenced."
-                        help=SUPPRESS_HELP)
-
-    def parse_args(self, args=None, values=None):
-        opt, arglist = OptionParser.parse_args(self, args, values)
-        if opt.implicit_deps_changed or opt.implicit_deps_unchanged:
-            opt.implicit_cache = 1
-        return opt, arglist
-
-class SConscriptSettableOptions:
-    """This class wraps an OptParser instance and provides
-    uniform access to options that can be either set on the command
-    line or from a SConscript file. A value specified on the command
-    line always overrides a value set in a SConscript file.
-    Not all command line options are SConscript settable, and the ones
-    that are must be explicitly added to settable dictionary and optionally
-    validated and coerced in the set() method."""
-    
-    def __init__(self, options):
-        self.options = options
-
-        # This dictionary stores the defaults for all the SConscript
-        # settable options, as well as indicating which options
-        # are SConscript settable. 
-        self.settable = {'num_jobs':1,
-                         'max_drift':SCons.Sig.default_max_drift,
-                         'implicit_cache':0,
-                         'clean':0,
-                         'duplicate':'hard-soft-copy'}
-
-    def get(self, name):
-        if not self.settable.has_key(name):
-            raise SCons.Error.UserError, "This option is not settable from a SConscript file: %s"%name
-        if hasattr(self.options, name) and getattr(self.options, name) is not None:
-            return getattr(self.options, name)
-        else:
-            return self.settable[name]
-
-    def set(self, name, value):
-        if not self.settable.has_key(name):
-            raise SCons.Error.UserError, "This option is not settable from a SConscript file: %s"%name
-
-        if name == 'num_jobs':
-            try:
-                value = int(value)
-                if value < 1:
-                    raise ValueError
-            except ValueError:
-                raise SCons.Errors.UserError, "A positive integer is required: %s"%repr(value)
-        elif name == 'max_drift':
-            try:
-                value = int(value)
-            except ValueError:
-                raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
-        elif name == 'duplicate':
-            try:
-                value = str(value)
-            except ValueError:
-                raise SCons.Errors.UserError, "A string is required: %s"%repr(value)
-            if not value in SCons.Node.FS.Valid_Duplicates:
-                raise SCons.Errors.UserError, "Not a valid duplication style: %s" % value
-            # Set the duplicate stye right away so it can affect linking
-            # of SConscript files.
-            SCons.Node.FS.set_duplicate(value)
-
-        self.settable[name] = value
-    
-
-def _main(args, parser):
-    targets = []
-    fs = SCons.Node.FS.default_fs
-
-    # Enable deprecated warnings by default.
-    SCons.Warnings._warningOut = _scons_internal_warning
-    SCons.Warnings.enableWarningClass(SCons.Warnings.CorruptSConsignWarning)
-    SCons.Warnings.enableWarningClass(SCons.Warnings.DeprecatedWarning)
-    SCons.Warnings.enableWarningClass(SCons.Warnings.DuplicateEnvironmentWarning)
-    SCons.Warnings.enableWarningClass(SCons.Warnings.MissingSConscriptWarning)
-    SCons.Warnings.enableWarningClass(SCons.Warnings.NoParallelSupportWarning)
-    # This is good for newbies, and hopefully most everyone else too.
-    SCons.Warnings.enableWarningClass(SCons.Warnings.MisleadingKeywordsWarning)
-
-    global ssoptions
-    ssoptions = SConscriptSettableOptions(options)
-
-    _set_globals(options)
-    SCons.Node.implicit_cache = options.implicit_cache
-    SCons.Node.implicit_deps_changed = options.implicit_deps_changed
-    SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
-    if options.warn:
-        _setup_warn(options.warn)
-    if options.noexec:
-        SCons.SConf.dryrun = 1
-        SCons.Action.execute_actions = None
-        CleanTask.execute = CleanTask.show
-    if options.question:
-        SCons.SConf.dryrun = 1
-    SCons.SConf.SetCacheMode(options.config)
-    SCons.SConf.SetProgressDisplay(progress_display)
-
-    if options.no_progress or options.silent:
-        progress_display.set_mode(0)
-    if options.silent:
-        display.set_mode(0)
-    if options.silent:
-        SCons.Action.print_actions = None
-    if options.cache_disable:
-        def disable(self): pass
-        fs.CacheDir = disable
-    if options.cache_force:
-        fs.cache_force = 1
-    if options.cache_show:
-        fs.cache_show = 1
-    if options.directory:
-        cdir = _create_path(options.directory)
-        try:
-            os.chdir(cdir)
-        except OSError:
-            sys.stderr.write("Could not change directory to %s\n" % cdir)
-
-    xmit_args = []
-    for a in args:
-        if '=' in a:
-            xmit_args.append(a)
-        else:
-            targets.append(a)
-    SCons.Script.SConscript._scons_add_args(xmit_args)
-    SCons.Script.SConscript._scons_add_targets(targets)
-
-    target_top = None
-    if options.climb_up:
-        target_top = '.'  # directory to prepend to targets
-        script_dir = os.getcwd()  # location of script
-        while script_dir and not _SConstruct_exists(script_dir):
-            script_dir, last_part = os.path.split(script_dir)
-            if last_part:
-                target_top = os.path.join(last_part, target_top)
-            else:
-                script_dir = ''
-        if script_dir:
-            display("scons: Entering directory `%s'" % script_dir)
-            os.chdir(script_dir)
-        else:
-            raise SCons.Errors.UserError, "No SConstruct file found."
-
-    fs.set_toplevel_dir(os.getcwd())
-
-    scripts = []
-    if options.file:
-        scripts.extend(options.file)
-    if not scripts:
-        sfile = _SConstruct_exists()
-        if sfile:
-            scripts.append(sfile)
-
-    if options.help_msg:
-        if not scripts:
-            # There's no SConstruct, but they specified -h.
-            # Give them the options usage now, before we fail
-            # trying to read a non-existent SConstruct file.
-            parser.print_help()
-            sys.exit(0)
-        SCons.Script.SConscript.print_help = 1
-
-    if not scripts:
-        raise SCons.Errors.UserError, "No SConstruct file found."
-
-    if scripts[0] == "-":
-        d = fs.getcwd()
-    else:
-        d = fs.File(scripts[0]).dir
-    fs.set_SConstruct_dir(d)
-
-    class Unbuffered:
-        def __init__(self, file):
-            self.file = file
-        def write(self, arg):
-            self.file.write(arg)
-            self.file.flush()
-        def __getattr__(self, attr):
-            return getattr(self.file, attr)
-
-    sys.stdout = Unbuffered(sys.stdout)
-
-    if options.include_dir:
-        sys.path = options.include_dir + sys.path
-
-    global repositories
-    for rep in repositories:
-        fs.Repository(rep)
-
-    if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
-
-    progress_display("scons: Reading SConscript files ...")
-
-    start_time = time.time()
-    try:
-        for script in scripts:
-            SCons.Script.SConscript._SConscript(fs, script)
-    except SCons.Errors.StopError, e:
-        # We had problems reading an SConscript file, such as it
-        # couldn't be copied in to the BuildDir.  Since we're just
-        # reading SConscript files and haven't started building
-        # things yet, stop regardless of whether they used -i or -k
-        # or anything else.
-        global exit_status
-        sys.stderr.write("scons: *** %s  Stop.\n" % e)
-        exit_status = 2
-        sys.exit(exit_status)
-    global sconscript_time
-    sconscript_time = time.time() - start_time
-    SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
-    progress_display("scons: done reading SConscript files.")
-
-    # Tell the Node.FS subsystem that we're all done reading the
-    # SConscript files and calling Repository() and BuildDir() and the
-    # like, so it can go ahead and start memoizing the string values of
-    # file system nodes.
-    SCons.Node.FS.save_strings(1)
-
-    if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
-
-    fs.chdir(fs.Top)
-
-    if options.help_msg:
-        if SCons.Script.SConscript.help_text is None:
-            # They specified -h, but there was no Help() inside the
-            # SConscript files.  Give them the options usage.
-            parser.print_help(sys.stdout)
-        else:
-            print SCons.Script.SConscript.help_text
-            print "Use scons -H for help about command-line options."
-        sys.exit(0)
-
-    # Now that we've read the SConscripts we can set the options
-    # that are SConscript settable:
-    SCons.Node.implicit_cache = ssoptions.get('implicit_cache')
-    SCons.Node.FS.set_duplicate(ssoptions.get('duplicate'))
-
-    lookup_top = None
-    if targets:
-        # They specified targets on the command line, so if they
-        # used -u, -U or -D, we have to look up targets relative
-        # to the top, but we build whatever they specified.
-        if target_top:
-            lookup_top = fs.Dir(target_top)
-            target_top = None
-    else:
-        # There are no targets specified on the command line,
-        # so if they used -u, -U or -D, we may have to restrict
-        # what actually gets built.
-        d = None
-        if target_top:
-            if options.climb_up == 1:
-                # -u, local directory and below
-                target_top = fs.Dir(target_top)
-                lookup_top = target_top
-            elif options.climb_up == 2:
-                # -D, all Default() targets
-                target_top = None
-                lookup_top = None
-            elif options.climb_up == 3:
-                # -U, local SConscript Default() targets
-                target_top = fs.Dir(target_top)
-                def check_dir(x, target_top=target_top):
-                    if hasattr(x, 'cwd') and not x.cwd is None:
-                        cwd = x.cwd.srcnode()
-                        return cwd == target_top
-                    else:
-                        # x doesn't have a cwd, so it's either not a target,
-                        # or not a file, so go ahead and keep it as a default
-                        # target and let the engine sort it out:
-                        return 1                
-                d = filter(check_dir, SCons.Script.SConscript.DefaultTargets)
-                SCons.Script.SConscript.DefaultTargets[:] = d
-                target_top = None
-                lookup_top = None
-
-        if SCons.Script.SConscript.DefaultCalled:
-            targets = SCons.Script.SConscript.DefaultTargets
-        else:
-            if d is None:
-                d = [fs.Dir('.')]
-            targets = d
+import SCons.Defaults
 
+import Main
 
-    if not targets:
-        sys.stderr.write("scons: *** No targets specified and no Default() targets found.  Stop.\n")
-        sys.exit(2)
+main                    = Main.main
 
-    def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
-        if isinstance(x, SCons.Node.Node):
-            node = x
-        else:
-            node = SCons.Node.Alias.default_ans.lookup(x)
-            if node is None:
-                node = fs.Entry(x, directory=ltop, create=1)
-        if ttop and not node.is_under(ttop):
-            if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
-                node = ttop
-            else:
-                node = None
-        return node
+import SConscript
+_SConscript = SConscript
 
-    nodes = filter(lambda x: x is not None, map(Entry, targets))
+call_stack              = _SConscript.call_stack
 
-    task_class = BuildTask     # default action is to build targets
-    opening_message = "Building targets ..."
-    closing_message = "done building targets."
-    if keep_going_on_error:
-        failure_message = "done building targets (errors occurred during build)."
-    else:
-        failure_message = "building terminated because of errors."
-    if options.question:
-        task_class = QuestionTask
-    try:
-        if ssoptions.get('clean'):
-            task_class = CleanTask
-            opening_message = "Cleaning targets ..."
-            closing_message = "done cleaning targets."
-            if keep_going_on_error:
-                closing_message = "done cleaning targets (errors occurred during clean)."
-            else:
-                failure_message = "cleaning terminated because of errors."
-    except AttributeError:
+#
+Action                  = SCons.Action.Action
+BoolOption              = SCons.Options.BoolOption
+Builder                 = SCons.Builder.Builder
+Configure               = _SConscript.Configure
+EnumOption              = SCons.Options.EnumOption
+Environment             = SCons.Environment.Environment
+ListOption              = SCons.Options.ListOption
+PackageOption           = SCons.Options.PackageOption
+PathOption              = SCons.Options.PathOption
+Platform                = SCons.Platform.Platform
+Return                  = _SConscript.Return
+Scanner                 = SCons.Scanner.Base
+Tool                    = SCons.Tool.Tool
+WhereIs                 = SCons.Util.WhereIs
+
+# Action factories.
+Chmod                   = SCons.Defaults.Chmod
+Copy                    = SCons.Defaults.Copy
+Delete                  = SCons.Defaults.Delete
+Mkdir                   = SCons.Defaults.Mkdir
+Move                    = SCons.Defaults.Move
+Touch                   = SCons.Defaults.Touch
+
+# Functions we might still convert to Environment methods.
+CScan                   = SCons.Defaults.CScan
+DefaultEnvironment      = SCons.Defaults.DefaultEnvironment
+
+# Other variables we provide.
+class TargetList(UserList.UserList):
+    def _do_nothing(self, *args, **kw):
         pass
-
-    SCons.Environment.CalculatorArgs['max_drift'] = ssoptions.get('max_drift')
-
-    if options.random:
-        def order(dependencies):
-            """Randomize the dependencies."""
-            # This is cribbed from the implementation of
-            # random.shuffle() in Python 2.X.
-            d = dependencies
-            for i in xrange(len(d)-1, 0, -1):
-                j = int(random.random() * (i+1))
-                d[i], d[j] = d[j], d[i]
-            return d
-    else:
-        def order(dependencies):
-            """Leave the order of dependencies alone."""
-            return dependencies
-
-    progress_display("scons: " + opening_message)
-    taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order)
-
-    nj = ssoptions.get('num_jobs')
-    jobs = SCons.Job.Jobs(nj, taskmaster)
-    if nj > 1 and jobs.num_jobs == 1:
-        msg = "parallel builds are unsupported by this version of Python;\n" + \
-              "\tignoring -j or num_jobs option.\n"
-        SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
-
-    if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
-
-    try:
-        jobs.run()
-    finally:
-        if exit_status:
-            progress_display("scons: " + failure_message)
+    def _add_Default(self, list):
+        self.extend(list)
+    def _clear(self):
+        del self[:]
+
+ARGUMENTS               = {}
+ARGLIST                 = []
+BUILD_TARGETS           = TargetList()
+COMMAND_LINE_TARGETS    = []
+DEFAULT_TARGETS         = []
+
+def _Add_Arguments(alist):
+    for arg in alist:
+        a, b = string.split(arg, '=', 1)
+        ARGUMENTS[a] = b
+        ARGLIST.append((a, b))
+
+def _Add_Targets(tlist):
+    if tlist:
+        COMMAND_LINE_TARGETS.extend(tlist)
+        BUILD_TARGETS.extend(tlist)
+        BUILD_TARGETS._add_Default = BUILD_TARGETS._do_nothing
+        BUILD_TARGETS._clear = BUILD_TARGETS._do_nothing
+
+def _Set_Default_Targets_Has_Been_Called(d, fs):
+    return DEFAULT_TARGETS
+
+def _Set_Default_Targets_Has_Not_Been_Called(d, fs):
+    if d is None:
+        d = [fs.Dir('.')]
+    return d
+
+_Get_Default_Targets = _Set_Default_Targets_Has_Not_Been_Called
+
+def _Set_Default_Targets(env, tlist):
+    global DEFAULT_TARGETS
+    global _Get_Default_Targets
+    _Get_Default_Targets = _Set_Default_Targets_Has_Been_Called
+    for t in tlist:
+        if t is None:
+            # Delete the elements from the list in-place, don't
+            # reassign an empty list to DEFAULT_TARGETS, so that the
+            # variables will still point to the same object we point to.
+            del DEFAULT_TARGETS[:]
+            BUILD_TARGETS._clear()
+        elif isinstance(t, SCons.Node.Node):
+            DEFAULT_TARGETS.append(t)
+            BUILD_TARGETS._add_Default([t])
         else:
-            progress_display("scons: " + closing_message)
-        if not options.noexec:
-            SCons.SConsign.write()
-
-    if not memory_stats is None:
-        memory_stats.append(SCons.Debug.memory())
-        when = [
-            'before SConscript files',
-            'after SConscript files',
-            'before building',
-            'after building',
-        ]
-        for i in xrange(len(when)):
-            memory_outf.write('Memory %s:  %d\n' % (when[i], memory_stats[i]))
-
-    if print_count:
-        SCons.Debug.countLoggedInstances('*')
+            nodes = env.arg2nodes(t, env.fs.Entry)
+            DEFAULT_TARGETS.extend(nodes)
+            BUILD_TARGETS._add_Default(nodes)
 
-    if print_objects:
-        SCons.Debug.listLoggedInstances('*')
-        #SCons.Debug.dumpLoggedInstances('*')
+#
+help_text = None
 
-def _exec_main():
-    all_args = sys.argv[1:]
-    try:
-        all_args = string.split(os.environ['SCONSFLAGS']) + all_args
-    except KeyError:
-            # it's OK if there's no SCONSFLAGS
-            pass
-    parser = OptParser()
-    global options
-    options, args = parser.parse_args(all_args)
-    if options.debug == "pdb":
-        import pdb
-        pdb.Pdb().runcall(_main, args, parser)
+def HelpFunction(text):
+    global help_text
+    if SCons.Script.help_text is None:
+        SCons.Script.help_text = text
     else:
-        _main(args, parser)
-
-def main():
-    global exit_status
-    
-    try:
-       _exec_main()
-    except SystemExit, s:
-        if s:
-            exit_status = s
-    except KeyboardInterrupt:
-        print "Build interrupted."
-        sys.exit(2)
-    except SyntaxError, e:
-        _scons_syntax_error(e)
-    except SCons.Errors.InternalError:
-        _scons_internal_error()
-    except SCons.Errors.UserError, e:
-        _scons_user_error(e)
-    except:
-        # An exception here is likely a builtin Python exception Python
-        # code in an SConscript file.  Show them precisely what the
-        # problem was and where it happened.
-        SCons.Script.SConscript.SConscript_exception()
-        sys.exit(2)
+        help_text = help_text + text
 
-    if print_time:
-        total_time = time.time()-start_time
-        scons_time = total_time-sconscript_time-command_time
-        print "Total build time: %f seconds"%total_time
-        print "Total SConscript file execution time: %f seconds"%sconscript_time
-        print "Total SCons execution time: %f seconds"%scons_time
-        print "Total command execution time: %f seconds"%command_time
+#
+# Will be set to 1 if we are reading a SConscript.
+sconscript_reading = 0
 
-    sys.exit(exit_status)
+#
+def Options(files=None, args=ARGUMENTS):
+    return SCons.Options.Options(files, args)
+
+# The list of global functions to add to the SConscript name space
+# that end up calling corresponding methods or Builders in the
+# DefaultEnvironment().
+GlobalDefaultEnvironmentFunctions = [
+    # Methods from the SConsEnvironment class, above.
+    'Default',
+    'EnsurePythonVersion',
+    'EnsureSConsVersion',
+    'Exit',
+    'Export',
+    'GetLaunchDir',
+    'GetOption',
+    'Help',
+    'Import',
+    'SConscript',
+    'SConscriptChdir',
+    'SetOption',
+
+    # Methods from the Environment.Base class.
+    'AddPostAction',
+    'AddPreAction',
+    'Alias',
+    'AlwaysBuild',
+    'BuildDir',
+    'CacheDir',
+    'Clean',
+    'Command',
+    'Depends',
+    'Dir',
+    'Execute',
+    'File',
+    'FindFile',
+    'Flatten',
+    'GetBuildPath',
+    'Ignore',
+    'Install',
+    'InstallAs',
+    'Literal',
+    'Local',
+    'ParseDepends',
+    'Precious',
+    'Repository',
+    'SConsignFile',
+    'SideEffect',
+    'SourceCode',
+    'SourceSignatures',
+    'Split',
+    'TargetSignatures',
+    'Value',
+]
+
+GlobalDefaultBuilders = [
+    # Supported builders.
+    'CFile',
+    'CXXFile',
+    'DVI',
+    'Jar',
+    'Java',
+    'JavaH',
+    'Library',
+    'M4',
+    'MSVSProject',
+    'Object',
+    'PCH',
+    'PDF',
+    'PostScript',
+    'Program',
+    'RES',
+    'RMIC',
+    'SharedLibrary',
+    'SharedObject',
+    'StaticLibrary',
+    'StaticObject',
+    'Tar',
+    'TypeLibrary',
+    'Zip',
+]
+
+for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
+    exec "%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))
index 98258c23c9217e95e49621e90c298740b5bb975d..559a679482e1659618dbd9aef8a7d538a8259e4c 100644 (file)
@@ -178,6 +178,16 @@ def generate(env):
     except (SCons.Util.RegError, SCons.Errors.InternalError):
         pass
 
+    # For most platforms, a loadable module is the same as a shared
+    # library.  Platforms which are different can override these, but
+    # setting them the same means that LoadableModule works everywhere.
+    SCons.Tool.createLoadableModuleBuilder(env)
+    env['LDMODULE'] = '$SHLINK'
+    env['LDMODULEPREFIX'] = '$SHLIBPREFIX' 
+    env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' 
+    env['LDMODULEFLAGS'] = '$SHLINKFLAGS'
+    env['LDMODULECOM'] = '$SHLINKCOM'
+
 def exists(env):
     if SCons.Tool.msvs.is_msvs_installed():
         # there's at least one version of MSVS installed.
index a173c3efa9bb2242343a3611efd2b0a63d762c25..04e09f5ad3321ade98b4e53d6033da85ae0dc0f9 100644 (file)
@@ -45,7 +45,7 @@ import types
 import SCons.Builder
 import SCons.Node.FS
 import SCons.Platform.win32
-import SCons.Script.SConscript
+import SCons.Script
 import SCons.Util
 import SCons.Warnings
 
@@ -1052,10 +1052,12 @@ def projectEmitter(target, source, env):
     dspfile = SCons.Node.FS.default_fs.File(target[0]).srcnode()
     dswfile = SCons.Node.FS.default_fs.File(SCons.Util.splitext(str(dspfile))[0] + env.subst('$MSVSSOLUTIONSUFFIX'))
 
+    # XXX Need to find a way to abstract this; the build engine
+    # shouldn't depend on anything in SCons.Script.
+    stack = SCons.Script.call_stack
     if not source:
-        source = [SCons.Script.SConscript.stack[-1].sconscript.srcnode()]
-
-    source[0].attributes.sconstruct = SCons.Script.SConscript.stack[0].sconscript
+        source = [stack[-1].sconscript.srcnode()]
+    source[0].attributes.sconstruct = stack[0].sconscript
 
     bdswpath = SCons.Util.splitext(str(target[0]))[0] + env.subst('$MSVSSOLUTIONSUFFIX')
     bdswfile = SCons.Node.FS.default_fs.File(bdswpath)
index ffb89944029b9db4c09a2a05277826f433f784bb..9a28c87a388985b884b92d2bba3af145262fd235 100644 (file)
@@ -152,7 +152,7 @@ def exists_test(node):
     node.is_derived()
     node.is_pseudo_derived()
     import SCons.Script
-    if SCons.Script.options.noexec:
+    if SCons.Script.Main.options.noexec:
         if (before,via_node,after) != (False,False,False):
             import sys
             sys.stderr.write('BuildDir exits() populated during dryrun!\n')
diff --git a/test/Script-import.py b/test/Script-import.py
new file mode 100644 (file)
index 0000000..90052a5
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# __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.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that a module that we import into an SConscript file
+can itself easily import the global SCons variables.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import m1
+""")
+
+test.write("m1.py", """\
+from SCons.Script import *
+SConscript('SConscript')
+""")
+
+test.write('SConscript', """\
+import m2
+""")
+
+test.write("m2.py", """\
+from SCons.Script import *
+Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
+""")
+
+test.write("file.in", "file.in\n")
+
+test.run(arguments = '.')
+
+test.must_match("file.out", "file.in\n")
+
+test.pass_test()
index 5a6e473493ffa373266a911066fc524768285681..412b8ced11095364a337b7d79d0af6b30c9a7a00 100644 (file)
@@ -43,15 +43,19 @@ test.fail_test(string.find(test.stdout(), 'Copyright') == -1 and
 stats = pstats.Stats(scons_prof)
 stats.sort_stats('time')
 
-sys.stdout = StringIO.StringIO()
+try:
+    save_stdout = sys.stdout
+    sys.stdout = StringIO.StringIO()
 
-stats.strip_dirs().print_stats()
+    stats.strip_dirs().print_stats()
 
-s = sys.stdout.getvalue()
+    s = sys.stdout.getvalue()
+finally:
+    sys.stdout = save_stdout
 
-test.fail_test(string.find(s, '__init__.py') == -1)
+test.fail_test(string.find(s, 'Main.py') == -1)
 test.fail_test(string.find(s, 'print_version') == -1)
-test.fail_test(string.find(s, 'SCons.Script.main()') == -1)
+test.fail_test(string.find(s, 'SCons.Script.Main.main()') == -1)
 test.fail_test(string.find(s, 'option_parser.py') == -1)
 
 
@@ -71,11 +75,10 @@ stats.strip_dirs().print_stats()
 
 s = sys.stdout.getvalue()
 
-test.fail_test(string.find(s, '__init__.py') == -1)
+test.fail_test(string.find(s, 'Main.py') == -1)
 test.fail_test(string.find(s, 'print_version') == -1)
-test.fail_test(string.find(s, 'SCons.Script.main()') == -1)
+test.fail_test(string.find(s, 'SCons.Script.Main.main()') == -1)
 test.fail_test(string.find(s, 'option_parser.py') == -1)
  
 
 test.pass_test()
-