diff options
author | Steven Knight <knight@baldmt.com> | 2002-04-11 01:34:07 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2002-04-11 01:34:07 (GMT) |
commit | 3207c9ca9efaac1b8d3f2174d2e5f336f92887ab (patch) | |
tree | 184b6e6e1fb12fde12568a6ad52149821670f28b /src/engine/SCons/Node | |
parent | 48b6454994a21440a03cacaf14bad63295a62bbf (diff) | |
download | SCons-3207c9ca9efaac1b8d3f2174d2e5f336f92887ab.zip SCons-3207c9ca9efaac1b8d3f2174d2e5f336f92887ab.tar.gz SCons-3207c9ca9efaac1b8d3f2174d2e5f336f92887ab.tar.bz2 |
Implement implicit dependency caching.
Diffstat (limited to 'src/engine/SCons/Node')
-rw-r--r-- | src/engine/SCons/Node/FS.py | 12 | ||||
-rw-r--r-- | src/engine/SCons/Node/FSTests.py | 15 | ||||
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 66 |
3 files changed, 69 insertions, 24 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index c49361d..1c506c9 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -467,10 +467,8 @@ class Dir(Entry): """Return the .sconsign file info for this directory, creating it first if necessary.""" if not self._sconsign: - #XXX Rework this to get rid of the hard-coding import SCons.Sig - import SCons.Sig.MD5 - self._sconsign = SCons.Sig.SConsignFile(self, SCons.Sig.MD5) + self._sconsign = SCons.Sig.SConsignFile(self) return self._sconsign @@ -534,11 +532,15 @@ class File(Entry): self.get_bsig(), old[2]) + def store_implicit(self): + self.dir.sconsign().set_implicit(self.name, self.implicit) + def get_prevsiginfo(self): - """Fetch the previous signature information from the - .sconsign entry.""" return self.dir.sconsign().get(self.name) + def get_stored_implicit(self): + return self.dir.sconsign().get_implicit(self.name) + def get_implicit_deps(self, env, scanner, target): if scanner: return scanner.scan(self, env, target) diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 0e19cec..6b35adb 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -36,10 +36,16 @@ import stat built_it = None class Builder: + def __init__(self, factory): + self.factory = factory + def execute(self, **kw): global built_it built_it = 1 return 0 + + def source_factory(self, name): + return self.factory(name) scanner_count = 0 @@ -285,7 +291,7 @@ class FSTestCase(unittest.TestCase): built_it = None assert not built_it d1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE - d1.builder_set(Builder()) + d1.builder_set(Builder(fs.File)) d1.env_set(Environment()) d1.build() assert not built_it @@ -293,7 +299,7 @@ class FSTestCase(unittest.TestCase): built_it = None assert not built_it f1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE - f1.builder_set(Builder()) + f1.builder_set(Builder(fs.File)) f1.env_set(Environment()) f1.build() assert built_it @@ -381,6 +387,7 @@ class FSTestCase(unittest.TestCase): match(d12.path_, "subdir/d12/") e13 = fs.Entry("subdir/e13") match(e13.path, "subdir/subdir/e13") + fs.chdir(fs.Dir('..')) # Test scanning f1.target_scanner = Scanner() @@ -391,7 +398,9 @@ class FSTestCase(unittest.TestCase): assert f1.implicit == [] f1.implicit = None f1.scan() - assert f1.implicit[0].path_ == os.path.join("d1", "f1") + assert f1.implicit[0].path_ == os.path.join("d1", "f1"), f1.implicit[0].path_ + f1.store_implicit() + assert f1.get_stored_implicit()[0] == os.path.join("d1", "f1") # Test building a file whose directory is not there yet... f1 = fs.File(test.workpath("foo/bar/baz/ack")) diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index a9ca790..cbaed7b 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -35,6 +35,7 @@ import string import types import copy import sys +import SCons.Sig from SCons.Errors import BuildError import SCons.Util @@ -53,6 +54,9 @@ executed = 4 failed = 5 stack = 6 # nodes that are in the current Taskmaster execution stack +# controls whether implicit depedencies are cached: +implicit_cache = 0 + class Node: """The base Node class, for entities that we know how to build, or use to build other Nodes. @@ -116,9 +120,9 @@ class Node: if self.source_scanner: self.found_includes = {} self.includes = None - + def get_parents(node, parent): return node.get_parents() - def clear_cache(node, parent): + def clear_cache(node, parent): node.implicit = None node.bsig = None w = Walker(self, get_parents, ignore_cycle, clear_cache) @@ -170,17 +174,38 @@ class Node: # Don't bother scanning non-derived files, because we don't # care what their dependencies are. # Don't scan again, if we already have scanned. - if self.implicit is None: - if self.builder: - self.implicit = [] - for child in self.children(scan=0): - self._add_child(self.implicit, child.get_implicit_deps(self.env, child.source_scanner, self)) - - # scan this node itself for implicit dependencies - self._add_child(self.implicit, self.get_implicit_deps(self.env, self.target_scanner, self)) - else: - self.implicit = [] - + if not self.implicit is None: + return + self.implicit = [] + if not self.builder: + return + + if implicit_cache: + implicit = self.get_stored_implicit() + if implicit is not None: + implicit = map(self.builder.source_factory, implicit) + self._add_child(self.implicit, implicit) + calc = SCons.Sig.default_calc + if calc.current(self, calc.bsig(self)): + return + else: + self.implicit = [] + + for child in self.children(scan=0): + self._add_child(self.implicit, + child.get_implicit_deps(self.env, + child.source_scanner, + self)) + + # scan this node itself for implicit dependencies + self._add_child(self.implicit, + self.get_implicit_deps(self.env, + self.target_scanner, + self)) + + if implicit_cache: + self.store_implicit() + def scanner_key(self): return None @@ -225,6 +250,15 @@ class Node: def get_timestamp(self): return 0 + def store_implicit(self): + """Make the implicit deps permanent (that is, store them in the + .sconsign file or equivalent).""" + pass + + def get_stored_implicit(self): + """Fetch the stored implicit dependencies""" + return None + def set_precious(self, precious = 1): """Set the Node's precious value.""" self.precious = precious @@ -276,7 +310,7 @@ class Node: return self.sources + self.depends else: return self.sources + self.depends + self.implicit - + def get_parents(self): return self.parents.keys() @@ -300,10 +334,10 @@ class Walker: The Walker object can be initialized with any node, and returns the next node on the descent with each next() call. 'kids_func' is an optional function that will be called to - get the children of a node instead of calling 'children'. + get the children of a node instead of calling 'children'. 'cycle_func' is an optional function that will be called when a cycle is detected. - + This class does not get caught in node cycles caused, for example, by C header file include loops. """ |