Give the global functions corresponding Environment methods.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 8 Sep 2003 04:01:32 +0000 (04:01 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 8 Sep 2003 04:01:32 +0000 (04:01 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@790 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/SCons/Environment.py
src/engine/SCons/EnvironmentTests.py
src/engine/SCons/Script/SConscript.py
src/engine/SCons/Script/__init__.py
test/Default.py
test/FindFile.py
test/Repository/Local.py
test/pre-post-actions.py

index 490975d585a1237c9256a805dae75c5aade611a9..95696c99c029cfc03ba266dfd3c60b05e6e925e5 100644 (file)
@@ -891,6 +891,7 @@ variable after the Environment is constructed will not cause the tools to
 be redetected.
 
 SCons supports the following tool specifications out of the box:
+
 .ES
 386asm
 aixc++
@@ -1089,6 +1090,7 @@ provides the following builders:
 Builds a static object file
 from one or more C, C++, or Fortran source files.
 Source files must have one of the following extensions:
+
 .ES
   .asm    assembly language file
   .ASM    assembly language file
@@ -1424,6 +1426,7 @@ env.M4(target = 'foo.c', source = 'foo.c.m4')
 .IP Jar
 Builds a Java archive (.jar) file
 from a source tree of .class files.
+
 .ES
 env.Jar(target = 'foo.jar', source = 'classes')
 .EE
@@ -1678,6 +1681,32 @@ method of a construction environment (see below).
 .SS Other Construction Environment Methods
 Additional construction environment methods include:
 
+.TP 
+.RI AddPostAction( target ", " action )
+Arranges for the specified
+.I action
+to be performed
+after the specified
+.I target
+has been built.
+The specified action(s) may be
+an Action object, or anything that
+can be converted into an Action object
+(see below).
+
+.TP 
+.RI AddPreAction( target ", " action )
+Arranges for the specified
+.I action
+to be performed
+before the specified
+.I target
+is built.
+The specified action(s) may be
+an Action object, or anything that
+can be converted into an Action object
+(see below).
+
 .TP
 .RI Alias( alias ", " targets )
 Creates a phony target that
@@ -1696,6 +1725,24 @@ env.Alias('install', ['/usr/local/bin', '/usr/local/lib'])
 env.Alias('install', ['/usr/local/man'])
 .EE
 
+.TP
+.RI AlwaysBuild( target ", ...)"
+Marks each given
+.I target
+so that it is always assumed to be out of date,
+and will always be rebuilt if needed.
+Note, however, that
+.BR AlwaysBuild ()
+does not add its target(s) to the default target list,
+so the targets will only be built
+if they are specified on the command line,
+or are a dependent of a target specified on the command line--but
+they will
+.I always
+be built if so specified.
+Multiple targets can be passed in to a single call to
+.BR AlwaysBuild ().
+
 .TP
 .RI Append( key = val ", [...])"
 Appends the specified keyword arguments
@@ -1716,36 +1763,6 @@ and the lists are added together.
 env.Append(CCFLAGS = ' -g', FOO = ['foo.yyy'])
 .EE
 
-.TP
-.RI PrependENVPath( name ", " newpath ", [" envname ", " sep ])
-This appends new path elements to the given path in the
-specified external environment
-.RB ( ENV
-by default).
-This will only add
-any particular path once (leaving the first one it encounters and
-ignoring the rest, to preserve path order),
-and to help assure this,
-will normalize all paths (using
-.B os.path.normpath
-and
-.BR os.path.normcase ).
-This can also handle the
-case where the given old path variable is a list instead of a
-string, in which case a list will be returned instead of a string.
-Example:
-
-.ES
-print 'before:',env['ENV']['INCLUDE']
-include_path = '/foo/bar:/foo'
-env.PrependENVPath('INCLUDE', include_path)
-print 'after:',env['ENV']['INCLUDE']
-
-yields:
-before: /biz:/foo
-after: /foo/bar:/foo:/biz
-.EE
-
 .TP
 .RI AppendENVPath( name ", " newpath ", [" envname ", " sep ])
 This appends new path elements to the given path in the
@@ -1786,6 +1803,7 @@ The returned Builder
 is intended to be passed to the
 .B SourceCode
 function.
+
 .ES
 env.SourceCode('.', env.BitKeeper())
 .EE
@@ -1834,7 +1852,7 @@ for the keywords.
 env2 = env.Copy()
 env3 = env.Copy(CCFLAGS = '-g')
 .EE
-
+.IP
 Additionally, a list of tools may be specified, as in the Environment
 constructor:
 
@@ -1843,7 +1861,6 @@ def MyTool(env): env['FOO'] = 'bar'
 env4 = env.Copy(tools = ['msvc', MyTool])
 .EE
 
-
 .TP
 .RI CVS( repository ", " module )
 A factory function that
@@ -1883,6 +1900,44 @@ env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo'))
 env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo/bar'))
 .EE
 
+.TP 
+.RI Default( targets )
+This specifies a list of default targets,
+which will be built by
+.B scons
+if no explicit targets are given on the command line.
+Multiple calls to
+.BR Default ()
+are legal,
+and add to the list of default targets.
+
+Multiple targets should be specified as
+separate arguments to the
+.BR Default ()
+method, or as a list.
+.BR Default ()
+will also accept the Node returned by any
+of a construction environment's
+builder methods.
+Examples:
+
+.ES
+env.Default('foo', 'bar', 'baz')
+env.Default(['a', 'b', 'c'])
+hello = env.Program('hello', 'hello.c')
+env.Default(hello)
+.EE
+.IP
+An argument to
+.BR Default ()
+of
+.B None
+will clear all default targets.
+Later calls to
+.BR Default ()
+will add to the (now empty) default-target list
+like normal.
+
 .TP
 .RI Depends( target ", " dependency )
 Specifies an explicit dependency;
@@ -1911,6 +1966,21 @@ dict = env.Dictionary()
 cc_dict = env.Dictionary('CC', 'CCFLAGS', 'CCCOM')
 .EE
 
+.TP
+.RI FindFile( file ", " dirs )
+Search for 
+.I file 
+in the path specified by 
+.IR dirs .
+.I file
+may be a list of file names or a single file name. In addition to searching
+for files that exist in the filesytem, this function also searches for
+derived files that have not yet been built.
+
+.ES
+foo = env.FindFile('foo', ['dir1', 'dir2'])
+.EE
+
 .TP
 .RI Ignore( target ", " dependency )
 The specified dependency file(s)
@@ -1946,6 +2016,15 @@ env.InstallAs(target = ['../lib/libfoo.a', '../lib/libbar.a'],
               source = ['libFOO.a', 'libBAR.a'])
 .EE
 
+.TP
+.RI Local( targets )
+The specified
+.I targets
+will have copies made in the local tree,
+even if an already up-to-date copy
+exists in a repository.
+Returns a list of the target Node or Nodes.
+
 .TP
 Perforce()
 A factory function that
@@ -1956,6 +2035,7 @@ The returned Builder
 is intended to be passed to the
 .B SourceCode
 function:
+
 .ES
 env.SourceCode('.', env.Perforce())
 .EE
@@ -1977,24 +2057,6 @@ USER,
 and
 USERNAME.
 
-.TP
-.RI AlwaysBuild( target ", ...)"
-Marks each given
-.I target
-so that it is always assumed to be out of date,
-and will always be rebuilt if needed.
-Note, however, that
-.BR AlwaysBuild ()
-does not add its target(s) to the default target list,
-so the targets will only be built
-if they are specified on the command line,
-or are a dependent of a target specified on the command line--but
-they will
-.I always
-be built if so specified.
-Multiple targets can be passed in to a single call to
-.BR AlwaysBuild ().
-
 .TP
 .RI Precious( target ", ...)"
 Marks each given
@@ -2025,6 +2087,36 @@ and the lists are added together.
 env.Prepend(CCFLAGS = '-g ', FOO = ['foo.yyy'])
 .EE
 
+.TP
+.RI PrependENVPath( name ", " newpath ", [" envname ", " sep ])
+This appends new path elements to the given path in the
+specified external environment
+.RB ( ENV
+by default).
+This will only add
+any particular path once (leaving the first one it encounters and
+ignoring the rest, to preserve path order),
+and to help assure this,
+will normalize all paths (using
+.B os.path.normpath
+and
+.BR os.path.normcase ).
+This can also handle the
+case where the given old path variable is a list instead of a
+string, in which case a list will be returned instead of a string.
+Example:
+
+.ES
+print 'before:',env['ENV']['INCLUDE']
+include_path = '/foo/bar:/foo'
+env.PrependENVPath('INCLUDE', include_path)
+print 'after:',env['ENV']['INCLUDE']
+
+yields:
+before: /biz:/foo
+after: /foo/bar:/foo:/biz
+.EE
+
 .TP
 RCS()
 A factory function that
@@ -2035,6 +2127,7 @@ The returned Builder
 is intended to be passed to the
 .B SourceCode
 function:
+
 .ES
 env.SourceCode('.', env.RCS())
 .EE
@@ -2072,6 +2165,7 @@ The returned Builder
 is intended to be passed to the
 .B SourceCode
 function:
+
 .ES
 env.SourceCode('.', env.SCCS())
 .EE
@@ -2157,6 +2251,7 @@ source code management files on disk.
 You can avoid these extra searches
 and speed up your build a little
 by disabling these searches as follows:
+
 .ES
 env.SourceCode('.', None)
 .EE
@@ -2175,6 +2270,7 @@ functions that return appropriate
 Builders for various popular
 source code management systems.
 Canonical examples of invocation include:
+
 .ES
 env.SourceCode('.', env.BitKeeper('/usr/local/BKsources'))
 env.SourceCode('src', env.CVS('/usr/local/CVSROOT'))
@@ -2303,6 +2399,7 @@ Alias, CFile, CXXFile, DVI, Library, Object, PDF, PostScript, and Program
 are available by default.
 If you initialize this variable when an
 Environment is created:
+
 .ES
 env = Environment(BUILDERS = {'NewBuilder' : foo})
 .EE
@@ -2310,12 +2407,14 @@ env = Environment(BUILDERS = {'NewBuilder' : foo})
 the default Builders will no longer be available.
 To use a new Builder object in addition to the default Builders,
 add your new Builder object like this:
+
 .ES
 env = Environment()
 env.Append(BUILDERS = {'NewBuilder' : foo})
 .EE
 .IP
 or this:
+
 .ES
 env = Environment()
 env['BUILDERS]['NewBuilder'] = foo
@@ -3235,6 +3334,7 @@ In addition, the construction environment
 variables CPPPATH, LIBPATH, LIBS, PROGEMITTER, SHLIBEMITTER and LIBEMITTER
 are modified. Because the build-performance is affected when using this tool,
 you have to explicitly specify it at Environment creation:
+
 .ES
 Environment(tools=['default','qt']).
 .EE
@@ -4614,6 +4714,7 @@ The specified
 will have copies made in the local tree,
 even if an already up-to-date copy
 exists in a repository.
+Returns a list of the target Node or Nodes.
 
 .TP
 .RI ParseConfig( env ", " command ", [" function ])
@@ -4906,6 +5007,7 @@ to the directory in which each
 subsidiary SConscript file lives.
 This behavior may be disabled
 by specifying:
+
 .ES
 SConscriptChdir(0)
 .EE
@@ -5322,6 +5424,7 @@ the command line.
 This allows white space to be enclosed
 in an argument by defining
 a command in a list within a list:
+
 .ES
 Action([['cc', '-c', '-DWHITE SPACE', '-o', '$TARGET', '$SOURCES']])
 .EE
@@ -5347,6 +5450,7 @@ more than one target file or source file.
 The actual target and source file name(s) may
 be retrieved from their Node objects
 via the built-in Python str() function:
+
 .ES
 target_file_name = str(target)
 source_file_names = map(lambda x: str(x), source)
index 8f1f75466e3b04be54901acc3e6a5ad10c1fcd24..4d0f6461bbc42aec743744266bf088f2f334264b 100644 (file)
@@ -39,6 +39,9 @@ RELEASE X.XX - XXX
   - Support arbitrary expansion of construction variables within
     file and directory arguments to Builder calls and Environment methods.
 
+  - Add Environment-method versions of AddPreAction(), AddPostAction(),
+    Default(), FindFile(), and Local().
+
   From Bram Moolenaar:
 
   - Split the non-SCons-specific functionality from SConf.py to a new,
index e7407ee67deb31e38f659254806a926be13ea5ff..074fd3c6c901ec68359d962e4f0278ec2adfd530 100644 (file)
@@ -577,6 +577,20 @@ class Environment:
     # same-named global functions.
     #######################################################################
 
+    def AddPreAction(self, files, action):
+        nodes = self.arg2nodes(files, self.fs.Entry)
+        action = SCons.Action.Action(action)
+        for n in nodes:
+            n.add_pre_action(action)
+        return nodes
+    
+    def AddPostAction(self, files, action):
+        nodes = self.arg2nodes(files, self.fs.Entry)
+        action = SCons.Action.Action(action)
+        for n in nodes:
+            n.add_post_action(action)
+        return nodes
+
     def AlwaysBuild(self, *targets):
         tlist = []
         for t in targets:
@@ -598,6 +612,18 @@ class Environment:
                                     source_factory=SCons.Node.FS.default_fs.Entry)
         return bld(self, target, source)
 
+    def Default(self, *targets):
+        global DefaultTargets
+        if DefaultTargets is None:
+            DefaultTargets = []
+        for t in targets:
+            if t is None:
+                DefaultTargets = []
+            elif isinstance(t, SCons.Node.Node):
+                DefaultTargets.append(t)
+            else:
+                DefaultTargets.extend(self.arg2nodes(t, self.fs.Entry))
+
     def Depends(self, target, dependency):
         """Explicity specify that 'target's depend on 'dependency'."""
         tlist = self.arg2nodes(target, self.fs.File)
@@ -609,6 +635,11 @@ class Environment:
             tlist = tlist[0]
         return tlist
 
+    def FindFile(self, file, dirs):
+        file = self.subst(file)
+        nodes = self.arg2nodes(dirs, self.fs.Dir)
+        return SCons.Node.FS.find_file(file, nodes, self.fs.File)
+
     def Ignore(self, target, dependency):
         """Ignore a dependency."""
         tlist = self.arg2nodes(target, self.fs.File)
@@ -653,6 +684,18 @@ class Environment:
             ret = ret[0]
         return ret
 
+    def Local(self, *targets):
+        ret = []
+        for targ in targets:
+            if isinstance(targ, SCons.Node.Node):
+                targ.set_local()
+                ret.append(targ)
+            else:
+                for t in self.arg2nodes(targ, self.fs.Entry):
+                   t.set_local()
+                   ret.append(t)
+        return ret
+
     def Precious(self, *targets):
         tlist = []
         for t in targets:
index d3807f50e2dc5e6610e46257e63bfc38e5ddb2fe..db053511a167f5b5256c3bed735fc0674e341700 100644 (file)
@@ -957,6 +957,18 @@ class EnvironmentTestCase(unittest.TestCase):
         assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
 
+    def test_PrependENVPath(self):
+        """Test prepending to an ENV path."""
+        env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
+                           MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
+        # have to include the pathsep here so that the test will work on UNIX too.
+        env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';') 
+        env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
+        env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
+        env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
+        assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
+        assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
+
     def test_Replace(self):
         """Test replacing construction variables in an Environment
 
@@ -997,6 +1009,28 @@ class EnvironmentTestCase(unittest.TestCase):
 
 
 
+    def test_AddPostAction(self):
+        """Test the AddPostAction() method"""
+        env = Environment(FOO='fff', BAR='bbb')
+
+        n = env.AddPostAction('$FOO', lambda x: x)
+        assert str(n[0]) == 'fff', n[0]
+
+        n = env.AddPostAction(['ggg', '$BAR'], lambda x: x)
+        assert str(n[0]) == 'ggg', n[0]
+        assert str(n[1]) == 'bbb', n[1]
+
+    def test_AddPreAction(self):
+        """Test the AddPreAction() method"""
+        env = Environment(FOO='fff', BAR='bbb')
+
+        n = env.AddPreAction('$FOO', lambda x: x)
+        assert str(n[0]) == 'fff', n[0]
+
+        n = env.AddPreAction(['ggg', '$BAR'], lambda x: x)
+        assert str(n[0]) == 'ggg', n[0]
+        assert str(n[1]) == 'bbb', n[1]
+
     def test_AlwaysBuild(self):
         """Test the AlwaysBuild() method"""
         env = Environment(FOO='fff', BAR='bbb')
@@ -1045,6 +1079,25 @@ class EnvironmentTestCase(unittest.TestCase):
         assert 'foo1.in' in map(lambda x: x.path, t.sources)
         assert 'foo2.in' in map(lambda x: x.path, t.sources)
 
+    def test_Default(self):
+        """Test the Default() method"""
+        env = Environment(FOO = 'fff', BAR = 'bbb')
+
+        t = env.Default(None)
+        assert SCons.Environment.DefaultTargets == []
+
+        t = env.Default('xyz')
+        d = map(str, SCons.Environment.DefaultTargets)
+        assert d == ['xyz'], d
+
+        t = env.Default('$FOO')
+        d = map(str, SCons.Environment.DefaultTargets)
+        assert d == ['xyz', 'fff'], d
+
+        t = env.Default(None, '$BAR', 'another_file')
+        d = map(str, SCons.Environment.DefaultTargets)
+        assert d == ['bbb', 'another_file'], d
+
     def test_Depends(self):
        """Test the explicit Depends method."""
        env = Environment(FOO = 'xxx', BAR='yyy')
@@ -1064,6 +1117,15 @@ class EnvironmentTestCase(unittest.TestCase):
        assert d.__class__.__name__ == 'File'
        assert d.path == 'yyy.py'
 
+    def test_FindFile(self):
+        """Test the FindFile() method"""
+        env = Environment(FOO = 'fff', BAR = 'bbb')
+
+        r = env.FindFile('foo', ['no_such_directory'])
+        assert r is None, r
+
+        # XXX
+
     def test_Ignore(self):
         """Test the explicit Ignore method."""
         env = Environment(FOO='yyy', BAR='zzz')
@@ -1083,7 +1145,7 @@ class EnvironmentTestCase(unittest.TestCase):
         assert i.path == 'zzzyyy'
 
     def test_Install(self):
-       """Test Install and InstallAs methods"""
+       """Test the Install method"""
         env = Environment(FOO='iii', BAR='jjj')
 
         tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ])
@@ -1129,6 +1191,10 @@ class EnvironmentTestCase(unittest.TestCase):
         match = str(e) == "Target `export/foo1' of Install() is a file, but should be a directory.  Perhaps you have the Install() arguments backwards?"
         assert match, e
 
+    def test_InstallAs(self):
+       """Test the InstallAs method"""
+        env = Environment(FOO='iii', BAR='jjj')
+
         tgt = env.InstallAs(target=string.split('foo1 foo2'),
                             source=string.split('bar1 bar2'))
         assert len(tgt) == 2, len(tgt)
@@ -1144,6 +1210,17 @@ class EnvironmentTestCase(unittest.TestCase):
         assert tgt.sources[0].path == 'jjj.s'
         assert tgt.builder == InstallBuilder
 
+    def test_Local(self):
+        """Test the Local() method."""
+        env = Environment(FOO='lll')
+
+        l = env.Local(env.fs.File('fff'))
+        assert str(l[0]) == 'fff', l[0]
+
+        l = env.Local('ggg', '$FOO')
+        assert str(l[0]) == 'ggg', l[0]
+        assert str(l[1]) == 'lll', l[1]
+
     def test_Precious(self):
         """Test the Precious() method."""
         env = Environment(FOO='ggg', BAR='hhh')
@@ -1207,7 +1284,7 @@ class EnvironmentTestCase(unittest.TestCase):
         s = e.src_builder()
         assert s is None, s
 
-        
+
 if __name__ == "__main__":
     suite = unittest.makeSuite(EnvironmentTestCase, 'test_')
     if not unittest.TextTestRunner().run(suite).wasSuccessful():
index 1c17ee203ae3f93a286807533f69558bcb740973..276ff4e138802546e0341dc2e5f351805e944a32 100644 (file)
@@ -56,7 +56,6 @@ import traceback
 def do_nothing(text): pass
 HelpFunction = do_nothing
 
-default_targets = None
 clean_targets = {}
 arguments = {}
 launch_dir = os.path.abspath(os.curdir)
@@ -356,27 +355,6 @@ def annotate(node):
 # leave this disabled until we find a more efficient mechanism.
 #SCons.Node.Annotate = annotate
 
-def Default(*targets):
-    global default_targets
-    if default_targets is None:
-        default_targets = []
-    for t in targets:
-        if t is None:
-            default_targets = []
-        elif isinstance(t, SCons.Node.Node):
-            default_targets.append(t)
-        else:
-            default_targets.extend(SCons.Node.arg2nodes(t,
-                                         SCons.Node.FS.default_fs.Entry))
-
-def Local(*targets):
-    for targ in targets:
-        if isinstance(targ, SCons.Node.Node):
-            targ.set_local()
-        else:
-            for t in SCons.Node.arg2nodes(targ, SCons.Node.FS.default_fs.Entry):
-               t.set_local()
-
 def Help(text):
     HelpFunction(text)
 
@@ -390,10 +368,6 @@ def GetBuildPath(files):
         return ret[0]
     return ret
 
-def FindFile(file, dirs):
-    nodes = SCons.Node.arg2nodes(dirs, SCons.Node.FS.default_fs.Dir)
-    return SCons.Node.FS.find_file(file, nodes)
-
 def Export(*vars):
     for var in vars:
         global_exports.update(compute_exports(var))
@@ -512,16 +486,6 @@ def Clean(target, files):
     except KeyError:
         clean_targets[target] = nodes
 
-def AddPreAction(files, action):
-    nodes = SCons.Node.arg2nodes(files, SCons.Node.FS.default_fs.Entry)
-    for n in nodes:
-        n.add_pre_action(SCons.Action.Action(action))
-
-def AddPostAction(files, action):
-    nodes = SCons.Node.arg2nodes(files, SCons.Node.FS.default_fs.Entry)
-    for n in nodes:
-        n.add_post_action(SCons.Action.Action(action))
-
 def Exit(value=0):
     sys.exit(value)
 
@@ -553,8 +517,6 @@ def BuildDefaultGlobals():
 
     globals = {}
     globals['Action']            = SCons.Action.Action
-    globals['AddPostAction']     = AddPostAction
-    globals['AddPreAction']      = AddPreAction
     globals['Alias']             = Alias
     globals['ARGUMENTS']         = arguments
     globals['BuildDir']          = BuildDir
@@ -563,7 +525,6 @@ def BuildDefaultGlobals():
     globals['Clean']             = Clean
     globals['Configure']         = SCons.SConf.SConf
     globals['CScan']             = SCons.Defaults.CScan
-    globals['Default']           = Default
     globals['DefaultEnvironment'] = SCons.Defaults.DefaultEnvironment
     globals['Dir']               = SCons.Node.FS.default_fs.Dir
     globals['EnsurePythonVersion'] = EnsurePythonVersion
@@ -572,7 +533,6 @@ def BuildDefaultGlobals():
     globals['Exit']              = Exit
     globals['Export']            = Export
     globals['File']              = SCons.Node.FS.default_fs.File
-    globals['FindFile']          = FindFile
     globals['GetBuildPath']      = GetBuildPath
     globals['GetCommandHandler'] = SCons.Action.GetCommandHandler
     globals['GetJobs']           = GetJobs
@@ -581,7 +541,6 @@ def BuildDefaultGlobals():
     globals['Help']              = Help
     globals['Import']            = Import
     globals['Literal']           = SCons.Util.Literal
-    globals['Local']             = Local
     globals['Options']           = Options
     globals['ParseConfig']       = SCons.Util.ParseConfig
     globals['Platform']          = SCons.Platform.Platform
@@ -602,4 +561,25 @@ def BuildDefaultGlobals():
     globals['Tool']              = SCons.Tool.Tool
     globals['Value']             = SCons.Node.Python.Value
     globals['WhereIs']           = SCons.Util.WhereIs
+
+    class DefaultEnvironmentCall:
+        """ """
+        def __init__(self, method_name):
+            self.method_name = method_name
+        def __call__(self, *args, **kw):
+            method = getattr(SCons.Defaults.DefaultEnvironment(),
+                             self.method_name)
+            return apply(method, args, kw)
+
+    EnvironmentMethods = [
+        'AddPostAction',
+        'AddPreAction',
+        'Default',
+        'FindFile',
+        'Local',
+    ]
+
+    for name in EnvironmentMethods:
+        globals[name] = DefaultEnvironmentCall(name)
+
     return globals
index 3b5c9d9b7dd287bcb6a58e9971c41f9161799f42..3ab4ed09d47fc69aaab045165022a7f3bc8a44e3 100644 (file)
@@ -883,16 +883,16 @@ def _main(args, parser):
                         # or not a file, so go ahead and keep it as a default
                         # target and let the engine sort it out:
                         return 1                
-                default_targets = SCons.Script.SConscript.default_targets
+                default_targets = SCons.Environment.DefaultTargets
                 if default_targets is None:
                     default_targets = []
                 else:
                     default_targets = filter(check_dir, default_targets)
-                SCons.Script.SConscript.default_targets = default_targets
+                SCons.Environment.DefaultTargets = default_targets
                 target_top = None
                 lookup_top = None
 
-        targets = SCons.Script.SConscript.default_targets
+        targets = SCons.Environment.DefaultTargets
         if targets is None:
             targets = [SCons.Node.FS.default_fs.Dir('.')]
 
index d2c438fc35a63a28ed23f7a2286ebdf889254afc..ae0346aa8edf22994e87f8d1907eb84429102162 100644 (file)
@@ -155,57 +155,77 @@ test.fail_test(test.read(test.workpath('eight', 'bar.out')) != "eight/bar.in\n")
 
 
 
-test.subdir('sub1')
+test.subdir('nine', ['nine', 'sub1'])
 
-test.write('SConstruct', """
+test.write(['nine', 'SConstruct'], """\
 B = Builder(action = r'%s build.py $TARGET $SOURCES')
 env = Environment(BUILDERS = { 'B' : B })
 env.B(target = 'xxx.out', source = 'xxx.in')
 SConscript('sub1/SConscript')
 """ % python)
 
-test.write('xxx.in', "xxx.in\n")
+test.write(['nine', 'xxx.in'], "xxx.in\n")
 
-test.write(['sub1', 'SConscript'], """
-B = Builder(action = r'%s build.py $TARGET $SOURCES')
+test.write(['nine', 'sub1', 'SConscript'], """
+B = Builder(action = r'%s ../build.py $TARGET $SOURCES')
 env = Environment(BUILDERS = { 'B' : B })
 env.B(target = 'xxx.out', source = 'xxx.in')
 Default('xxx.out')
 """ % python)
 
-test.write(['sub1', 'xxx.in'], "sub1/xxx.in\n")
+test.write(['nine', 'sub1', 'xxx.in'], "sub1/xxx.in\n")
 
-test.run()     # no arguments, use the Default
+test.run(chdir = 'nine')       # no arguments, use the Default
 
-test.fail_test(os.path.exists(test.workpath('xxx.out')))
-test.fail_test(test.read(test.workpath('sub1', 'xxx.out')) != "sub1/xxx.in\n")
+test.fail_test(os.path.exists(test.workpath('nine', 'xxx.out')))
+test.fail_test(test.read(test.workpath('nine', 'sub1', 'xxx.out')) != "sub1/xxx.in\n")
 
 
 
-test.subdir('sub2')
+test.subdir('ten', ['ten', 'sub2'])
 
-test.write('SConstruct', """
+test.write(['ten', 'SConstruct'], """\
 Default('sub2')
-B = Builder(action = r'%s build.py $TARGET $SOURCES')
+B = Builder(action = r'%s ../build.py $TARGET $SOURCES')
 env = Environment(BUILDERS = { 'B' : B })
 env.B(target = 'xxx.out', source = 'xxx.in')
 SConscript('sub2/SConscript')
 """ % python)
 
-test.write('xxx.in', "xxx.in\n")
+test.write(['ten', 'xxx.in'], "xxx.in\n")
 
-test.write(['sub2', 'SConscript'], """
-B = Builder(action = r'%s build.py $TARGET $SOURCES')
+test.write(['ten', 'sub2', 'SConscript'], """
+B = Builder(action = r'%s ../build.py $TARGET $SOURCES')
 env = Environment(BUILDERS = { 'B' : B })
 env.B(target = 'xxx.out', source = 'xxx.in')
 """ % python)
 
-test.write(['sub2', 'xxx.in'], "sub2/xxx.in\n")
+test.write(['ten', 'sub2', 'xxx.in'], "sub2/xxx.in\n")
+
+test.run(chdir = 'ten')        # no arguments, use the Default
+
+test.fail_test(os.path.exists(test.workpath('ten', 'xxx.out')))
+test.fail_test(test.read(test.workpath('ten', 'sub2', 'xxx.out')) != "sub2/xxx.in\n")
+
+
+test.subdir('eleven')
+
+test.write(['eleven', 'SConstruct'], """
+B = Builder(action = r'%s ../build.py $TARGET $SOURCES')
+env = Environment(BUILDERS = { 'B' : B }, XXX = 'foo.out')
+env.B(target = 'foo.out', source = 'foo.in')
+env.B(target = 'bar.out', source = 'bar.in')
+env.Default('$XXX')
+""" % python)
+
+test.write(os.path.join('eleven', 'foo.in'), "eleven/foo.in\n");
+
+test.write(os.path.join('eleven', 'bar.in'), "eleven/bar.in\n");
 
-test.run()     # no arguments, use the Default
+test.run(chdir = 'eleven')     # no arguments, use the Default
 
-test.fail_test(os.path.exists(test.workpath('xxx.out')))
-test.fail_test(test.read(test.workpath('sub2', 'xxx.out')) != "sub2/xxx.in\n")
+test.fail_test(test.read(test.workpath('eleven', 'foo.out')) != "eleven/foo.in\n")
+test.fail_test(os.path.exists(test.workpath('eleven', 'bar')))
 
 
 
index 9c837b5fee90dd3bf4e4782fe5d8b6b09ea7685e..8f6cb1ac7ba131379089960bd816d0113f08699c 100644 (file)
@@ -38,13 +38,14 @@ test.write(['bar', 'testfile1'], 'test 3\n')
 test.write(['bar', 'baz', 'testfile2'], 'test 4\n')
 
 test.write('SConstruct', """
+env = Environment(FILE = 'file', BAR = 'bar')
 file1 = FindFile('testfile1', [ 'foo', '.', 'bar', 'bar/baz' ])
 print open(str(file1), 'r').read()
-file2 = FindFile('testfile1', [ 'bar', 'foo', '.', 'bar/baz' ])
+file2 = env.FindFile('test${FILE}1', [ 'bar', 'foo', '.', 'bar/baz' ])
 print open(str(file2), 'r').read()
 file3 = FindFile('testfile2', [ 'foo', '.', 'bar', 'bar/baz' ])
 print open(str(file3), 'r').read()
-file4 = FindFile('testfile2', [ 'bar/baz', 'foo', '.', 'bar' ])
+file4 = env.FindFile('testfile2', [ '$BAR/baz', 'foo', '.', 'bar' ])
 print open(str(file4), 'r').read()
 """)
 
index 1163767b4bc07ceeca8de9b419b7c70f8ef65155..59620950313f5ffef7f6a427f5504b8a47dff5cc 100644 (file)
@@ -52,7 +52,7 @@ def copy(env, source, target):
     open(target, "wb").write(open(source, "rb").read())
 
 Build = Builder(action=copy)
-env = Environment(BUILDERS={'Build':Build})
+env = Environment(BUILDERS={'Build':Build}, BBB='bbb')
 env.Build('aaa.mid', 'aaa.in')
 env.Build('aaa.out', 'aaa.mid')
 Local('aaa.out')
@@ -70,7 +70,7 @@ def bbb_copy(env, source, target):
 
 Import("env")
 env.Build('bbb.1', 'bbb.0')
-Local('bbb.1')
+env.Local('${BBB}.1')
 env.Command('bbb.2', 'bbb.x', bbb_copy)
 env.Depends('bbb.2', 'bbb.1')
 """)
index 91fcb3b4f5c7b05a93e5293f586df00b478fc6d4..d5340f26be0982dc79d9c6b01516ec18833dcd0d 100644 (file)
@@ -36,32 +36,22 @@ _exe = TestSCons._exe
 
 test = TestSCons.TestSCons()
 
-test.write('foo.c', r"""
-#include <stdio.h>
-
-int main(void)
-{
-    printf("Foo\n");
-    return 0;
-}
-""")
-
 test.write('SConstruct', """
 import os.path
 
-env=Environment()
+env = Environment(XXX='bar%s')
 
 def before(env, target, source):
     f=open(str(target[0]), "wb")
     f.write("Foo\\n")
     f.close()
-    f=open("before.txt", "wb")
-    f.write("Bar\\n")
+    f=open("before.txt", "ab")
+    f.write(str(target[0]) + "\\n")
     f.close()
 
 def after(env, target, source):
     fin = open(str(target[0]), "rb")
-    fout = open("after%s", "wb")
+    fout = open("after_" + str(target[0]), "wb")
     fout.write(fin.read())
     fout.close()
     fin.close()
@@ -69,12 +59,46 @@ def after(env, target, source):
 foo = env.Program(source='foo.c', target='foo')
 AddPreAction(foo, before)
 AddPostAction('foo%s', after)
+
+bar = env.Program(source='bar.c', target='bar')
+env.AddPreAction('$XXX', before)
+env.AddPostAction('$XXX', after)
 """ % (_exe, _exe))
 
-after_exe = test.workpath('after' + _exe)
+test.write('foo.c', r"""
+#include <stdio.h>
+
+int main(void)
+{
+    printf("foo.c\n");
+    return 0;
+}
+""")
+
+test.write('bar.c', r"""
+#include <stdio.h>
+
+int main(void)
+{
+    printf("bar.c\n");
+    return 0;
+}
+""")
+
 
 test.run(arguments='.')
-test.fail_test(open('before.txt', 'rb').read() != "Bar\n")
-os.chmod(after_exe, os.stat(after_exe)[stat.ST_MODE] | stat.S_IXUSR)
-test.run(program=test.workpath(after_exe), stdout="Foo\n")
+
+test.run(program=test.workpath('foo'+ _exe), stdout="foo.c\n")
+test.run(program=test.workpath('bar'+ _exe), stdout="bar.c\n")
+
+test.fail_test(test.read('before.txt', 'rb') != "bar%s\nfoo%s\n" % (_exe, _exe))
+
+after_foo_exe = test.workpath('after_foo' + _exe)
+os.chmod(after_foo_exe, os.stat(after_foo_exe)[stat.ST_MODE] | stat.S_IXUSR)
+test.run(program=test.workpath(after_foo_exe), stdout="foo.c\n")
+
+after_bar_exe = test.workpath('after_bar' + _exe)
+os.chmod(after_bar_exe, os.stat(after_bar_exe)[stat.ST_MODE] | stat.S_IXUSR)
+test.run(program=test.workpath(after_bar_exe), stdout="bar.c\n")
+
 test.pass_test()