summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Scanner
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-12-31 02:51:50 (GMT)
committerSteven Knight <knight@baldmt.com>2001-12-31 02:51:50 (GMT)
commit74bc0282241e4d35b225660fe783955629ed234a (patch)
treecf4b0175cee4670e6b366e7a4c2218dc3bce508f /src/engine/SCons/Scanner
parent19ece17e5e025b7b9278a846eea60c8d12be438a (diff)
downloadSCons-74bc0282241e4d35b225660fe783955629ed234a.zip
SCons-74bc0282241e4d35b225660fe783955629ed234a.tar.gz
SCons-74bc0282241e4d35b225660fe783955629ed234a.tar.bz2
General performance tweaks
Diffstat (limited to 'src/engine/SCons/Scanner')
-rw-r--r--src/engine/SCons/Scanner/C.py45
-rw-r--r--src/engine/SCons/Scanner/CTests.py29
-rw-r--r--src/engine/SCons/Scanner/Prog.py2
-rw-r--r--src/engine/SCons/Scanner/__init__.py31
4 files changed, 57 insertions, 50 deletions
diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py
index a5aa02d..2c51223 100644
--- a/src/engine/SCons/Scanner/C.py
+++ b/src/engine/SCons/Scanner/C.py
@@ -36,8 +36,7 @@ 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)
+include_re = re.compile('^[ \t]*#[ \t]*include[ \t]+(<|")([\\w./\\\\]+)(>|")', re.M)
def CScan(fs = SCons.Node.FS.default_fs):
"Return a prototype Scanner instance for scanning C/C++ source files"
@@ -73,9 +72,9 @@ class CScanner(SCons.Scanner.Recursive):
def __hash__(self):
return hash(self.hash)
-def scan(filename, env, args = [SCons.Node.FS.default_fs, ()]):
+def scan(node, env, args = [SCons.Node.FS.default_fs, ()]):
"""
- scan(str, Environment) -> [str]
+ scan(node, Environment) -> [node]
the C/C++ dependency scanner function
@@ -95,23 +94,29 @@ def scan(filename, env, args = [SCons.Node.FS.default_fs, ()]):
"""
fs, cpppath = args
+ nodes = []
- if fs.File(filename, fs.Top).exists():
- file = open(filename)
- contents = file.read()
- file.close()
+ if node.exists():
- angle_includes = angle_re.findall(contents)
- quote_includes = quote_re.findall(contents)
-
- dir = os.path.dirname(filename)
- if dir:
- source_dir = (fs.Dir(dir, fs.Top),)
+ # cache the includes list in node so we only scan it once:
+ if hasattr(node, 'includes'):
+ includes = node.includes
else:
- source_dir = ( fs.Top, )
+ includes = include_re.findall(node.get_contents())
+ node.includes = includes
+
+ source_dir = node.get_dir()
+
+ for include in includes:
+ if include[0] == '"':
+ node = SCons.Util.find_file(include[1], (source_dir,) + cpppath,
+ fs.File)
+ else:
+ node = SCons.Util.find_file(include[1], cpppath + (source_dir,),
+ fs.File)
+
+ if not node is None:
+ nodes.append(node)
+
+ return nodes
- return (SCons.Util.find_files(angle_includes, cpppath + source_dir,
- fs.File)
- + SCons.Util.find_files(quote_includes, source_dir + cpppath,
- fs.File))
- return []
diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py
index c9cc5ea..70fc2b4 100644
--- a/src/engine/SCons/Scanner/CTests.py
+++ b/src/engine/SCons/Scanner/CTests.py
@@ -138,13 +138,16 @@ def deps_match(self, deps, headers):
expect.sort()
self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
+def make_node(filename):
+ return SCons.Node.FS.default_fs.File(test.workpath(filename))
+
# define some tests:
class CScannerTestCase1(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([])
s = SCons.Scanner.C.CScan()
- deps = s.instance(env).scan(test.workpath('f1.cpp'), env)
+ deps = s.instance(env).scan(make_node('f1.cpp'), env)
headers = ['f1.h', 'f2.h', 'fi.h']
deps_match(self, deps, map(test.workpath, headers))
@@ -152,7 +155,7 @@ class CScannerTestCase2(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.C.CScan()
- deps = s.instance(env).scan(test.workpath('f1.cpp'), env)
+ deps = s.instance(env).scan(make_node('f1.cpp'), env)
headers = ['f1.h', 'd1/f2.h']
deps_match(self, deps, map(test.workpath, headers))
@@ -160,7 +163,7 @@ class CScannerTestCase3(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.C.CScan()
- deps = s.instance(env).scan(test.workpath('f2.cpp'), env)
+ deps = s.instance(env).scan(make_node('f2.cpp'), env)
headers = ['f1.h', 'd1/f1.h', 'd1/d2/f1.h']
deps_match(self, deps, map(test.workpath, headers))
@@ -168,7 +171,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(test.workpath('f2.cpp'), env)
+ deps = s.instance(env).scan(make_node('f2.cpp'), env)
headers = ['f1.h', 'd1/f1.h', 'd1/d2/f1.h', 'd1/d2/f4.h']
deps_match(self, deps, map(test.workpath, headers))
@@ -176,7 +179,7 @@ class CScannerTestCase5(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([])
s = SCons.Scanner.C.CScan()
- deps = s.instance(env).scan(test.workpath('f3.cpp'), env)
+ deps = s.instance(env).scan(make_node('f3.cpp'), env)
# Make sure exists() gets called on the file node being
# scanned, essential for cooperation with BuildDir functionality.
@@ -197,8 +200,8 @@ class CScannerTestCase6(unittest.TestCase):
s3 = s.instance(env3)
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)
+ deps1 = s1.scan(make_node('f1.cpp'), None)
+ deps2 = s2.scan(make_node('f1.cpp'), None)
headers1 = ['f1.h', 'd1/f2.h']
headers2 = ['f1.h', 'd1/d2/f2.h']
deps_match(self, deps1, map(test.workpath, headers1))
@@ -218,9 +221,9 @@ class CScannerTestCase8(unittest.TestCase):
fs = SCons.Node.FS.FS(test.workpath(''))
env = DummyEnvironment(["include"])
s = SCons.Scanner.C.CScan(fs = fs)
- deps1 = s.instance(env).scan(test.workpath('fa.cpp'), None)
+ deps1 = s.instance(env).scan(make_node('fa.cpp'), None)
fs.chdir(fs.Dir('subdir'))
- deps2 = s.instance(env).scan(test.workpath('fa.cpp'), None)
+ deps2 = s.instance(env).scan(make_node('fa.cpp'), None)
headers1 = ['include/fa.h', 'include/fb.h']
headers2 = ['subdir/include/fa.h', 'subdir/include/fb.h']
deps_match(self, deps1, headers1)
@@ -232,8 +235,8 @@ class CScannerTestCase9(unittest.TestCase):
s = SCons.Scanner.C.CScan(fs=fs)
env = DummyEnvironment([])
test.write('fa.h','\n')
- deps = s.instance(env).scan('fa.cpp', None)
- deps_match(self, deps, [ 'fa.h' ])
+ deps = s.instance(env).scan(make_node('fa.cpp'), None)
+ deps_match(self, deps, [ test.workpath('fa.h') ])
test.unlink('fa.h')
class CScannerTestCase10(unittest.TestCase):
@@ -243,8 +246,8 @@ 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('include/fa.cpp', None)
- deps_match(self, deps, [ 'include/fa.h', 'include/fb.h' ])
+ deps = s.instance(env).scan(make_node('include/fa.cpp'), None)
+ deps_match(self, deps, [ test.workpath('include/fa.h'), test.workpath('include/fb.h') ])
test.unlink('include/fa.cpp')
def suite():
diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py
index cbbfb42..0182cda 100644
--- a/src/engine/SCons/Scanner/Prog.py
+++ b/src/engine/SCons/Scanner/Prog.py
@@ -32,7 +32,7 @@ def ProgScan():
files for static-lib dependencies"""
return SCons.Scanner.Base(scan, "ProgScan", SCons.Node.FS.default_fs.File)
-def scan(filename, env, node_factory):
+def scan(node, env, node_factory):
"""
This scanner scans program files for static-library
dependencies. It will search the LIBPATH environment variable
diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py
index ba37edc..52eae8e 100644
--- a/src/engine/SCons/Scanner/__init__.py
+++ b/src/engine/SCons/Scanner/__init__.py
@@ -90,18 +90,18 @@ class Base:
self.argument = argument
self.skeys = skeys
- def scan(self, filename, env):
+ def scan(self, node, env):
"""
- This method scans a single object. 'filename' is the filename
+ This method scans a single object. 'node' is the node
that will be passed to the scanner function, and 'env' is the
environment that will be passed to the scanner function. A list of
direct dependency nodes for the specified filename will be returned.
"""
if not self.argument is _null:
- return self.function(filename, env, self.argument)
+ return self.function(node, env, self.argument)
else:
- return self.function(filename, env)
+ return self.function(node, env)
def instance(self, env):
"""
@@ -127,28 +127,27 @@ class Recursive(Base):
list of all dependencies.
"""
- def scan(self, filename, env):
+ def scan(self, node, env):
"""
- This method does the actual scanning. 'filename' is the filename
+ This method does the actual scanning. 'node' is the node
that will be passed to the scanner function, and 'env' is the
environment that will be passed to the scanner function. An
aggregate list of dependency nodes for the specified filename
and any of its scanned dependencies will be returned.
"""
- files = [filename]
- seen = [filename]
+ nodes = [node]
+ seen = [node]
deps = []
- while files:
- f = files.pop(0)
+ while nodes:
+ n = nodes.pop(0)
if not self.argument is _null:
- d = self.function(f, env, self.argument)
+ d = self.function(n, env, self.argument)
else:
- d = self.function(f, env)
- d = filter(lambda x, seen=seen: str(x) not in seen, d)
+ d = self.function(n, env)
+ d = filter(lambda x, seen=seen: x not in seen, d)
if d:
deps.extend(d)
- s = map(str, d)
- seen.extend(s)
- files.extend(s)
+ seen.extend(d)
+ nodes.extend(d)
return deps