summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Scanner
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-11-20 17:58:56 (GMT)
committerSteven Knight <knight@baldmt.com>2001-11-20 17:58:56 (GMT)
commitfa11b8d2fa2e3adc18588992ff869b1f1457c03f (patch)
tree569699b30c9de0106b55352d89b2d03ef8cfe086 /src/engine/SCons/Scanner
parent76166c77f852377b6139a9414cc355fe2661a0e7 (diff)
downloadSCons-fa11b8d2fa2e3adc18588992ff869b1f1457c03f.zip
SCons-fa11b8d2fa2e3adc18588992ff869b1f1457c03f.tar.gz
SCons-fa11b8d2fa2e3adc18588992ff869b1f1457c03f.tar.bz2
Crain: Finish LIBS, LIBPATH, CPPPATH
Diffstat (limited to 'src/engine/SCons/Scanner')
-rw-r--r--src/engine/SCons/Scanner/C.py55
-rw-r--r--src/engine/SCons/Scanner/CTests.py47
-rw-r--r--src/engine/SCons/Scanner/Prog.py66
-rw-r--r--src/engine/SCons/Scanner/ProgTests.py93
4 files changed, 206 insertions, 55 deletions
diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py
index 0d74dc5..e2842e1 100644
--- a/src/engine/SCons/Scanner/C.py
+++ b/src/engine/SCons/Scanner/C.py
@@ -33,6 +33,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.Scanner
import re
import os.path
+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)
@@ -44,28 +45,6 @@ def CScan():
s.name = "CScan"
return s
-def find_files(filenames, paths):
- """
- find_files([str], [str]) -> [str]
-
- filenames - a list of filenames to find
- paths - a list of paths to search in
-
- returns - the fullnames of the files
-
- Only the first fullname found is returned for each filename, and any
- file that aren't found are ignored.
- """
- fullnames = []
- for filename in filenames:
- for path in paths:
- fullname = os.path.join(path, filename)
- if os.path.exists(fullname):
- fullnames.append(fullname)
- break
-
- return fullnames
-
def scan(filename, env, node_factory):
"""
scan(str, Environment) -> [str]
@@ -87,22 +66,24 @@ def scan(filename, env, node_factory):
dependencies.
"""
- if hasattr(env, "CPPPATH"):
- paths = env.CPPPATH
- else:
+ try:
+ paths = env.Dictionary("CPPPATH")
+ except KeyError:
paths = []
-
- file = open(filename)
- contents = file.read()
- file.close()
- angle_includes = angle_re.findall(contents)
- quote_includes = quote_re.findall(contents)
+ try:
+ file = open(filename)
+ contents = file.read()
+ file.close()
- source_dir = os.path.dirname(filename)
-
- deps = (find_files(angle_includes, paths + [source_dir])
- + find_files(quote_includes, [source_dir] + paths))
+ angle_includes = angle_re.findall(contents)
+ quote_includes = quote_re.findall(contents)
- deps = map(node_factory, deps)
- return deps
+ source_dir = os.path.dirname(filename)
+
+ return (SCons.Util.find_files(angle_includes, paths + [source_dir],
+ node_factory)
+ + SCons.Util.find_files(quote_includes, [source_dir] + paths,
+ node_factory))
+ except OSError:
+ return []
diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py
index 8b8aeb5..e6bd29e 100644
--- a/src/engine/SCons/Scanner/CTests.py
+++ b/src/engine/SCons/Scanner/CTests.py
@@ -27,6 +27,7 @@ import TestCmd
import SCons.Scanner.C
import unittest
import sys
+import os.path
test = TestCmd.TestCmd(workdir = '')
@@ -88,55 +89,65 @@ for h in headers:
# define some helpers:
class DummyEnvironment:
- pass
+ def __init__(self, listCppPath):
+ self.path = listCppPath
+
+ def Dictionary(self, *args):
+ if not args:
+ return { 'CPPPATH': self.path }
+ elif len(args) == 1 and args[0] == 'CPPPATH':
+ return self.path
+ else:
+ raise KeyError, "Dummy environment only has CPPPATH attribute."
def deps_match(deps, headers):
- return deps.sort() == map(test.workpath, headers).sort()
+ deps = map(str, deps)
+ headers = map(test.workpath, headers)
+ deps.sort()
+ headers.sort()
+ return map(os.path.normpath, deps) == \
+ map(os.path.normpath, headers)
# define some tests:
class CScannerTestCase1(unittest.TestCase):
def runTest(self):
- env = DummyEnvironment
+ env = DummyEnvironment([])
s = SCons.Scanner.C.CScan()
deps = s.scan(test.workpath('f1.cpp'), env)
- self.failUnless(deps_match(deps, ['f1.h', 'f2.h']))
+ self.failUnless(deps_match(deps, ['f1.h', 'f2.h']), map(str, deps))
class CScannerTestCase2(unittest.TestCase):
def runTest(self):
- env = DummyEnvironment
- env.CPPPATH = [test.workpath("d1")]
+ env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.C.CScan()
deps = s.scan(test.workpath('f1.cpp'), env)
headers = ['f1.h', 'd1/f2.h']
- self.failUnless(deps_match(deps, headers))
+ self.failUnless(deps_match(deps, headers), map(str, deps))
class CScannerTestCase3(unittest.TestCase):
def runTest(self):
- env = DummyEnvironment
- env.CPPPATH = [test.workpath("d1")]
+ env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.C.CScan()
deps = s.scan(test.workpath('f2.cpp'), env)
- headers = ['f1.h', 'd1/f2.h', 'd1/d2/f1.h']
- self.failUnless(deps_match(deps, headers))
-
+ headers = ['f1.h', 'd1/f1.h', 'd1/d2/f1.h']
+ self.failUnless(deps_match(deps, headers), map(str, deps))
class CScannerTestCase4(unittest.TestCase):
def runTest(self):
- env = DummyEnvironment
- env.CPPPATH = [test.workpath("d1"), test.workpath("d1/d2")]
+ env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")])
s = SCons.Scanner.C.CScan()
deps = s.scan(test.workpath('f2.cpp'), env)
- headers = ['f1.h', 'd1/f2.h', 'd1/d2/f1.h', 'd1/d2/f4.h']
- self.failUnless(deps_match(deps, headers))
+ headers = ['f1.h', 'd1/f1.h', 'd1/d2/f1.h', 'd1/d2/f4.h']
+ self.failUnless(deps_match(deps, headers), map(str, deps))
class CScannerTestCase5(unittest.TestCase):
def runTest(self):
- env = DummyEnvironment
+ env = DummyEnvironment([])
s = SCons.Scanner.C.CScan()
deps = s.scan(test.workpath('f3.cpp'), env)
headers = ['f1.h', 'f2.h', 'f3.h', 'd1/f1.h', 'd1/f2.h', 'd1/f3.h']
- self.failUnless(deps_match(deps, headers))
+ self.failUnless(deps_match(deps, headers), map(str, deps))
def suite():
suite = unittest.TestSuite()
diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py
new file mode 100644
index 0000000..f9d352c
--- /dev/null
+++ b/src/engine/SCons/Scanner/Prog.py
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 2001 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Scanner
+import SCons.Node.FS
+import SCons.Util
+
+def ProgScan():
+ """Return a Scanner instance for scanning executable files
+ for static-lib dependencies"""
+ s = SCons.Scanner.Scanner(scan, SCons.Node.FS.default_fs.File)
+ s.name = "ProgScan"
+ return s
+
+def scan(filename, env, node_factory):
+ """
+ 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:
+ paths = env.Dictionary("LIBPATH")
+ except KeyError:
+ paths = []
+
+ try:
+ libs = env.Dictionary("LIBS")
+ except KeyError:
+ libs = []
+
+ try:
+ prefix = env.Dictionary("LIBPREFIX")
+ except KeyError:
+ prefix=''
+
+ try:
+ suffix = env.Dictionary("LIBSUFFIX")
+ except KeyError:
+ suffix=''
+
+ libs = map(lambda x, s=suffix, p=prefix: p + x + s, libs)
+ return SCons.Util.find_files(libs, paths, node_factory)
diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py
new file mode 100644
index 0000000..6c3f5e4
--- /dev/null
+++ b/src/engine/SCons/Scanner/ProgTests.py
@@ -0,0 +1,93 @@
+#
+# Copyright (c) 2001 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestCmd
+import SCons.Scanner.Prog
+import unittest
+import sys
+import os.path
+
+test = TestCmd.TestCmd(workdir = '')
+
+test.subdir('d1', ['d1', 'd2'])
+
+libs = [ 'l1.lib', 'd1/l2.lib', 'd1/d2/l3.lib' ]
+
+for h in libs:
+ test.write(h, " ")
+
+# define some helpers:
+
+class DummyEnvironment:
+ def __init__(self, **kw):
+ self._dict = kw
+ self._dict['LIBSUFFIX'] = '.lib'
+
+ def Dictionary(self, *args):
+ if not args:
+ return self._dict
+ elif len(args) == 1:
+ return self._dict[args[0]]
+ else:
+ return map(lambda x, s=self: s._dict[x], args)
+
+def deps_match(deps, libs):
+ deps=map(str, deps)
+ deps.sort()
+ libs.sort()
+ return map(os.path.normpath, deps) == \
+ map(os.path.normpath,
+ map(test.workpath, libs))
+
+# define some tests:
+
+class ProgScanTestCase1(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment(LIBPATH=[ test.workpath("") ],
+ LIBS=[ 'l1', 'l2', 'l3' ])
+ s = SCons.Scanner.Prog.ProgScan()
+ deps = s.scan('dummy', env)
+ assert deps_match(deps, ['l1.lib']), map(str, deps)
+
+class ProgScanTestCase2(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment(LIBPATH=map(test.workpath,
+ ["", "d1", "d1/d2" ]),
+ LIBS=[ 'l1', 'l2', 'l3' ])
+ s = SCons.Scanner.Prog.ProgScan()
+ deps = s.scan('dummy', env)
+ assert deps_match(deps, ['l1.lib', 'd1/l2.lib', 'd1/d2/l3.lib' ]), map(str, deps)
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(ProgScanTestCase1())
+ suite.addTest(ProgScanTestCase2())
+ return suite
+
+if __name__ == "__main__":
+ runner = unittest.TextTestRunner()
+ result = runner.run(suite())
+ if not result.wasSuccessful():
+ sys.exit(1)