summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Scanner
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-05-19 17:49:55 (GMT)
committerSteven Knight <knight@baldmt.com>2004-05-19 17:49:55 (GMT)
commit04ebe107191659f805bd63148c61c1026efeb686 (patch)
tree9122729d1120c1119fe10ff360f4675789ca8f9b /src/engine/SCons/Scanner
parent12d2ae1193b9e32e0164218bb73240791914f976 (diff)
downloadSCons-04ebe107191659f805bd63148c61c1026efeb686.zip
SCons-04ebe107191659f805bd63148c61c1026efeb686.tar.gz
SCons-04ebe107191659f805bd63148c61c1026efeb686.tar.bz2
Fix spurious rebuilds/reinstalls of header files and circular dependencies with generated header files by allowing Scanners to be associated explicitly with Builders, not just through Scanner file suffix lists.
Diffstat (limited to 'src/engine/SCons/Scanner')
-rw-r--r--src/engine/SCons/Scanner/CTests.py3
-rw-r--r--src/engine/SCons/Scanner/FortranTests.py3
-rw-r--r--src/engine/SCons/Scanner/IDLTests.py3
-rw-r--r--src/engine/SCons/Scanner/ScannerTests.py73
-rw-r--r--src/engine/SCons/Scanner/__init__.py35
5 files changed, 117 insertions, 0 deletions
diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py
index f63060a..693ec18 100644
--- a/src/engine/SCons/Scanner/CTests.py
+++ b/src/engine/SCons/Scanner/CTests.py
@@ -193,6 +193,9 @@ class DummyEnvironment(UserDict.UserDict):
path = [path]
return map(self.subst, path)
+ def get_calculator(self):
+ return None
+
if os.path.normcase('foo') == os.path.normcase('FOO'):
my_normpath = os.path.normcase
else:
diff --git a/src/engine/SCons/Scanner/FortranTests.py b/src/engine/SCons/Scanner/FortranTests.py
index e69f99e..766f0ee 100644
--- a/src/engine/SCons/Scanner/FortranTests.py
+++ b/src/engine/SCons/Scanner/FortranTests.py
@@ -168,6 +168,9 @@ class DummyEnvironment:
path = [path]
return map(self.subst, path)
+ def get_calculator(self):
+ return None
+
def deps_match(self, deps, headers):
scanned = map(os.path.normpath, map(str, deps))
expect = map(os.path.normpath, headers)
diff --git a/src/engine/SCons/Scanner/IDLTests.py b/src/engine/SCons/Scanner/IDLTests.py
index c20dedc..876f492 100644
--- a/src/engine/SCons/Scanner/IDLTests.py
+++ b/src/engine/SCons/Scanner/IDLTests.py
@@ -218,6 +218,9 @@ class DummyEnvironment:
def __delitem__(self,key):
del self.Dictionary()[key]
+ def get_calculator(self):
+ return None
+
global my_normpath
my_normpath = os.path.normpath
diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py
index 4e662a2..a0c6f01 100644
--- a/src/engine/SCons/Scanner/ScannerTests.py
+++ b/src/engine/SCons/Scanner/ScannerTests.py
@@ -65,6 +65,17 @@ class FindPathDirsTestCase(unittest.TestCase):
class ScannerTestCase(unittest.TestCase):
+ def test_creation(self):
+ """Test creation of Scanner objects through the Scanner() function"""
+ def func(self):
+ pass
+ s = SCons.Scanner.Scanner(func)
+ assert isinstance(s, SCons.Scanner.Base), s
+ s = SCons.Scanner.Scanner({})
+ assert isinstance(s, SCons.Scanner.Selector), s
+
+class BaseTestCase(unittest.TestCase):
+
def func(self, filename, env, target, *args):
self.filename = filename
self.env = env
@@ -192,6 +203,66 @@ class ScannerTestCase(unittest.TestCase):
self.failUnless(sk == ['.3', '.4'],
"sk was %s, not ['.3', '.4']")
+ def test_select(self):
+ """Test the Scanner.Base select() method"""
+ scanner = SCons.Scanner.Base(function = self.func)
+ s = scanner.select('.x')
+ assert s is scanner, s
+
+class SelectorTestCase(unittest.TestCase):
+ class skey:
+ def __init__(self, key):
+ self.key = key
+ def scanner_key(self):
+ return self.key
+
+ def test___init__(self):
+ """Test creation of Scanner.Selector object"""
+ s = SCons.Scanner.Selector({})
+ assert isinstance(s, SCons.Scanner.Selector), s
+ assert s.dict == {}, s.dict
+
+ def test___call__(self):
+ """Test calling Scanner.Selector objects"""
+ called = []
+ def s1func(node, env, path, called=called):
+ called.append('s1func')
+ called.append(node)
+ return []
+ def s2func(node, env, path, called=called):
+ called.append('s2func')
+ called.append(node)
+ return []
+ s1 = SCons.Scanner.Base(s1func)
+ s2 = SCons.Scanner.Base(s2func)
+ selector = SCons.Scanner.Selector({'.x' : s1, '.y' : s2})
+ nx = self.skey('.x')
+ selector(nx, None, [])
+ assert called == ['s1func', nx], called
+ del called[:]
+ ny = self.skey('.y')
+ selector(ny, None, [])
+ assert called == ['s2func', ny], called
+
+ def test_select(self):
+ """Test the Scanner.Selector select() method"""
+ selector = SCons.Scanner.Selector({'.x' : 1, '.y' : 2})
+ s = selector.select(self.skey('.x'))
+ assert s == 1, s
+ s = selector.select(self.skey('.y'))
+ assert s == 2, s
+ s = selector.select(self.skey('.z'))
+ assert s is None, s
+
+ def test_add_scanner(self):
+ """Test the Scanner.Selector add_scanner() method"""
+ selector = SCons.Scanner.Selector({'.x' : 1, '.y' : 2})
+ s = selector.select(self.skey('.z'))
+ assert s is None, s
+ selector.add_scanner('.z', 3)
+ s = selector.select(self.skey('.z'))
+ assert s == 3, s
+
class CurrentTestCase(unittest.TestCase):
def test_class(self):
"""Test the Scanner.Current class"""
@@ -355,6 +426,8 @@ def suite():
tclasses = [
FindPathDirsTestCase,
ScannerTestCase,
+ BaseTestCase,
+ SelectorTestCase,
CurrentTestCase,
ClassicTestCase,
ClassicCPPTestCase,
diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py
index 8f6c9e6..8432638 100644
--- a/src/engine/SCons/Scanner/__init__.py
+++ b/src/engine/SCons/Scanner/__init__.py
@@ -43,6 +43,15 @@ class _Null:
# used as an actual argument value.
_null = _Null
+def Scanner(function, *args, **kw):
+ """Public interface factory function for creating different types
+ of Scanners based on the different types of "functions" that may
+ be supplied."""
+ if SCons.Util.is_Dict(function):
+ return apply(Selector, (function,) + args, kw)
+ else:
+ return apply(Base, (function,) + args, kw)
+
class FindPathDirs:
"""A class to bind a specific *PATH variable name and the fs object
to a function that will return all of the *path directories."""
@@ -190,6 +199,31 @@ class Base:
return env.subst_list(self.skeys)[0]
return self.skeys
+ def select(self, node):
+ return self
+
+
+class Selector(Base):
+ """
+ A class for selecting a more specific scanner based on the
+ scanner_key() (suffix) for a specific Node.
+ """
+ def __init__(self, dict, *args, **kw):
+ Base.__init__(self, (None,)+args, kw)
+ self.dict = dict
+
+ def __call__(self, node, env, path = ()):
+ return self.select(node)(node, env, path)
+
+ def select(self, node):
+ try:
+ return self.dict[node.scanner_key()]
+ except KeyError:
+ return None
+
+ def add_scanner(self, skey, scanner):
+ self.dict[skey] = scanner
+
class Current(Base):
"""
@@ -200,6 +234,7 @@ class Current(Base):
def __init__(self, *args, **kw):
def current_check(node, env):
+ calc = env.get_calculator()
c = not node.has_builder() or node.current(env.get_calculator())
return c
kw['scan_check'] = current_check