diff options
Diffstat (limited to 'src/engine/SCons/Node')
| -rw-r--r-- | src/engine/SCons/Node/FS.py | 9 | ||||
| -rw-r--r-- | src/engine/SCons/Node/FSTests.py | 8 | ||||
| -rw-r--r-- | src/engine/SCons/Node/NodeTests.py | 74 | ||||
| -rw-r--r-- | src/engine/SCons/Node/__init__.py | 77 |
4 files changed, 103 insertions, 65 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 15434cb..0d158a1 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -488,12 +488,6 @@ class Base(SCons.Node.Node): self._rexists = self.rfile().exists() return self._rexists - def get_parents(self): - parents = SCons.Node.Node.get_parents(self) - if self.dir and not isinstance(self.dir, ParentOfRoot): - parents.append(self.dir) - return parents - def is_under(self, dir): if self is dir: return 1 @@ -1117,8 +1111,7 @@ class Dir(Base): self.abspath_ = self.abspath + os.sep self.repositories = [] self.srcdir = None - self.source_scanner = None - + self.entries = {} self.entries['.'] = self self.entries['..'] = self.dir diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index fb2e0fa..f69dd4e 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -60,6 +60,8 @@ class Scanner: return [self.node] def __hash__(self): return self.hash + def select(self, node): + return self class Environment: def __init__(self): @@ -1034,12 +1036,6 @@ class FSTestCase(unittest.TestCase): skey = fs.Dir('ddd.x').scanner_key() assert skey is None, skey - d1 = fs.Dir('dir') - f1 = fs.File('dir/file') - assert f1.dir == d1, f1.dir - parents = f1.get_parents() - assert parents == [ d1 ], parents - test.write("i_am_not_a_directory", "\n") try: exc_caught = 0 diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 535c84e..e36d6ce 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -138,6 +138,8 @@ class Scanner: def __call__(self, node): self.called = 1 return node.found_includes + def select(self, node): + return self class MyNode(SCons.Node.Node): """The base Node class contains a number of do-nothing methods that @@ -543,12 +545,6 @@ class NodeTestCase(unittest.TestCase): node.add_dependency([three, four, one]) assert node.depends == [zero, one, two, three, four] - assert zero.get_parents() == [node] - assert one.get_parents() == [node] - assert two.get_parents() == [node] - assert three.get_parents() == [node] - assert four.get_parents() == [node] - try: node.add_depends([[five, six]]) except: @@ -556,8 +552,6 @@ class NodeTestCase(unittest.TestCase): else: raise "did not catch expected exception" assert node.depends == [zero, one, two, three, four] - assert five.get_parents() == [] - assert six.get_parents() == [] def test_add_source(self): @@ -583,12 +577,6 @@ class NodeTestCase(unittest.TestCase): node.add_source([three, four, one]) assert node.sources == [zero, one, two, three, four] - assert zero.get_parents() == [node] - assert one.get_parents() == [node] - assert two.get_parents() == [node] - assert three.get_parents() == [node] - assert four.get_parents() == [node] - try: node.add_source([[five, six]]) except: @@ -596,8 +584,6 @@ class NodeTestCase(unittest.TestCase): else: raise "did not catch expected exception" assert node.sources == [zero, one, two, three, four] - assert five.get_parents() == [] - assert six.get_parents() == [] def test_add_ignore(self): """Test adding files whose dependencies should be ignored. @@ -622,12 +608,6 @@ class NodeTestCase(unittest.TestCase): node.add_ignore([three, four, one]) assert node.ignore == [zero, one, two, three, four] - assert zero.get_parents() == [node] - assert one.get_parents() == [node] - assert two.get_parents() == [node] - assert three.get_parents() == [node] - assert four.get_parents() == [node] - try: node.add_ignore([[five, six]]) except: @@ -635,8 +615,6 @@ class NodeTestCase(unittest.TestCase): else: raise "did not catch expected exception" assert node.ignore == [zero, one, two, three, four] - assert five.get_parents() == [] - assert six.get_parents() == [] def test_get_found_includes(self): """Test the default get_found_includes() method @@ -689,6 +667,33 @@ class NodeTestCase(unittest.TestCase): deps = node.get_implicit_deps(env, s, target) assert deps == [d, e, f], map(str, deps) + def test_get_source_scanner(self): + """Test fetching the source scanner for a Node + """ + class Builder: + pass + target = SCons.Node.Node() + source = SCons.Node.Node() + s = target.get_source_scanner(source) + assert s is None, s + + ts1 = Scanner() + ts2 = Scanner() + ts3 = Scanner() + + source.backup_source_scanner = ts1 + s = target.get_source_scanner(source) + assert s is ts1, s + + source.builder = Builder() + source.builder.source_scanner = ts2 + s = target.get_source_scanner(source) + assert s is ts2, s + + target.source_scanner = ts3 + s = target.get_source_scanner(source) + assert s is ts3, s + def test_scan(self): """Test Scanner functionality """ @@ -947,6 +952,7 @@ class NodeTestCase(unittest.TestCase): n.includes = 'testincludes' n.found_include = {'testkey':'testvalue'} n.implicit = 'testimplicit' + n.waiting_parents = ['foo', 'bar'] n.clear() @@ -955,6 +961,7 @@ class NodeTestCase(unittest.TestCase): assert n.includes is None, n.includes assert n.found_includes == {}, n.found_includes assert n.implicit is None, n.implicit + assert n.waiting_parents == [], n.waiting_parents def test_get_subst_proxy(self): """Test the get_subst_proxy method.""" @@ -985,6 +992,25 @@ class NodeTestCase(unittest.TestCase): n = SCons.Node.Node() n.postprocess() + def test_add_to_waiting_parents(self): + """Test the add_to_waiting_parents() method""" + n1 = SCons.Node.Node() + n2 = SCons.Node.Node() + assert n1.waiting_parents == [], n1.waiting_parents + n1.add_to_waiting_parents(n2) + assert n1.waiting_parents == [n2], n1.waiting_parents + + def test_call_for_all_waiting_parents(self): + """Test the call_for_all_waiting_parents() method""" + n1 = SCons.Node.Node() + n2 = SCons.Node.Node() + n1.add_to_waiting_parents(n2) + result = [] + def func(node, result=result): + result.append(node) + n1.call_for_all_waiting_parents(func) + assert result == [n1, n2], result + if __name__ == "__main__": diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 2841759..75b3a6d 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -116,10 +116,11 @@ class Node: self.ignore = [] # dependencies to ignore self.ignore_dict = {} self.implicit = None # implicit (scanned) dependencies (None means not scanned yet) - self.parents = {} + self.waiting_parents = [] self.wkids = None # Kids yet to walk, when it's an array self.target_scanner = None # explicit scanner from this node's Builder - self.source_scanner = None # source scanner + self.source_scanner = None + self.backup_source_scanner = None self.env = None self.state = None @@ -208,20 +209,29 @@ class Node: else: self.store_info(new_binfo) - # Clear out the implicit dependency caches: - # XXX this really should somehow be made more general and put - # under the control of the scanners. - if self.source_scanner: - self.found_includes = {} - self.includes = None - for parent in self.get_parents(): - parent.implicit = None - parent.del_binfo() + # Clear our scanned included files. + self.found_includes = {} + self.includes = None + + # Clear the implicit dependency caches of any Nodes + # waiting for this Node to be built. + for parent in self.waiting_parents: + parent.implicit = None + parent.del_binfo() + self.waiting_parents = [] # The content just changed, delete any cached info # so it will get recalculated. self.del_cinfo() + def add_to_waiting_parents(self, node): + self.waiting_parents.append(node) + + def call_for_all_waiting_parents(self, func): + func(self) + for parent in self.waiting_parents: + parent.call_for_all_waiting_parents(func) + def postprocess(self): """Clean up anything we don't need to hang onto after we've been built.""" @@ -248,6 +258,8 @@ class Node: self.found_includes = {} self.implicit = None + self.waiting_parents = [] + def visited(self): """Called just after this node has been visited without requiring a build..""" @@ -329,6 +341,10 @@ class Node: if not scanner: return [] + # Give the scanner a chance to select a more specific scanner + # for this Node. + scanner = scanner.select(self) + try: recurse = scanner.recursive except AttributeError: @@ -367,6 +383,22 @@ class Node: self.implicit_factory_cache[path] = n return n + def get_source_scanner(self, node): + """Fetch the source scanner for the specified node + + NOTE: "self" is the target being built, "node" is + the source file for which we want to fetch the scanner. + """ + if self.source_scanner: + return self.source_scanner + try: + scanner = node.builder.source_scanner + if scanner: + return scanner + except AttributeError: + pass + return node.backup_source_scanner or None + def scan(self): """Scan this node's dependents for implicit dependencies.""" # Don't bother scanning non-derived files, because we don't @@ -405,20 +437,14 @@ class Node: # self.del_binfo() for child in self.children(scan=0): - scanner = child.source_scanner + scanner = self.get_source_scanner(child) if scanner: - self._add_child(self.implicit, - self.implicit_dict, - child.get_implicit_deps(build_env, - scanner, - self)) + deps = child.get_implicit_deps(build_env, scanner, self) + self._add_child(self.implicit, self.implicit_dict, deps) # scan this node itself for implicit dependencies - self._add_child(self.implicit, - self.implicit_dict, - self.get_implicit_deps(build_env, - self.target_scanner, - self)) + deps = self.get_implicit_deps(build_env, self.target_scanner, self) + self._add_child(self.implicit, self.implicit_dict, deps) # XXX See note above re: --implicit-cache. #if implicit_cache: @@ -632,7 +658,6 @@ class Node: collection.append(c) dict[c] = 1 added = 1 - c.parents[self] = 1 if added: self._children_reset() @@ -686,9 +711,6 @@ class Node: else: return self.sources + self.depends + self.implicit - def get_parents(self): - return self.parents.keys() - def set_state(self, state): self.state = state @@ -738,7 +760,8 @@ class Node: if self.is_derived() and self.env: env = self.get_build_env() for s in self.sources: - def f(node, env=env, scanner=s.source_scanner, target=self): + scanner = s.get_source_scanner(self) + def f(node, env=env, scanner=scanner, target=self): return node.get_found_includes(env, scanner, target) return SCons.Util.render_tree(s, f, 1) else: |
