Commits

Steven Knight  committed 9228c1b

Turn more global functions into Environment methods. (clone of 0.92.C121)

  • Participants
  • Parent commits c220cad

Comments (0)

Files changed (13)

File doc/man/scons.1

 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
 .RI EnsurePythonVersion( major ", " minor )
+.TP
+.RI env.EnsurePythonVersion( major ", " minor )
 Ensure that the Python version is at least 
 .IR major . minor . 
 This function will
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
 .RI EnsureSConsVersion( major ", " minor )
+.TP
+.RI env.EnsureSConsVersion( major ", " minor )
 Ensure that the SCons version is at least 
 .IR major . minor . 
 This function will
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
 .RI Exit([ value ])
+.TP
+.RI env.Exit([ value ])
 This tells
 .B scons
 to exit immediately
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
 .RI Export( vars )
+.TP
+.RI env.Export( vars )
 This tells 
 .B scons
 to export a list of variables from the current
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .\".TP
 .\".RI GetLaunchDir( XXX )
+.\".TP
+.\".RI env.GetLaunchDir( XXX )
 .\"XXX
 
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
 .RI GetOption( name )
+.TP
+.RI env.GetOption( name )
 This function provides a way to query a select subset of the scons command line
 options from a SConscript file. See 
 .IR SetOption () 
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
 .RI Help( text )
+.TP
+.RI env.Help( text )
 This specifies help text to be printed if the 
 .B -h 
 argument is given to
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP 
 .RI Import( vars )
+.TP 
+.RI env.Import( vars )
 This tells 
 .B scons
 to import a list of variables into the current SConscript file. This
 .TP
 .RI SConscript( scripts ", [" exports ", " build_dir ", " src_dir ", " duplicate ])
 .TP
+.RI env.SConscript( scripts ", [" exports ", " build_dir ", " src_dir ", " duplicate ])
+.TP
 .RI SConscript(dirs= subdirs ", [name=" script ", " exports ", " build_dir ", " src_dir ", " duplicate ])
+.TP
+.RI env.SConscript(dirs= subdirs ", [name=" script ", " exports ", " build_dir ", " src_dir ", " duplicate ])
 This tells
 .B scons
 to execute
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
 .RI SetOption( name ", " value )
+.TP
+.RI env.SetOption( name ", " value )
 This function provides a way to set a select subset of the scons command
 line options from a SConscript file. The options supported are: clean which
 cooresponds to -c, --clean, and --remove; implicit_cache which corresponds

File src/CHANGES.txt

 
   - Add Environment-method versions of the following global functions:
     AddPreAction(), AddPostAction(), BuildDir(), CacheDir(), Clean(),
-    Default(), FindFile(), GetBuildPath(), Local(), Repository(),
-    SConsignFile(), SourceSignatures(), TargetSignatures().
+    Default(), EnsurePythonVersion(), EnsureSConsVersion(), Exit(),
+    Export(), FindFile(), GetBuildPath(), GetOption(), Help(),
+    Import(), Local(), Repository(), SConsignFile(), SetOption(),
+    SourceSignatures(), TargetSignatures().
 
   - Add the following global functions that correspond to the same-named
     Environment methods:  AlwaysBuild(), Command(), Depends(), Ignore(),
   - Rearrange the man page to show construction environment methods and
     global functions in the same list, and to explain the difference.
 
+  - Rename the Environment.Environment class to Enviroment.Base.
+    Allow the wrapping interface to extend an Environment by using its own
+    subclass of Environment.Base and setting a new Environment.Environment
+    variable as the calling entry point.
+
   From Bram Moolenaar:
 
   - Split the non-SCons-specific functionality from SConf.py to a new,

File src/engine/SCons/Environment.py

         for i, v in dict.items():
             self.__setitem__(i, v)
 
-class Environment:
+class Base:
     """Base class for construction Environments.  These are
     the primary objects used to communicate dependency and
     construction information to the build engine.
             self._build_signature = 0
         else:
             raise SCons.Errors.UserError, "Unknown target signature type '%s'"%type
+
+# The entry point that will be used by the external world
+# to refer to a construction environment.  This allows the wrapper
+# interface to extend a construction environment for its own purposes
+# by subclassing SCons.Environment.Base and then assigning the
+# class to SCons.Environment.Environment.
+
+Environment = Base

File src/engine/SCons/EnvironmentTests.py

         env.TargetSignatures('$C')
         assert env._build_signature == 0, env._build_signature
 
+    def test_Environment(type):
+        """Test setting Environment variable to an Environment.Base subclass"""
+        class MyEnv(SCons.Environment.Base):
+            def xxx(self, string):
+                return self.subst(string)
+
+        SCons.Environment.Environment = MyEnv
+
+        env = SCons.Environment.Environment(FOO = 'foo')
+
+        f = env.subst('$FOO')
+        assert f == 'foo', f
+
+        f = env.xxx('$FOO')
+        assert f == 'foo', f
+
 
 if __name__ == "__main__":
     suite = unittest.makeSuite(EnvironmentTestCase, 'test_')

File src/engine/SCons/Script/SConscript.py

 
     return (files, exports)
 
-def SConscript(*ls, **kw):
+def _SConscript(fs, *ls, **kw):
     files, exports = GetSConscriptFilenames(ls, kw)
 
-    default_fs = SCons.Node.FS.default_fs
-    top = default_fs.Top
-    sd = default_fs.SConstruct_dir.rdir()
+    top = fs.Top
+    sd = fs.SConstruct_dir.rdir()
 
     # evaluate each SConscript file
     results = []
                 if isinstance(fn, SCons.Node.Node):
                     f = fn
                 else:
-                    f = default_fs.File(str(fn))
+                    f = fs.File(str(fn))
                 _file_ = None
 
                 # Change directory to the top of the source
                 # tree to make sure the os's cwd and the cwd of
-                # SCons.Node.FS.default_fs match so we can open the
-                # SConscript.
-                default_fs.chdir(top, change_os_dir=1)
+                # fs match so we can open the SConscript.
+                fs.chdir(top, change_os_dir=1)
                 if f.rexists():
                     _file_ = open(f.rstr(), "r")
                 elif f.has_src_builder():
                     # where the SConstruct and SConscript files might be
                     # in different Repositories.  For now, cross that
                     # bridge when someone comes to it.
-                    ldir = default_fs.Dir(f.dir.get_path(sd))
+                    ldir = fs.Dir(f.dir.get_path(sd))
                     try:
-                        default_fs.chdir(ldir, change_os_dir=sconscript_chdir)
+                        fs.chdir(ldir, change_os_dir=sconscript_chdir)
                     except OSError:
                         # There was no local directory, so we should be
                         # able to chdir to the Repository directory.
                         # Note that we do this directly, not through
-                        # default_fs.chdir(), because we still need to
+                        # fs.chdir(), because we still need to
                         # interpret the stuff within the SConscript file
                         # relative to where we are logically.
-                        default_fs.chdir(ldir, change_os_dir=0)
+                        fs.chdir(ldir, change_os_dir=0)
                         os.chdir(f.rfile().dir.get_abspath())
 
                     # Append the SConscript directory to the beginning
             sys.path = old_sys_path
             frame = stack.pop()
             try:
-                default_fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
+                fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
             except OSError:
                 # There was no local directory, so chdir to the
                 # Repository directory.  Like above, we do this
                 # directly.
-                default_fs.chdir(frame.prev_dir, change_os_dir=0)
+                fs.chdir(frame.prev_dir, change_os_dir=0)
                 os.chdir(frame.prev_dir.rdir().get_abspath())
 
             results.append(frame.retval)
 # leave this disabled until we find a more efficient mechanism.
 #SCons.Node.Annotate = annotate
 
-def Help(text):
-    HelpFunction(text)
+class SConsEnvironment(SCons.Environment.Base):
+    """An Environment subclass that contains all of the methods that
+    are particular to the wrapper SCons interface and which aren't
+    (or shouldn't be) part of the build engine itself.
+    """
 
-def Export(*vars):
-    for var in vars:
-        global_exports.update(compute_exports(var))
+    #
+    # Private functions of an SConsEnvironment.
+    #
 
-def Import(*vars):
-    try:
+    def _check_version(self, major, minor, version_string):
+        """Return 0 if 'major' and 'minor' are greater than the version
+        in 'version_string', and 1 otherwise."""
+        try:
+            v_major, v_minor, v_micro, release, serial = sys.version_info
+        except AttributeError:
+            version = string.split(string.split(version_string, ' ')[0], '.')
+            v_major = int(version[0])
+            v_minor = int(re.match('\d+', version[1]).group())
+        if major > v_major or (major == v_major and minor > v_minor):
+            return 0
+        else:
+            return 1
+
+    #
+    # Public functions of an SConsEnvironment.  These get
+    # entry points in the global name space so they can be called
+    # as global functions.
+    #
+
+    def EnsureSConsVersion(self, major, minor):
+        """Exit abnormally if the SCons version is not late enough."""
+        if not self._check_version(major,minor,SCons.__version__):
+            print "SCons %d.%d or greater required, but you have SCons %s" %(major,minor,SCons.__version__)
+            sys.exit(2)
+
+    def EnsurePythonVersion(self, major, minor):
+        """Exit abnormally if the Python version is not late enough."""
+        if not self._check_version(major,minor,sys.version):
+            v = string.split(sys.version, " ", 1)[0]
+            print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v)
+            sys.exit(2)
+
+    def Exit(self, value=0):
+        sys.exit(value)
+
+    def Export(self, *vars):
         for var in vars:
-            var = SCons.Util.Split(var)
-            for v in var:
-                if v == '*':
-                    stack[-1].globals.update(global_exports)
-                    stack[-1].globals.update(stack[-1].exports)
-                else:
-                    if stack[-1].exports.has_key(v):
-                        stack[-1].globals[v] = stack[-1].exports[v]
+            global_exports.update(compute_exports(var))
+
+    def GetLaunchDir(self):
+        global launch_dir
+        return launch_dir
+
+    def GetOption(self, name):
+        name = self.subst(name)
+        return SCons.Script.ssoptions.get(name)
+
+    def Help(self, text):
+        text = self.subst(text, raw=1)
+        HelpFunction(text)
+
+    def Import(self, *vars):
+        try:
+            for var in vars:
+                var = SCons.Util.Split(var)
+                for v in var:
+                    if v == '*':
+                        stack[-1].globals.update(global_exports)
+                        stack[-1].globals.update(stack[-1].exports)
                     else:
-                        stack[-1].globals[v] = global_exports[v]
-    except KeyError,x:
-        raise SCons.Errors.UserError, "Import of non-existant variable '%s'"%x
+                        if stack[-1].exports.has_key(v):
+                            stack[-1].globals[v] = stack[-1].exports[v]
+                        else:
+                            stack[-1].globals[v] = global_exports[v]
+        except KeyError,x:
+            raise SCons.Errors.UserError, "Import of non-existant variable '%s'"%x
 
-def GetLaunchDir():
-    return launch_dir
+    def SConscript(self, *ls, **kw):
+        ls = map(lambda l, self=self: self.subst(l), ls)
+        return apply(_SConscript, [self.fs,] + ls, kw)
+
+    def SetOption(self, name, value):
+        name = self.subst(name)
+        SCons.Script.ssoptions.set(name, value)
+
+#
+#
+#
+SCons.Environment.Environment = SConsEnvironment
 
 def SetBuildSignatureType(type):
     SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
     def __init__(self, files=None, args=arguments):
         SCons.Options.Options.__init__(self, files, args)
 
-def CheckVersion(major, minor, version_string):
-    """Return 0 if 'major' and 'minor' are greater than the version
-    in 'version_string', and 1 otherwise."""
-    try:
-        v_major, v_minor, v_micro, release, serial = sys.version_info
-    except AttributeError:
-        version = string.split(string.split(version_string, ' ')[0], '.')
-        v_major = int(version[0])
-        v_minor = int(re.match('\d+', version[1]).group())
-    if major > v_major or (major == v_major and minor > v_minor):
-        return 0
-    else:
-        return 1
-
-def EnsureSConsVersion(major, minor):
-    """Exit abnormally if the SCons version is not late enough."""
-    if not CheckVersion(major,minor,SCons.__version__):
-        print "SCons %d.%d or greater required, but you have SCons %s" %(major,minor,SCons.__version__)
-        sys.exit(2)
-
-def EnsurePythonVersion(major, minor):
-    """Exit abnormally if the Python version is not late enough."""
-    if not CheckVersion(major,minor,sys.version):
-	v = string.split(sys.version, " ", 1)[0]
-        print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v)
-        sys.exit(2)
-
 def GetJobs():
     SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
                         "The GetJobs() function has been deprecated;\n" +\
                         "\tuse SetOption('num_jobs', num) instead.")
     SetOption('num_jobs', num)
 
-def Exit(value=0):
-    sys.exit(value)
-
 
 def Alias(name):
     alias = SCons.Node.Alias.default_ans.lookup(name)
         alias = SCons.Node.Alias.default_ans.Alias(name)
     return alias
 
-def SetOption(name, value):
-    SCons.Script.ssoptions.set(name, value)
-
-def GetOption(name):
-    return SCons.Script.ssoptions.get(name)
-
 #
 _DefaultEnvironmentProxy = None
 
     globals['Configure']         = SCons.SConf.SConf
     globals['CScan']             = SCons.Defaults.CScan
     globals['DefaultEnvironment'] = SCons.Defaults.DefaultEnvironment
-    globals['EnsurePythonVersion'] = EnsurePythonVersion
-    globals['EnsureSConsVersion'] = EnsureSConsVersion
     globals['Environment']       = SCons.Environment.Environment
-    globals['Exit']              = Exit
-    globals['Export']            = Export
     globals['GetCommandHandler'] = SCons.Action.GetCommandHandler
-    globals['GetJobs']           = GetJobs
-    globals['GetLaunchDir']      = GetLaunchDir
-    globals['GetOption']         = GetOption    
-    globals['Help']              = Help
-    globals['Import']            = Import
     globals['Literal']           = SCons.Util.Literal
     globals['Options']           = Options
     globals['ParseConfig']       = SCons.Util.ParseConfig
     globals['Platform']          = SCons.Platform.Platform
     globals['Return']            = Return
-    globals['SConscript']        = SConscript
     globals['SConscriptChdir']   = SConscriptChdir
     globals['Scanner']           = SCons.Scanner.Base
-    globals['SetBuildSignatureType'] = SetBuildSignatureType
     globals['SetCommandHandler'] = SCons.Action.SetCommandHandler
-    globals['SetContentSignatureType'] = SetContentSignatureType
-    globals['SetJobs']           = SetJobs
-    globals['SetOption']         = SetOption
     globals['Split']             = SCons.Util.Split
     globals['Tool']              = SCons.Tool.Tool
     globals['Value']             = SCons.Node.Python.Value
     globals['WhereIs']           = SCons.Util.WhereIs
 
+    # Deprecated functions, leave this here for now.
+    globals['GetJobs']           = GetJobs
+    globals['SetBuildSignatureType'] = SetBuildSignatureType
+    globals['SetContentSignatureType'] = SetContentSignatureType
+    globals['SetJobs']           = SetJobs
+
     class DefaultEnvironmentCall:
         """A class that implements "global function" calls of
         Environment methods by fetching the specified method from the
         'TargetSignatures',
     ]
 
-    for name in EnvironmentMethods:
+    SConsEnvironmentMethods = [
+        'EnsurePythonVersion',
+        'EnsureSConsVersion',
+        'Exit',
+        'Export',
+        'GetLaunchDir',
+        'GetOption',
+        'Help',
+        'Import',
+        'SConscript',
+        'SetOption',
+    ]
+
+    for name in EnvironmentMethods + SConsEnvironmentMethods:
         globals[name] = DefaultEnvironmentCall(name)
 
     return globals

File src/engine/SCons/Script/__init__.py

 
 def _main(args, parser):
     targets = []
+    fs = SCons.Node.FS.default_fs
 
     # Enable deprecated warnings by default.
     SCons.Warnings._warningOut = _scons_internal_warning
         SCons.Action.print_actions = None
     if options.cache_disable:
         def disable(self): pass
-        SCons.Node.FS.default_fs.CacheDir = disable
+        fs.CacheDir = disable
     if options.cache_force:
-        SCons.Node.FS.default_fs.cache_force = 1
+        fs.cache_force = 1
     if options.cache_show:
-        SCons.Node.FS.default_fs.cache_show = 1
+        fs.cache_show = 1
     if options.directory:
         cdir = _create_path(options.directory)
         try:
         else:
             raise SCons.Errors.UserError, "No SConstruct file found."
 
-    SCons.Node.FS.default_fs.set_toplevel_dir(os.getcwd())
+    fs.set_toplevel_dir(os.getcwd())
 
     scripts = []
     if options.file:
         raise SCons.Errors.UserError, "No SConstruct file found."
 
     if scripts[0] == "-":
-        d = SCons.Node.FS.default_fs.getcwd()
+        d = fs.getcwd()
     else:
-        d = SCons.Node.FS.default_fs.File(scripts[0]).dir
-    SCons.Node.FS.default_fs.set_SConstruct_dir(d)
+        d = fs.File(scripts[0]).dir
+    fs.set_SConstruct_dir(d)
 
     class Unbuffered:
         def __init__(self, file):
 
     global repositories
     for rep in repositories:
-        SCons.Node.FS.default_fs.Repository(rep)
+        fs.Repository(rep)
 
     progress_display("scons: Reading SConscript files ...")
     try:
         start_time = time.time()
         try:
             for script in scripts:
-                SCons.Script.SConscript.SConscript(script)
+                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
         sys.exit(0)
     progress_display("scons: done reading SConscript files.")
 
-    SCons.Node.FS.default_fs.chdir(SCons.Node.FS.default_fs.Top)
+    fs.chdir(fs.Top)
 
     if options.help_msg:
         # They specified -h, but there was no Help() inside the
         # 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 = SCons.Node.FS.default_fs.Dir(target_top)
+            lookup_top = fs.Dir(target_top)
             target_top = None
     else:
         # There are no targets specified on the command line,
         if target_top:
             if options.climb_up == 1:
                 # -u, local directory and below
-                target_top = SCons.Node.FS.default_fs.Dir(target_top)
+                target_top = fs.Dir(target_top)
                 lookup_top = target_top
             elif options.climb_up == 2:
                 # -D, all Default() targets
                 lookup_top = None
             elif options.climb_up == 3:
                 # -U, local SConscript Default() targets
-                target_top = SCons.Node.FS.default_fs.Dir(target_top)
+                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()
 
         targets = SCons.Environment.DefaultTargets
         if targets is None:
-            targets = [SCons.Node.FS.default_fs.Dir('.')]
+            targets = [fs.Dir('.')]
 
     if not targets:
         sys.stderr.write("scons: *** No targets specified and no Default() targets found.  Stop.\n")
         else:
             node = SCons.Node.Alias.default_ans.lookup(x)
             if node is None:
-                node = SCons.Node.FS.default_fs.Entry(x,
-                                                      directory = ltop,
-                                                      create = 1)
+                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

File test/EnsureVersion.py

 else:
     test.write('SConstruct', """
 import sys
+env = Environment()
 EnsurePythonVersion(0,0)
-EnsureSConsVersion(0,0)
+env.EnsureSConsVersion(0,0)
 sys.exit(0)
 """)
 
 
     test.write('SConstruct', """
 import sys
-EnsurePythonVersion(0,0)
+env = Environment()
+env.EnsurePythonVersion(0,0)
 EnsureSConsVersion(2000,0)
 sys.exit(0)
 """)

File test/Exit.py

 subdir_foo_out = os.path.join('subdir', 'foo.out')
 
 test.write('SConstruct', """\
-print "SConstruct"
+print "SConstruct, Exit()"
 Exit()
 """)
 
 test.run(stdout = """\
 scons: Reading SConscript files ...
-SConstruct
+SConstruct, Exit()
+""")
+
+test.write('SConstruct', """\
+env = Environment()
+print "SConstruct, env.Exit()"
+env.Exit()
+""")
+
+test.run(stdout = """\
+scons: Reading SConscript files ...
+SConstruct, env.Exit()
 """)
 
 test.write('SConstruct', """\

File test/GetSetOption.py

+#!/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 getting and setting options through global functions
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+env = Environment()
+option_list = ['clean', 'implicit_cache', 'max_drift', 'num_jobs']
+val = 1
+for option in option_list:
+    SetOption(option, val)
+    o = env.GetOption(option)
+    assert o == val, "%s %s != %s" % (option, o, val)
+    val = val + 1
+for option in option_list:
+    env.SetOption(option, val)
+    o = GetOption(option)
+    assert o == val, "%s %s != %s" % (option, o, val)
+    val = val + 1
+""")
+
+test.run(arguments = '.')
+
+test.pass_test()

File test/Help.py

 
 test.run(arguments = '-h', stdout = expect)
 
+test.write('SConstruct', r"""
+env = Environment(MORE='more', HELP='help')
+env.Help("\nEven $MORE\n$HELP text!\n")
+""")
+
+expect = """scons: Reading SConscript files ...
+scons: done reading SConscript files.
+
+Even more
+help text!
+
+Use scons -H for help about command-line options.
+"""
+
+test.run(arguments = '-h', stdout = expect)
+
 test.pass_test()

File test/SConscript.py

          stdout = test.wrap_stdout(read_str = "`white space/SConscript'\n",
                                    build_str = "scons: `.' is up to date.\n"))
 
+# Test calling SConscript through a construction environment.
+test.subdir('sub')
+test.write("SConstruct", """\
+env = Environment(SUBDIR='sub')
+print "SConstruct"
+x = 'xxx'
+env.Export("x")
+env.SConscript('$SUBDIR/SConscript')
+""")
+
+test.write(['sub', 'SConscript'], """\
+env = Environment()
+env.Import("x")
+print "sub/SConscript"
+print "x =", x
+""")
+
+test.run(arguments = ".",
+         stdout = test.wrap_stdout(read_str = "SConstruct\nsub/SConscript\nx = xxx\n",
+                                   build_str = "scons: `.' is up to date.\n"))
+
 test.pass_test()

File test/option--U.py

 test.write(['sub3', 'baz.in'], "sub3/baz.in\n")
 test.write('xxx.in', "xxx.in\n")
 
-test.write('SConscript', """assert GetLaunchDir() == r'%s'"""%test.workpath('sub1'))
+test.write('SConscript', """assert GetLaunchDir() == r'%s'\n"""%test.workpath('sub1'))
 test.run(arguments = '-U foo.out', chdir = 'sub1')
 
 test.fail_test(not os.path.exists(test.workpath('sub1', 'foo.out')))
 
 test.unlink(['sub1', 'foo.out'])
 
-test.write('SConscript', """assert GetLaunchDir() == r'%s'"""%test.workpath('sub1'))
+test.write('SConscript', """\
+env = Environment()
+assert env.GetLaunchDir() == r'%s'
+"""%test.workpath('sub1'))
 test.run(arguments = '-U',
          chdir = 'sub1',
          stderr = "scons: *** No targets specified and no Default() targets found.  Stop.\n",

File test/scan-once.py

 import string
 import re
 import SCons.Environment
-import SCons.Script.SConscript
 
 def Subdirs(env, dirlist):
     for file in _subconf_list(dirlist):
-        SCons.Script.SConscript.SConscript(file, "env")
+        env.SConscript(file, "env")
 
 def _subconf_list(dirlist):
     return map(lambda x: os.path.join(x, "SConscript"), string.split(dirlist))