From 68b5dfbc87552d4cd1a9c067f6ba4523d9560bb9 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Mon, 8 Sep 2003 04:01:32 +0000 Subject: Give the global functions corresponding Environment methods. --- doc/man/scons.1 | 204 +++++++++++++++++++++++++--------- src/CHANGES.txt | 3 + src/engine/SCons/Environment.py | 43 +++++++ src/engine/SCons/EnvironmentTests.py | 81 +++++++++++++- src/engine/SCons/Script/SConscript.py | 62 ++++------- src/engine/SCons/Script/__init__.py | 6 +- test/Default.py | 58 ++++++---- test/FindFile.py | 5 +- test/Repository/Local.py | 4 +- test/pre-post-actions.py | 60 +++++++--- 10 files changed, 389 insertions(+), 137 deletions(-) diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 490975d..95696c9 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -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 @@ -1697,6 +1726,24 @@ 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 to the end of construction variables in the environment. @@ -1717,36 +1764,6 @@ 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 specified external environment @@ -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; @@ -1912,6 +1967,21 @@ 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) will be ignored when deciding if @@ -1947,6 +2017,15 @@ env.InstallAs(target = ['../lib/libfoo.a', '../lib/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 returns a Builder object @@ -1956,6 +2035,7 @@ The returned Builder is intended to be passed to the .B SourceCode function: + .ES env.SourceCode('.', env.Perforce()) .EE @@ -1978,24 +2058,6 @@ 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 .I target @@ -2026,6 +2088,36 @@ 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 returns a Builder object @@ -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) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 8f1f754..4d0f646 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -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, diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index e7407ee..074fd3c 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -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: diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index d3807f5..db05351 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -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(): diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 1c17ee2..276ff4e 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -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 diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 3b5c9d9..3ab4ed0 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -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('.')] diff --git a/test/Default.py b/test/Default.py index d2c438f..ae0346a 100644 --- a/test/Default.py +++ b/test/Default.py @@ -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'))) diff --git a/test/FindFile.py b/test/FindFile.py index 9c837b5..8f6cb1a 100644 --- a/test/FindFile.py +++ b/test/FindFile.py @@ -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() """) diff --git a/test/Repository/Local.py b/test/Repository/Local.py index 1163767..5962095 100644 --- a/test/Repository/Local.py +++ b/test/Repository/Local.py @@ -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') """) diff --git a/test/pre-post-actions.py b/test/pre-post-actions.py index 91fcb3b..d5340f2 100644 --- a/test/pre-post-actions.py +++ b/test/pre-post-actions.py @@ -36,32 +36,22 @@ _exe = TestSCons._exe test = TestSCons.TestSCons() -test.write('foo.c', r""" -#include - -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 + +int main(void) +{ + printf("foo.c\n"); + return 0; +} +""") + +test.write('bar.c', r""" +#include + +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() -- cgit v0.12