diff options
| author | Steven Knight <knight@baldmt.com> | 2003-05-15 14:09:42 (GMT) |
|---|---|---|
| committer | Steven Knight <knight@baldmt.com> | 2003-05-15 14:09:42 (GMT) |
| commit | 86f456149f218ca14a67a31d98d92379feb2b072 (patch) | |
| tree | 313dec444e594790368c07782f23f54e592a51ca /src/engine/SCons/Node | |
| parent | f6ba11c5d37711d436bc1432878965fd3871eb57 (diff) | |
| download | SCons-86f456149f218ca14a67a31d98d92379feb2b072.zip SCons-86f456149f218ca14a67a31d98d92379feb2b072.tar.gz SCons-86f456149f218ca14a67a31d98d92379feb2b072.tar.bz2 | |
Refactor how actions get executed to eliminate a lot of redundant signature calcualations.
Diffstat (limited to 'src/engine/SCons/Node')
| -rw-r--r-- | src/engine/SCons/Node/FS.py | 5 | ||||
| -rw-r--r-- | src/engine/SCons/Node/FSTests.py | 52 | ||||
| -rw-r--r-- | src/engine/SCons/Node/NodeTests.py | 69 | ||||
| -rw-r--r-- | src/engine/SCons/Node/__init__.py | 76 |
4 files changed, 97 insertions, 105 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index b4641a7..c715ade 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1073,9 +1073,8 @@ class File(Entry): return self.fs.Rsearchall(pathlist, clazz=Dir, must_exist=0, cwd=self.cwd) - def generate_build_env(self): - env = SCons.Node.Node.generate_build_env(self) - + def generate_build_env(self, env): + """Generate an appropriate Environment to build this File.""" return env.Override({'Dir' : self.Dir, 'File' : self.File, 'RDirs' : self.RDirs}) diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 1f58264..13f171e 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -46,28 +46,6 @@ except NameError : True = 1 ; False = 0 -class Builder: - def __init__(self, factory): - self.factory = factory - - def get_actions(self): - class Action: - def __call__(self, targets, sources, env): - global built_it - built_it = 1 - return 0 - def show(self, string): - pass - def strfunction(self, targets, sources, env): - return "" - return [Action()] - - def targets(self, t): - return [t] - - def source_factory(self, name): - return self.factory(name) - scanner_count = 0 class Scanner: @@ -95,6 +73,34 @@ class Environment: def Override(self, overrides): return self +class Action: + def __call__(self, targets, sources, env): + global built_it + built_it = 1 + return 0 + def show(self, string): + pass + def strfunction(self, targets, sources, env): + return "" + def get_actions(self): + return [self] + +class Builder: + def __init__(self, factory): + self.factory = factory + self.env = Environment() + self.overrides = {} + self.action = Action() + + def get_actions(self): + return [self] + + def targets(self, t): + return [t] + + def source_factory(self, name): + return self.factory(name) + class BuildDirTestCase(unittest.TestCase): def runTest(self): """Test build dir functionality""" @@ -916,7 +922,7 @@ class FSTestCase(unittest.TestCase): test.write("remove_me", "\n") assert os.path.exists(test.workpath("remove_me")) f1 = fs.File(test.workpath("remove_me")) - f1.builder = 1 + f1.builder = Builder(fs.File) f1.env_set(Environment()) f1.prepare() assert not os.path.exists(test.workpath("remove_me")) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 2cf6d4b..ff57871 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -53,6 +53,9 @@ class MyAction: self.order = built_order return 0 + def get_actions(self): + return [self] + class MyNonGlobalAction: def __init__(self): self.order = 0 @@ -71,11 +74,24 @@ class MyNonGlobalAction: self.order = built_order return 0 + def get_actions(self): + return [self] + +class Environment: + def Dictionary(self, *args): + return {} + def Override(self, overrides): + return overrides + class Builder: + def __init__(self): + self.env = Environment() + self.overrides = {} + self.action = MyAction() def targets(self, t): return [t] def get_actions(self): - return [MyAction()] + return [self.action] def get_contents(self, target, source, env): return 7 @@ -86,6 +102,7 @@ class NoneBuilder(Builder): class ListBuilder(Builder): def __init__(self, *nodes): + Builder.__init__(self) self.nodes = nodes def execute(self, target, source, env): if hasattr(self, 'status'): @@ -107,12 +124,6 @@ class ExceptBuilder2: def execute(self, target, source, env): raise "foo" -class Environment: - def Dictionary(self, *args): - return {} - def Override(self, overrides): - return overrides - class Scanner: called = None def __call__(self, node): @@ -154,7 +165,7 @@ class NodeTestCase(unittest.TestCase): node.sources = ["yyy", "zzz"] node.build() assert built_it - assert built_target[0] == node, built_target[0] + assert built_target == [node], built_target assert built_source == ["yyy", "zzz"], built_source built_it = None @@ -163,10 +174,10 @@ class NodeTestCase(unittest.TestCase): node.env_set(Environment()) node.path = "qqq" node.sources = ["rrr", "sss"] - node.overrides = { "foo" : 1, "bar" : 2 } + node.builder.overrides = { "foo" : 1, "bar" : 2 } node.build() assert built_it - assert built_target[0] == node, built_target[0] + assert built_target == [node], built_target assert built_source == ["rrr", "sss"], built_source assert built_args["foo"] == 1, built_args assert built_args["bar"] == 2, built_args @@ -184,6 +195,17 @@ class NodeTestCase(unittest.TestCase): fff.sources = ["hhh", "iii"] ggg.sources = ["hhh", "iii"] # [Charles C. 1/7/2002] Uhhh, why are there no asserts here? + # [SK, 15 May 2003] I dunno, let's add some... + built_it = None + fff.build() + assert built_it + assert built_target == [fff], built_target + assert built_source == ["hhh", "iii"], built_source + built_it = None + ggg.build() + assert built_it + assert built_target == [ggg], built_target + assert built_source == ["hhh", "iii"], built_source built_it = None jjj = MyNode("jjj") @@ -285,31 +307,6 @@ class NodeTestCase(unittest.TestCase): assert t == [], t assert m == None, m - def test_builder_sig_adapter(self): - """Test the node's adapter for builder signatures - """ - node = SCons.Node.Node() - node.builder_set(Builder()) - node.env_set(Environment()) - c = node.builder_sig_adapter().get_contents() - assert c == 7, c - - class ListBuilder: - def __init__(self, targets): - self.tgt = targets - def targets(self, t): - return self.tgt - def get_contents(self, target, source, env): - assert target == self.tgt - return 8 - - node1 = SCons.Node.Node() - node2 = SCons.Node.Node() - node.builder_set(ListBuilder([node1, node2])) - node.env_set(Environment()) - c = node.builder_sig_adapter().get_contents() - assert c == 8, c - def test_current(self): """Test the default current() method """ @@ -605,7 +602,7 @@ class NodeTestCase(unittest.TestCase): """Test Scanner functionality """ node = MyNode("nnn") - node.builder = 1 + node.builder = Builder() node.env_set(Environment()) s = Scanner() diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 5231f90..09c930b 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -122,21 +122,36 @@ class Node: # what line in what file created the node, for example). Annotate(self) - def generate_build_env(self): + def generate_build_env(self, env): """Generate the appropriate Environment to build this node.""" - if self.env is None: - # The node itself doesn't have an associated Environment - # (which kind of implies it's a source code file, but who - # knows...). Regardless of why, use the environment (if - # any) associated with the Builder itself. - env = self.builder.env - overrides = self.builder.overrides - else: - # The normal case: use the Environment used to specify how - # this Node is to be built. - env = self.env - overrides = self.overrides - return env.Override(overrides) + return env + + def get_build_env(self): + """Fetch the appropriate Environment to build this node.""" + executor = self.get_executor() + return executor.get_build_env() + + def set_executor(self, executor): + """Set the action executor for this node.""" + self.executor = executor + + def get_executor(self, create=1): + """Fetch the action executor for this node. Create one if + there isn't already one, and requested to do so.""" + try: + executor = self.executor + except AttributeError: + if not create: + raise + import SCons.Builder + env = self.generate_build_env(self.builder.env) + executor = SCons.Executor.Executor(self.builder, + env, + self.builder.overrides, + [self], + self.sources) + self.executor = executor + return executor def _for_each_action(self, func): """Call a function for each action required to build a node. @@ -147,15 +162,8 @@ class Node: to do different things.""" if not self.has_builder(): return - action_list = self.pre_actions + \ - self.builder.get_actions() + \ - self.post_actions - if not action_list: - return - targets = self.builder.targets(self) - env = self.generate_build_env() - for action in action_list: - func(action, targets, self.sources, env) + executor = self.get_executor() + executor(self, func) def build(self): """Actually build the node. @@ -249,24 +257,6 @@ class Node: """ return [], None - def builder_sig_adapter(self): - """Create an adapter for calculating a builder's signature. - - The underlying signature class will call get_contents() - to fetch the signature of a builder, but the actual - content of that signature depends on the node and the - environment (for construction variable substitution), - so this adapter provides the right glue between the two. - """ - class Adapter: - def __init__(self, node): - self.node = node - def get_contents(self): - return self.node.builder.get_contents(self.node.builder.targets(self.node), self.node.sources, self.node.generate_build_env()) - def get_timestamp(self): - return None - return Adapter(self) - def get_found_includes(self, env, scanner, target): """Return the scanned include lines (implicit dependencies) found in this node. @@ -351,7 +341,7 @@ class Node: self.implicit = [] self.del_bsig() - build_env = self.generate_build_env() + build_env = self.get_build_env() for child in self.children(scan=0): self._add_child(self.implicit, @@ -589,7 +579,7 @@ class Node: user, of the include tree for the sources of this node. """ if self.has_builder() and self.env: - env = self.generate_build_env() + env = self.get_build_env() for s in self.sources: def f(node, env=env, scanner=s.source_scanner, target=self): return node.get_found_includes(env, scanner, target) |
