diff options
| author | Steven Knight <knight@baldmt.com> | 2002-04-04 09:07:00 (GMT) |
|---|---|---|
| committer | Steven Knight <knight@baldmt.com> | 2002-04-04 09:07:00 (GMT) |
| commit | 6603cc0d6643e529da45fef6f85fcc1a0fc02ea4 (patch) | |
| tree | 4a27de7c3fd70e5af0f257ccc73aab38e343f156 /src/engine/SCons/Scanner | |
| parent | a7669bc6a02999a3375c7e732a27ded5f9bb9935 (diff) | |
| download | SCons-6603cc0d6643e529da45fef6f85fcc1a0fc02ea4.zip SCons-6603cc0d6643e529da45fef6f85fcc1a0fc02ea4.tar.gz SCons-6603cc0d6643e529da45fef6f85fcc1a0fc02ea4.tar.bz2 | |
Fix --debug=tree for directory targets (Anthony Roach)
Diffstat (limited to 'src/engine/SCons/Scanner')
| -rw-r--r-- | src/engine/SCons/Scanner/C.py | 57 | ||||
| -rw-r--r-- | src/engine/SCons/Scanner/CTests.py | 54 | ||||
| -rw-r--r-- | src/engine/SCons/Scanner/Prog.py | 87 | ||||
| -rw-r--r-- | src/engine/SCons/Scanner/ProgTests.py | 20 | ||||
| -rw-r--r-- | src/engine/SCons/Scanner/ScannerTests.py | 37 | ||||
| -rw-r--r-- | src/engine/SCons/Scanner/__init__.py | 20 |
6 files changed, 119 insertions, 156 deletions
diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 0a2654e..c81417a 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -41,45 +41,16 @@ import SCons.Util include_re = re.compile('^[ \t]*#[ \t]*include[ \t]+(<|")([\\w./\\\\]+)(>|")', re.M) -include_cache = {} - def CScan(fs = SCons.Node.FS.default_fs): """Return a prototype Scanner instance for scanning source files that use the C pre-processor""" - cs = CScanner(scan, "CScan", [fs, ()], - [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", - ".h", ".H", ".hxx", ".hpp", ".hh", - ".F", ".fpp", ".FPP"]) - cs.fs = fs + cs = SCons.Scanner.Recursive(scan, "CScan", fs, + [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", + ".h", ".H", ".hxx", ".hpp", ".hh", + ".F", ".fpp", ".FPP"]) return cs -class CScanner(SCons.Scanner.Recursive): - def __init__(self, *args, **kw): - apply(SCons.Scanner.Recursive.__init__, (self,) + args, kw) - self.hash = None - self.pathscanners = {} - - def instance(self, env): - """ - Return a unique instance of a C scanner object for a - given environment. - """ - try: - dirs = tuple(SCons.Node.arg2nodes(env.Dictionary('CPPPATH'), - self.fs.Dir)) - except: - dirs = () - if not self.pathscanners.has_key(dirs): - clone = copy.copy(self) - clone.hash = dirs - clone.argument = [self.fs, dirs] # XXX reaching into object - self.pathscanners[dirs] = clone - return self.pathscanners[dirs] - - def __hash__(self): - return hash(self.hash) - -def scan(node, env, args = [SCons.Node.FS.default_fs, ()]): +def scan(node, env, target, fs = SCons.Node.FS.default_fs): """ scan(node, Environment) -> [node] @@ -100,7 +71,21 @@ def scan(node, env, args = [SCons.Node.FS.default_fs, ()]): dependencies. """ - fs, cpppath = args + # This function caches various information in node and target: + # target.cpppath - env['CPPPATH'] converted to nodes + # node.found_includes - include files found by previous call to scan, + # keyed on cpppath + # node.includes - the result of include_re.findall() + + if not hasattr(target, 'cpppath'): + def Dir(x, dir=target.cwd, fs=fs): return fs.Dir(x,dir) + try: + target.cpppath = tuple(SCons.Node.arg2nodes(env['CPPPATH'],Dir)) + except KeyError: + target.cpppath = () + + cpppath = target.cpppath + nodes = [] try: @@ -109,7 +94,7 @@ def scan(node, env, args = [SCons.Node.FS.default_fs, ()]): if node.exists(): # cache the includes list in node so we only scan it once: - if hasattr(node, 'includes'): + if node.includes != None: includes = node.includes else: includes = include_re.findall(node.get_contents()) diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py index 684df99..f99af18 100644 --- a/src/engine/SCons/Scanner/CTests.py +++ b/src/engine/SCons/Scanner/CTests.py @@ -119,6 +119,10 @@ test.write('subdir/include/fb.h', "\n") # define some helpers: +class DummyTarget: + def __init__(self, cwd=None): + self.cwd = cwd + class DummyEnvironment: def __init__(self, listCppPath): self.path = listCppPath @@ -131,6 +135,15 @@ class DummyEnvironment: else: raise KeyError, "Dummy environment only has CPPPATH attribute." + def __getitem__(self,key): + return self.Dictionary()[key] + + def __setitem__(self,key,value): + self.Dictionary()[key] = value + + def __delitem__(self,key): + del self.Dictionary()[key] + def deps_match(self, deps, headers): scanned = map(os.path.normpath, map(str, deps)) expect = map(os.path.normpath, headers) @@ -145,15 +158,15 @@ class CScannerTestCase1(unittest.TestCase): def runTest(self): env = DummyEnvironment([]) s = SCons.Scanner.C.CScan() - deps = s.instance(env).scan(make_node('f1.cpp'), env) - headers = ['f1.h', 'f2.h', 'fi.h'] + deps = s.scan(make_node('f1.cpp'), env, DummyTarget()) + headers = ['f1.h', 'f2.h', 'fi.h'] deps_match(self, deps, map(test.workpath, headers)) class CScannerTestCase2(unittest.TestCase): def runTest(self): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.C.CScan() - deps = s.instance(env).scan(make_node('f1.cpp'), env) + deps = s.scan(make_node('f1.cpp'), env, DummyTarget()) headers = ['d1/f2.h', 'f1.h'] deps_match(self, deps, map(test.workpath, headers)) @@ -161,7 +174,7 @@ class CScannerTestCase3(unittest.TestCase): def runTest(self): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.C.CScan() - deps = s.instance(env).scan(make_node('f2.cpp'), env) + deps = s.scan(make_node('f2.cpp'), env, DummyTarget()) headers = ['d1/d2/f1.h', 'd1/f1.h', 'f1.h'] deps_match(self, deps, map(test.workpath, headers)) @@ -169,7 +182,7 @@ class CScannerTestCase4(unittest.TestCase): def runTest(self): env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")]) s = SCons.Scanner.C.CScan() - deps = s.instance(env).scan(make_node('f2.cpp'), env) + deps = s.scan(make_node('f2.cpp'), env, DummyTarget()) headers = ['d1/d2/f1.h', 'd1/d2/f4.h', 'd1/f1.h', 'f1.h'] deps_match(self, deps, map(test.workpath, headers)) @@ -177,7 +190,7 @@ class CScannerTestCase5(unittest.TestCase): def runTest(self): env = DummyEnvironment([]) s = SCons.Scanner.C.CScan() - deps = s.instance(env).scan(make_node('f3.cpp'), env) + deps = s.scan(make_node('f3.cpp'), env, DummyTarget()) # Make sure exists() gets called on the file node being # scanned, essential for cooperation with BuildDir functionality. @@ -193,35 +206,23 @@ class CScannerTestCase6(unittest.TestCase): env2 = DummyEnvironment([test.workpath("d1/d2")]) env3 = DummyEnvironment([test.workpath("d1/../d1")]) s = SCons.Scanner.C.CScan() - s1 = s.instance(env1) - s2 = s.instance(env2) - s3 = s.instance(env3) - assert not s1 is s2 - assert s1 is s3 - deps1 = s1.scan(make_node('f1.cpp'), None) - deps2 = s2.scan(make_node('f1.cpp'), None) + deps1 = s.scan(make_node('f1.cpp'), env1, DummyTarget()) + deps2 = s.scan(make_node('f1.cpp'), env2, DummyTarget()) headers1 = ['d1/f2.h', 'f1.h'] headers2 = ['d1/d2/f2.h', 'f1.h'] deps_match(self, deps1, map(test.workpath, headers1)) deps_match(self, deps2, map(test.workpath, headers2)) -class CScannerTestCase7(unittest.TestCase): - def runTest(self): - s = SCons.Scanner.C.CScan() - s1 = s.instance(DummyEnvironment([test.workpath("d1")])) - s2 = s.instance(DummyEnvironment([test.workpath("d1/../d1")])) - dict = {} - dict[s1] = 777 - assert dict[s2] == 777 - class CScannerTestCase8(unittest.TestCase): def runTest(self): fs = SCons.Node.FS.FS(test.workpath('')) env = DummyEnvironment(["include"]) s = SCons.Scanner.C.CScan(fs = fs) - deps1 = s.instance(env).scan(fs.File('fa.cpp'), None) + deps1 = s.scan(fs.File('fa.cpp'), env, DummyTarget()) fs.chdir(fs.Dir('subdir')) - deps2 = s.instance(env).scan(fs.File('#fa.cpp'), None) + target = DummyTarget(fs.getcwd()) + fs.chdir(fs.Dir('..')) + deps2 = s.scan(fs.File('#fa.cpp'), env, target) headers1 = ['include/fa.h', 'include/fb.h'] headers2 = ['subdir/include/fa.h', 'subdir/include/fb.h'] deps_match(self, deps1, headers1) @@ -233,7 +234,7 @@ class CScannerTestCase9(unittest.TestCase): fs = SCons.Node.FS.FS(test.workpath('')) s = SCons.Scanner.C.CScan(fs=fs) env = DummyEnvironment([]) - deps = s.instance(env).scan(fs.File('fa.cpp'), None) + deps = s.scan(fs.File('fa.cpp'), env, DummyTarget()) deps_match(self, deps, [ 'fa.h' ]) test.unlink('fa.h') @@ -244,7 +245,7 @@ class CScannerTestCase10(unittest.TestCase): s = SCons.Scanner.C.CScan(fs=fs) env = DummyEnvironment([]) test.write('include/fa.cpp', test.read('fa.cpp')) - deps = s.instance(env).scan(fs.File('#include/fa.cpp'), None) + deps = s.scan(fs.File('#include/fa.cpp'), env, DummyTarget()) deps_match(self, deps, [ 'include/fa.h', 'include/fb.h' ]) test.unlink('include/fa.cpp') @@ -256,7 +257,6 @@ def suite(): suite.addTest(CScannerTestCase4()) suite.addTest(CScannerTestCase5()) suite.addTest(CScannerTestCase6()) - suite.addTest(CScannerTestCase7()) suite.addTest(CScannerTestCase8()) suite.addTest(CScannerTestCase9()) suite.addTest(CScannerTestCase10()) diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py index 9ecc37b..76567ab 100644 --- a/src/engine/SCons/Scanner/Prog.py +++ b/src/engine/SCons/Scanner/Prog.py @@ -31,74 +31,49 @@ import SCons.Node.FS import SCons.Scanner import SCons.Util -class NullProgScanner: - """A do-nothing ProgScanner for Environments that have no LIBS.""" - def scan(node, env, args = []): - return [] - -null_scanner = NullProgScanner() - def ProgScan(fs = SCons.Node.FS.default_fs): """Return a prototype Scanner instance for scanning executable files for static-lib dependencies""" - ps = ProgScanner(scan, "ProgScan") - ps.fs = fs + ps = SCons.Scanner.Base(scan, "ProgScan", fs) return ps -class ProgScanner(SCons.Scanner.Base): - def __init__(self, *args, **kw): - apply(SCons.Scanner.Base.__init__, (self,) + args, kw) - self.hash = None - self.pathscanners = {} - - def instance(self, env): - """ - Return a unique instance of a Prog scanner object for a - given environment. - """ - try: - libs = env.Dictionary('LIBS') - except KeyError: - # There are no LIBS in this environment, so just return the - # fake "scanner" instance that always returns a null list. - return null_scanner - if SCons.Util.is_String(libs): - libs = string.split(libs) +def scan(node, env, target, fs): + """ + This scanner scans program files for static-library + dependencies. It will search the LIBPATH environment variable + for libraries specified in the LIBS variable, returning any + files it finds as dependencies. + """ - try: - dirs = tuple(SCons.Node.arg2nodes(env.Dictionary('LIBPATH'), - self.fs.Dir)) - except: - dirs = () + # This function caches information in target: + # target.libpath - env['LIBPATH'] converted to nodes + if not hasattr(target, 'libpath'): + def Dir(x, dir=target.cwd, fs=fs): return fs.Dir(x,dir) try: - prefix = env.Dictionary('LIBPREFIX') + target.libpath = tuple(SCons.Node.arg2nodes(env['LIBPATH'],Dir)) except KeyError: - prefix = '' + target.libpath = () + + libpath = target.libpath - try: - suffix = env.Dictionary('LIBSUFFIX') - except KeyError: - suffix = '' + try: + libs = env.Dictionary('LIBS') + except KeyError: + # There are no LIBS in this environment, so just return a null list: + return [] + if SCons.Util.is_String(libs): + libs = string.split(libs) - key = (dirs, tuple(libs), prefix, suffix) - if not self.pathscanners.has_key(key): - clone = copy.copy(self) - clone.hash = key - clone.argument = [self.fs, dirs, libs, prefix, suffix] # XXX reaching into object - self.pathscanners[key] = clone - return self.pathscanners[key] + try: + prefix = env.Dictionary('LIBPREFIX') + except KeyError: + prefix = '' - def __hash__(self): - return hash(self.hash) + try: + suffix = env.Dictionary('LIBSUFFIX') + except KeyError: + suffix = '' -def scan(node, env, args = [SCons.Node.FS.default_fs, (), [], '', '']): - """ - This scanner scans program files for static-library - dependencies. It will search the LIBPATH environment variable - for libraries specified in the LIBS variable, returning any - files it finds as dependencies. - """ - fs, libpath, libs, prefix, suffix = args libs = map(lambda x, s=suffix, p=prefix: p + x + s, libs) return SCons.Node.FS.find_files(libs, libpath, fs.File) diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py index b59e554..ea3d00d 100644 --- a/src/engine/SCons/Scanner/ProgTests.py +++ b/src/engine/SCons/Scanner/ProgTests.py @@ -42,6 +42,10 @@ for h in libs: # define some helpers: +class DummyTarget: + def __init__(self, cwd=None): + self.cwd = cwd + class DummyEnvironment: def __init__(self, **kw): self._dict = kw @@ -54,6 +58,14 @@ class DummyEnvironment: return self._dict[args[0]] else: return map(lambda x, s=self: s._dict[x], args) + def __getitem__(self,key): + return self.Dictionary()[key] + + def __setitem__(self,key,value): + self.Dictionary()[key] = value + + def __delitem__(self,key): + del self.Dictionary()[key] def deps_match(deps, libs): deps=map(str, deps) @@ -70,7 +82,7 @@ class ProgScanTestCase1(unittest.TestCase): env = DummyEnvironment(LIBPATH=[ test.workpath("") ], LIBS=[ 'l1', 'l2', 'l3' ]) s = SCons.Scanner.Prog.ProgScan() - deps = s.instance(env).scan('dummy', env) + deps = s.scan('dummy', env, DummyTarget()) assert deps_match(deps, ['l1.lib']), map(str, deps) class ProgScanTestCase2(unittest.TestCase): @@ -79,7 +91,7 @@ class ProgScanTestCase2(unittest.TestCase): ["", "d1", "d1/d2" ]), LIBS=[ 'l1', 'l2', 'l3' ]) s = SCons.Scanner.Prog.ProgScan() - deps = s.instance(env).scan('dummy', env) + deps = s.scan('dummy', env, DummyTarget()) assert deps_match(deps, ['l1.lib', 'd1/l2.lib', 'd1/d2/l3.lib' ]), map(str, deps) class ProgScanTestCase3(unittest.TestCase): @@ -88,7 +100,7 @@ class ProgScanTestCase3(unittest.TestCase): test.workpath("d1"), LIBS='l2 l3') s = SCons.Scanner.Prog.ProgScan() - deps = s.instance(env).scan('dummy', env) + deps = s.scan('dummy', env, DummyTarget()) assert deps_match(deps, ['d1/l2.lib', 'd1/d2/l3.lib']), map(str, deps) def suite(): @@ -104,7 +116,7 @@ def suite(): test.workpath("d1"), LIBS=u'l2 l3') s = SCons.Scanner.Prog.ProgScan() - deps = s.instance(env).scan('dummy', env) + deps = s.scan('dummy', env, DummyTarget()) assert deps_match(deps, ['d1/l2.lib', 'd1/d2/l3.lib']), map(str, deps) suite.addTest(ProgScanTestCase4()) \n""" diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index 76df18e..fce4078 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -27,11 +27,16 @@ import unittest import SCons.Scanner import sys +class DummyTarget: + cwd = None + + class ScannerTestBase: - def func(self, filename, env, *args): + def func(self, filename, env, target, *args): self.filename = filename self.env = env + self.target = target if len(args) > 0: self.arg = args[0] @@ -41,7 +46,7 @@ class ScannerTestBase: def test(self, scanner, env, filename, deps, *args): self.deps = deps - scanned = scanner.scan(filename, env) + scanned = scanner.scan(filename, env, DummyTarget()) scanned_strs = map(lambda x: str(x), scanned) self.failUnless(self.filename == filename, "the filename was passed incorrectly") @@ -67,10 +72,9 @@ class ScannerPositionalTestCase(ScannerTestBase, unittest.TestCase): env.VARIABLE = "var1" self.test(s, env, 'f1.cpp', ['f1.h', 'f1.hpp']) - env = DummyEnvironment() - env.VARIABLE = "i1" - i = s.instance(env) - self.test(i, env, 'i1.cpp', ['i1.h', 'i1.hpp']) + env = DummyEnvironment() + env.VARIABLE = "i1" + self.test(s, env, 'i1.cpp', ['i1.h', 'i1.hpp']) class ScannerKeywordTestCase(ScannerTestBase, unittest.TestCase): "Test the Scanner.Base class using the keyword argument" @@ -80,10 +84,9 @@ class ScannerKeywordTestCase(ScannerTestBase, unittest.TestCase): env.VARIABLE = "var2" self.test(s, env, 'f2.cpp', ['f2.h', 'f2.hpp']) - env = DummyEnvironment() - env.VARIABLE = "i2" - i = s.instance(env) - self.test(i, env, 'i2.cpp', ['i2.h', 'i2.hpp']) + env = DummyEnvironment() + env.VARIABLE = "i2" + self.test(s, env, 'i2.cpp', ['i2.h', 'i2.hpp']) class ScannerPositionalArgumentTestCase(ScannerTestBase, unittest.TestCase): "Test the Scanner.Base class using both position and optional arguments" @@ -94,10 +97,9 @@ class ScannerPositionalArgumentTestCase(ScannerTestBase, unittest.TestCase): env.VARIABLE = "var3" self.test(s, env, 'f3.cpp', ['f3.h', 'f3.hpp'], arg) - env = DummyEnvironment() - env.VARIABLE = "i3" - i = s.instance(env) - self.test(i, env, 'i3.cpp', ['i3.h', 'i3.hpp'], arg) + env = DummyEnvironment() + env.VARIABLE = "i3" + self.test(s, env, 'i3.cpp', ['i3.h', 'i3.hpp'], arg) class ScannerKeywordArgumentTestCase(ScannerTestBase, unittest.TestCase): "Test the Scanner.Base class using both keyword and optional arguments" @@ -109,10 +111,9 @@ class ScannerKeywordArgumentTestCase(ScannerTestBase, unittest.TestCase): env.VARIABLE = "var4" self.test(s, env, 'f4.cpp', ['f4.h', 'f4.hpp'], arg) - env = DummyEnvironment() - env.VARIABLE = "i4" - i = s.instance(env) - self.test(i, env, 'i4.cpp', ['i4.h', 'i4.hpp'], arg) + env = DummyEnvironment() + env.VARIABLE = "i4" + self.test(s, env, 'i4.cpp', ['i4.h', 'i4.hpp'], arg) class ScannerHashTestCase(ScannerTestBase, unittest.TestCase): "Test the Scanner.Base class __hash__() method" diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 53c67e4..b2e04a3 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -97,7 +97,7 @@ class Base: self.skeys = skeys self.node_factory = node_factory - def scan(self, node, env): + def scan(self, node, env, target): """ This method scans a single object. 'node' is the node that will be passed to the scanner function, and 'env' is the @@ -106,9 +106,9 @@ class Base: """ if not self.argument is _null: - list = self.function(node, env, self.argument) + list = self.function(node, env, target, self.argument) else: - list = self.function(node, env) + list = self.function(node, env, target) kw = {} if hasattr(node, 'dir'): kw['directory'] = node.dir @@ -119,16 +119,6 @@ class Base: nodes.append(l) return nodes - def instance(self, env): - """ - Return an instance of a Scanner object for use in scanning. - - In the base class, we just return the scanner itself. - Other Scanner classes may use this to clone copies and/or - return unique instances as needed. - """ - return self - def __cmp__(self, other): return cmp(self.__dict__, other.__dict__) @@ -143,7 +133,7 @@ class Recursive(Base): list of all dependencies. """ - def scan(self, node, env): + def scan(self, node, env, target): """ This method does the actual scanning. 'node' is the node that will be passed to the scanner function, and 'env' is the @@ -158,7 +148,7 @@ class Recursive(Base): while nodes: n = nodes.pop(0) d = filter(lambda x, seen=seen: not seen.has_key(x), - Base.scan(self, n, env)) + Base.scan(self, n, env, target)) if d: deps.extend(d) nodes.extend(d) |
