summaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/SCons/Action.py14
-rw-r--r--src/engine/SCons/ActionTests.py14
-rw-r--r--src/engine/SCons/Environment.py13
-rw-r--r--src/engine/SCons/EnvironmentTests.py48
-rw-r--r--src/engine/SCons/Node/FS.py44
-rw-r--r--src/engine/SCons/Node/FSTests.py50
-rw-r--r--src/engine/SCons/Node/NodeTests.py12
-rw-r--r--src/engine/SCons/Node/__init__.py3
-rw-r--r--src/engine/SCons/Script/SConscript.py7
-rw-r--r--src/engine/SCons/Script/__init__.py16
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)