__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import SCons.Scanner
-import re
+import copy
import os.path
+import re
+import SCons.Scanner
import SCons.Util
angle_re = re.compile('^[ \t]*#[ \t]*include[ \t]+<([\\w./\\\\]+)>', re.M)
quote_re = re.compile('^[ \t]*#[ \t]*include[ \t]+"([\\w./\\\\]+)"', re.M)
-def CScan():
+def CScan(fs = SCons.Node.FS.default_fs):
"Return a prototype Scanner instance for scanning C/C++ source files"
- return SCons.Scanner.Recursive(scan, "CScan",
- SCons.Node.FS.default_fs.File,
- [".c", ".C", ".cxx", ".cpp", ".c++",
- ".h", ".H", ".hxx", ".hpp"])
-
-def scan(filename, env, node_factory):
+ cs = CScanner(scan, "CScan", [fs, ()],
+ [".c", ".C", ".cxx", ".cpp", ".c++",
+ ".h", ".H", ".hxx", ".hpp"])
+ cs.fs = fs
+ return cs
+
+class CScanner(SCons.Scanner.Recursive):
+ def __init__(self, *args, **kw):
+ apply(SCons.Scanner.Recursive.__init__, (self,) + args, kw)
+ self.pathscanners = {}
+
+ def instance(self, env):
+ """
+ Return a unique instance of a C scanner object for a
+ given environment.
+ """
+ try:
+ dirs = tuple(SCons.Util.scons_str2nodes(env.Dictionary('CPPPATH'),
+ self.fs.Dir))
+ except:
+ dirs = ()
+ if not self.pathscanners.has_key(dirs):
+ clone = copy.copy(self)
+ clone.argument = [self.fs, dirs] # XXX reaching into object
+ self.pathscanners[dirs] = clone
+ return self.pathscanners[dirs]
+
+def scan(filename, env, args = [SCons.Node.FS.default_fs, ()]):
"""
scan(str, Environment) -> [str]
dependencies.
"""
- fs = SCons.Node.FS.default_fs
- try:
- paths = map(lambda x, dir=fs.Dir: dir(x),
- env.Dictionary("CPPPATH"))
- except KeyError:
- paths = []
+ fs, cpppath = args
try:
file = open(filename)
dir = os.path.dirname(filename)
if dir:
- source_dir = [fs.Dir(dir)]
+ source_dir = (fs.Dir(dir),)
else:
- source_dir = []
+ source_dir = ()
- return (SCons.Util.find_files(angle_includes, paths + source_dir,
- node_factory)
- + SCons.Util.find_files(quote_includes, source_dir + paths,
- node_factory))
+ return (SCons.Util.find_files(angle_includes, cpppath + source_dir,
+ fs.File)
+ + SCons.Util.find_files(quote_includes, source_dir + cpppath,
+ fs.File))
except (IOError, OSError):
return []
import SCons.Scanner.C
import unittest
import sys
+import os
import os.path
test = TestCmd.TestCmd(workdir = '')
+os.chdir(test.workpath(''))
+
# create some source files and headers:
test.write('f1.cpp',"""
def runTest(self):
env = DummyEnvironment([])
s = SCons.Scanner.C.CScan()
- deps = s.scan(test.workpath('f1.cpp'), env)
+ deps = s.instance(env).scan(test.workpath('f1.cpp'), env)
headers = ['f1.h', 'f2.h', 'fi.h']
deps_match(self, deps, headers)
def runTest(self):
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.C.CScan()
- deps = s.scan(test.workpath('f1.cpp'), env)
+ deps = s.instance(env).scan(test.workpath('f1.cpp'), env)
headers = ['f1.h', 'd1/f2.h']
deps_match(self, deps, headers)
def runTest(self):
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.C.CScan()
- deps = s.scan(test.workpath('f2.cpp'), env)
+ deps = s.instance(env).scan(test.workpath('f2.cpp'), env)
headers = ['f1.h', 'd1/f1.h', 'd1/d2/f1.h']
deps_match(self, deps, headers)
def runTest(self):
env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")])
s = SCons.Scanner.C.CScan()
- deps = s.scan(test.workpath('f2.cpp'), env)
+ deps = s.instance(env).scan(test.workpath('f2.cpp'), env)
headers = ['f1.h', 'd1/f1.h', 'd1/d2/f1.h', 'd1/d2/f4.h']
deps_match(self, deps, headers)
def runTest(self):
env = DummyEnvironment([])
s = SCons.Scanner.C.CScan()
- deps = s.scan(test.workpath('f3.cpp'), env)
+ deps = s.instance(env).scan(test.workpath('f3.cpp'), env)
headers = ['f1.h', 'f2.h', 'f3.h', 'fi.h', 'fj.h',
'd1/f1.h', 'd1/f2.h', 'd1/f3.h']
deps_match(self, deps, headers)
+class CScannerTestCase6(unittest.TestCase):
+ def runTest(self):
+ env1 = DummyEnvironment([test.workpath("d1")])
+ env2 = DummyEnvironment([test.workpath("d1/d2")])
+ s = SCons.Scanner.C.CScan()
+ s1 = s.instance(env1)
+ s2 = s.instance(env2)
+ s3 = s.instance(env1)
+ assert not s1 is s2
+ assert s1 is s3
+ deps1 = s1.scan(test.workpath('f1.cpp'), None)
+ deps2 = s2.scan(test.workpath('f1.cpp'), None)
+ headers1 = ['f1.h', 'd1/f2.h']
+ headers2 = ['f1.h', 'd1/d2/f2.h']
+ deps_match(self, deps1, headers1)
+ deps_match(self, deps2, headers2)
+
def suite():
suite = unittest.TestSuite()
suite.addTest(CScannerTestCase1())
suite.addTest(CScannerTestCase3())
suite.addTest(CScannerTestCase4())
suite.addTest(CScannerTestCase5())
+ suite.addTest(CScannerTestCase6())
return suite
if __name__ == "__main__":