diff options
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/SCons/Action.py | 14 | ||||
-rw-r--r-- | src/engine/SCons/ActionTests.py | 14 | ||||
-rw-r--r-- | src/engine/SCons/Environment.py | 13 | ||||
-rw-r--r-- | src/engine/SCons/EnvironmentTests.py | 48 | ||||
-rw-r--r-- | src/engine/SCons/Node/FS.py | 44 | ||||
-rw-r--r-- | src/engine/SCons/Node/FSTests.py | 50 | ||||
-rw-r--r-- | src/engine/SCons/Node/NodeTests.py | 12 | ||||
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 3 | ||||
-rw-r--r-- | src/engine/SCons/Script/SConscript.py | 7 | ||||
-rw-r--r-- | src/engine/SCons/Script/__init__.py | 16 |
10 files changed, 202 insertions, 19 deletions
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index c222d26..79fdd2c 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -266,11 +266,17 @@ class ActionBase: try: cwd = kw['dir'] - except: + except KeyError: cwd = None else: del kw['dir'] + def rstr(x): + try: + return x.rstr() + except AttributeError: + return str(x) + if kw.has_key('target'): t = kw['target'] del kw['target'] @@ -280,7 +286,7 @@ class ActionBase: cwd = t[0].cwd except (IndexError, AttributeError): pass - dict['TARGETS'] = SCons.Util.PathList(map(os.path.normpath, map(str, t))) + dict['TARGETS'] = SCons.Util.PathList(map(os.path.normpath, map(rstr, t))) if dict['TARGETS']: dict['TARGET'] = dict['TARGETS'][0] @@ -289,7 +295,7 @@ class ActionBase: del kw['source'] if not SCons.Util.is_List(s): s = [s] - dict['SOURCES'] = SCons.Util.PathList(map(os.path.normpath, map(str, s))) + dict['SOURCES'] = SCons.Util.PathList(map(os.path.normpath, map(rstr, s))) if dict['SOURCES']: dict['SOURCE'] = dict['SOURCES'][0] @@ -357,7 +363,7 @@ class CommandAction(ActionBase): if execute_actions: try: ENV = kw['env']['ENV'] - except: + except KeyError: global default_ENV if not default_ENV: import SCons.Environment diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index c1425ef..5fa1b8b 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -114,6 +114,20 @@ class ActionBaseTestCase(unittest.TestCase): assert SOURCES == ['s1', 's2'], d['SOURCES'] assert str(d['SOURCE']) == 's1', d['SOURCE'] + class N: + def __init__(self, name): + self.name = name + def rstr(self): + return 'rstr-' + self.name + + d = a.subst_dict(target = [N('t3'), 't4'], source = ['s3', N('s4')]) + TARGETS = map(lambda x: str(x), d['TARGETS']) + TARGETS.sort() + assert TARGETS == ['rstr-t3', 't4'], d['TARGETS'] + SOURCES = map(lambda x: str(x), d['SOURCES']) + SOURCES.sort() + assert SOURCES == ['rstr-s4', 's3'], d['SOURCES'] + class CommandActionTestCase(unittest.TestCase): def test_init(self): diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 42aa326..da7c15a 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -492,13 +492,18 @@ class DirVarInterp(VarInterpolator): def prepare(x, self=self): if isinstance(x, SCons.Node.Node): - return x + return [x] elif str(x): - return self.fs.Dir(str(x), directory=self.dir) + if os.path.isabs(str(x)): + return [self.fs.Dir(str(x), directory=self.dir)] + else: + return map(lambda d, s=str(x), fs=self.fs: + fs.Dir(s, directory=d), + [self.dir] + self.fs.Repositories) else: - return None + return [] - return map(prepare, src) + return reduce(lambda x, y: x+y, map(prepare, src), []) def instance(self, dir, fs): try: diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 75e5e83..418d891 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -507,6 +507,54 @@ class EnvironmentTestCase(unittest.TestCase): assert len(dict['_F77INCFLAGS']) == 0, dict['_F77INCFLAGS'] assert len(dict['_LIBDIRFLAGS']) == 0, dict['_LIBDIRFLAGS'] + blat = SCons.Node.FS.default_fs.File('blat') + SCons.Node.FS.default_fs.Repository('/rep1') + SCons.Node.FS.default_fs.Repository('/rep2') + env = Environment(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat], + INCPREFIX = '-I ', + INCSUFFIX = 'XXX', + FOO = 'baz') + dict = env.autogenerate(dir = SCons.Node.FS.default_fs.Dir('/xx')) + assert len(dict['_CPPINCFLAGS']) == 18, dict['_CPPINCFLAGS'] + assert dict['_CPPINCFLAGS'][0] == '$(', \ + dict['_CPPINCFLAGS'][0] + assert dict['_CPPINCFLAGS'][1] == '-I', \ + dict['_CPPINCFLAGS'][1] + assert dict['_CPPINCFLAGS'][2] == os.path.normpath('/xx/fooXXX'), \ + dict['_CPPINCFLAGS'][2] + assert dict['_CPPINCFLAGS'][3] == '-I', \ + dict['_CPPINCFLAGS'][3] + assert dict['_CPPINCFLAGS'][4] == os.path.normpath('/rep1/fooXXX'), \ + dict['_CPPINCFLAGS'][4] + assert dict['_CPPINCFLAGS'][5] == '-I', \ + dict['_CPPINCFLAGS'][5] + assert dict['_CPPINCFLAGS'][6] == os.path.normpath('/rep2/fooXXX'), \ + dict['_CPPINCFLAGS'][6] + assert dict['_CPPINCFLAGS'][7] == '-I', \ + dict['_CPPINCFLAGS'][7] + assert dict['_CPPINCFLAGS'][8] == os.path.normpath('/a/bXXX'), \ + dict['_CPPINCFLAGS'][8] + assert dict['_CPPINCFLAGS'][9] == '-I', \ + dict['_CPPINCFLAGS'][9] + assert dict['_CPPINCFLAGS'][10] == os.path.normpath('/xx/baz/barXXX'), \ + dict['_CPPINCFLAGS'][10] + assert dict['_CPPINCFLAGS'][11] == '-I', \ + dict['_CPPINCFLAGS'][11] + assert dict['_CPPINCFLAGS'][12] == os.path.normpath('/rep1/baz/barXXX'), \ + dict['_CPPINCFLAGS'][12] + assert dict['_CPPINCFLAGS'][13] == '-I', \ + dict['_CPPINCFLAGS'][13] + assert dict['_CPPINCFLAGS'][14] == os.path.normpath('/rep2/baz/barXXX'), \ + dict['_CPPINCFLAGS'][14] + assert dict['_CPPINCFLAGS'][15] == '-I', \ + dict['_CPPINCFLAGS'][15] + assert dict['_CPPINCFLAGS'][16] == os.path.normpath('blatXXX'), \ + dict['_CPPINCFLAGS'][16] + assert dict['_CPPINCFLAGS'][17] == '$)', \ + dict['_CPPINCFLAGS'][17] + + + def test_platform(self): """Test specifying a platform callable when instantiating.""" def p(env): diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 771ac56..2645cea 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -99,6 +99,7 @@ class FS: self.pathTop = path self.Root = {} self.Top = None + self.Repositories = [] def set_toplevel_dir(self, path): assert not self.Top, "You can only set the top-level path on an FS object that has not had its File, Dir, or Entry methods called yet." @@ -152,9 +153,9 @@ class FS: drive, path_first = os.path.splitdrive(path_comp[0]) if not path_first: # Absolute path - drive = _my_normcase(drive) + drive_path = _my_normcase(drive) try: - directory = self.Root[drive] + directory = self.Root[drive_path] except KeyError: if not create: raise UserError @@ -162,7 +163,7 @@ class FS: dir.path = dir.path + os.sep dir.abspath = dir.abspath + os.sep dir.srcpath = dir.srcpath + os.sep - self.Root[drive] = dir + self.Root[drive_path] = dir directory = dir path_comp = path_comp[1:] else: @@ -209,6 +210,7 @@ class FS: "File %s found where directory expected." % path ret = fsclass(path_comp[-1], directory) + ret.fs = self directory.entries[file_name] = ret directory.add_wkid(ret) return ret @@ -295,6 +297,20 @@ class FS: raise UserError, "Source directory cannot be under build directory." build_dir.link(src_dir, duplicate) + def Repository(self, *dirs): + """Specify repository directories to search.""" + for d in dirs: + self.Repositories.append(self.Dir(d)) + + def Rsearch(self, path, func = os.path.exists): + """Search for something in a repository.""" + for dir in self.Repositories: + t = os.path.join(dir.path, path) + if func(t): + return t + return None + + class Entry(SCons.Node.Node): """A generic class for file system entries. This class if for when we don't know yet whether the entry being looked up is a file @@ -334,6 +350,7 @@ class Entry(SCons.Node.Node): self.__doSrcpath(self.duplicate) self.srcpath_ = self.srcpath self.cwd = None # will hold the SConscript directory for target nodes + self._rfile = None def get_dir(self): return self.dir @@ -372,7 +389,7 @@ class Entry(SCons.Node.Node): raise AttributeError def exists(self): - return os.path.exists(str(self)) + return os.path.exists(self.rstr()) def cached_exists(self): try: @@ -420,6 +437,7 @@ class Dir(Entry): def __init__(self, name, directory): Entry.__init__(self, name, directory) self._morph() + self._rfile = None def _morph(self): """Turn a file system node (either a freshly initialized @@ -573,11 +591,11 @@ class File(Entry): def get_contents(self): if not self.exists(): return '' - return open(str(self), "rb").read() + return open(self.rstr(), "rb").read() def get_timestamp(self): if self.exists(): - return os.path.getmtime(str(self)) + return os.path.getmtime(self.rstr()) else: return 0 @@ -594,6 +612,8 @@ class File(Entry): self.dir.sconsign().set_timestamp(self.name, self.get_timestamp()) def get_prevsiginfo(self): + """Fetch the previous signature information from the + .sconsign entry.""" return self.dir.sconsign().get(self.name) def get_stored_implicit(self): @@ -650,6 +670,18 @@ class File(Entry): else: self.__createDir() + def rfile(self): + if not self._rfile: + self._rfile = self + if not os.path.isabs(self.path) and not os.path.isfile(self.path): + t = self.fs.Rsearch(self.path, os.path.isfile) + if t: + self._rfile = self.fs.File(t) + return self._rfile + + def rstr(self): + return os.path.normpath(str(self.rfile())) + default_fs = FS() diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 1ae1215..595396a 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -530,6 +530,55 @@ class FSTestCase(unittest.TestCase): exc_caught = 1 assert exc_caught, "Should have caught a TypeError" +class RepositoryTestCase(unittest.TestCase): + def runTest(self): + """Test FS (file system) Repository operations + + """ + fs = SCons.Node.FS.FS() + + fs.Repository('foo') + fs.Repository(os.path.join('foo', 'bar')) + fs.Repository(os.path.join('bar', 'foo')) + fs.Repository('bar') + + assert len(fs.Repositories) == 4, fs.Repositories + r = map(lambda x, np=os.path.normpath: np(str(x)), fs.Repositories) + assert r == ['foo', 'foo/bar', 'bar/foo', 'bar'], r + + test = TestCmd(workdir = '') + test.subdir('rep1', 'rep2', 'rep3', 'work') + + rep1 = test.workpath('rep1') + rep2 = test.workpath('rep2') + rep3 = test.workpath('rep3') + + os.chdir(test.workpath('work')) + + fs = SCons.Node.FS.FS() + fs.Repository(rep1, rep2, rep3) + + wf = fs.File(os.path.join('f1')) + assert wf.rfile() is wf + + test.write([rep1, 'f2'], "") + + wf = fs.File('f2') + assert not wf.rfile() is wf, wf.rfile() + assert str(wf.rfile()) == os.path.join(rep1, 'f2'), str(wf.rfile()) + + test.subdir([rep2, 'f3']) + test.write([rep3, 'f3'], "") + + wf = fs.File('f3') + assert not wf.rfile() is wf, wf.rfile() + assert wf.rstr() == os.path.join(rep3, 'f3'), wf.rstr() + + assert not fs.Rsearch('f1', os.path.exists) + assert fs.Rsearch('f2', os.path.exists) + assert fs.Rsearch('f3', os.path.exists) + + class find_fileTestCase(unittest.TestCase): def runTest(self): """Testing find_file function""" @@ -553,6 +602,7 @@ if __name__ == "__main__": suite = unittest.TestSuite() suite.addTest(FSTestCase()) suite.addTest(BuildDirTestCase()) + suite.addTest(RepositoryTestCase()) suite.addTest(find_fileTestCase()) if not unittest.TextTestRunner().run(suite).wasSuccessful(): sys.exit(1) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 03b06bd..cbd5473 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -41,7 +41,7 @@ cycle_detected = None class Builder: def execute(self, **kw): global built_it, built_target, built_source, built_args - built_it = 1 + built_it = 1 built_target = kw['target'] built_source = kw['source'] built_args = kw @@ -555,6 +555,16 @@ class NodeTestCase(unittest.TestCase): n = nw.next() assert nw.next() == None + def test_rstr(self): + """Test the rstr() method.""" + class MyNode(SCons.Node.Node): + def __init__(self, name): + self.name = name + def __str__(self): + return self.name + n1 = MyNode("n1") + assert n1.rstr() == 'n1', n1.rstr() + def test_arg2nodes(self): """Test the arg2nodes function.""" dict = {} diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 90cd122..2a5e5bc 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -356,6 +356,9 @@ class Node: def current(self): return None + def rstr(self): + return str(self) + def get_children(node, parent): return node.children() def ignore_cycle(node, stack): pass def do_nothing(node, parent): pass diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 48c4046..e088c99 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -167,7 +167,7 @@ def SConscript(*ls, **kw): else: f = SCons.Node.FS.default_fs.File(str(fn)) if f.exists(): - file = open(str(f), "r") + file = open(f.rstr(), "r") SCons.Node.FS.default_fs.chdir(f.dir) if sconscript_chdir: old_dir = os.getcwd() @@ -276,10 +276,13 @@ def BuildDefaultGlobals(): globals['FindFile'] = FindFile globals['GetBuildPath'] = GetBuildPath globals['GetCommandHandler'] = SCons.Action.GetCommandHandler + globals['GetLaunchDir'] = GetLaunchDir globals['Help'] = Help globals['Import'] = Import globals['Library'] = SCons.Defaults.StaticLibrary globals['Object'] = SCons.Defaults.StaticObject + globals['Repository'] = SCons.Node.FS.default_fs.Repository + globals['SetBuildSignatureType'] = SetBuildSignatureType globals['StaticLibrary'] = SCons.Defaults.StaticLibrary globals['StaticObject'] = SCons.Defaults.StaticObject globals['SharedLibrary'] = SCons.Defaults.SharedLibrary @@ -294,6 +297,4 @@ def BuildDefaultGlobals(): globals['Split'] = SCons.Util.Split globals['Tool'] = SCons.Tool.Tool globals['WhereIs'] = SCons.Util.WhereIs - globals['GetLaunchDir'] = GetLaunchDir - globals['SetBuildSignatureType'] = SetBuildSignatureType return globals diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 66b4fd7..10794f5 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -185,6 +185,7 @@ target_top = None exit_status = 0 # exit status, assume success by default profiling = 0 max_drift = None +repositories = [] # utility functions @@ -792,7 +793,11 @@ def options_init(): # long = ['warn-undefined-variables'], # help = "Warn when an undefined variable is referenced.") - Option(func = opt_not_yet, future = 1, + def opt_Y(opt, arg): + global repositories + repositories.append(arg) + + Option(func = opt_Y, short = 'Y', long = ['repository'], arg = 'REPOSITORY', help = "Search REPOSITORY for source and target files.") @@ -825,10 +830,15 @@ def _SConstruct_exists(dirname=''): 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(file): + for rep in repositories: + if os.path.isfile(os.path.join(rep, sfile)): + return sfile return None @@ -932,6 +942,10 @@ def _main(): sys.path = include_dirs + sys.path + global repositories + for rep in repositories: + SCons.Node.FS.default_fs.Repository(rep) + start_time = time.time() for script in scripts: SCons.Script.SConscript.SConscript(script) |