summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-05-15 14:09:42 (GMT)
committerSteven Knight <knight@baldmt.com>2003-05-15 14:09:42 (GMT)
commit86f456149f218ca14a67a31d98d92379feb2b072 (patch)
tree313dec444e594790368c07782f23f54e592a51ca /src/engine/SCons/Node
parentf6ba11c5d37711d436bc1432878965fd3871eb57 (diff)
downloadSCons-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.py5
-rw-r--r--src/engine/SCons/Node/FSTests.py52
-rw-r--r--src/engine/SCons/Node/NodeTests.py69
-rw-r--r--src/engine/SCons/Node/__init__.py76
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)