summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-12-16 14:22:29 (GMT)
committerSteven Knight <knight@baldmt.com>2004-12-16 14:22:29 (GMT)
commit64c24fdd205f1d3fe584990aaf6ae050bb46c431 (patch)
tree56224b472ce45750199e13b89473109b50ea3f9a /src/engine/SCons/Node
parent3869e426c19bd3b2e9bbb611b596220df9b34814 (diff)
downloadSCons-64c24fdd205f1d3fe584990aaf6ae050bb46c431.zip
SCons-64c24fdd205f1d3fe584990aaf6ae050bb46c431.tar.gz
SCons-64c24fdd205f1d3fe584990aaf6ae050bb46c431.tar.bz2
Cache get_suffix() and get_build_env(). (Kevin Quick)
Diffstat (limited to 'src/engine/SCons/Node')
-rw-r--r--src/engine/SCons/Node/FS.py6
-rw-r--r--src/engine/SCons/Node/NodeTests.py8
-rw-r--r--src/engine/SCons/Node/__init__.py60
3 files changed, 61 insertions, 13 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 1af739f..60ebb79 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -485,7 +485,11 @@ class Base(SCons.Node.Node):
return self.dir
def get_suffix(self):
- return SCons.Util.splitext(self.name)[1]
+ try:
+ return self.ext
+ except AttributeError:
+ self.ext = SCons.Util.splitext(self.name)[1]
+ return self.ext
def rfile(self):
return self
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index 12224d3..335c1a5 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -801,7 +801,7 @@ class NodeTestCase(unittest.TestCase):
"""
target = SCons.Node.Node()
source = SCons.Node.Node()
- s = target.get_source_scanner(source)
+ s = target.get_source_scanner(source, None)
assert s is None, s
ts1 = Scanner()
@@ -820,19 +820,19 @@ class NodeTestCase(unittest.TestCase):
builder = Builder2(ts1)
targets = builder([source])
- s = targets[0].get_source_scanner(source)
+ s = targets[0].get_source_scanner(source, None)
assert s is ts1, s
target.builder_set(Builder2(ts1))
target.builder.source_scanner = ts2
- s = target.get_source_scanner(source)
+ s = target.get_source_scanner(source, None)
assert s is ts2, s
builder = Builder1(env=Environment(SCANNERS = [ts3]))
targets = builder([source])
- s = targets[0].get_source_scanner(source)
+ s = targets[0].get_source_scanner(source, builder.env)
assert s is ts3, s
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 767b9e3..abbdf87 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -148,8 +148,17 @@ class Node:
def get_build_env(self):
"""Fetch the appropriate Environment to build this node."""
- executor = self.get_executor()
- return executor.get_build_env()
+ try:
+ build_env = self._build_env
+ except AttributeError:
+ # This gets called a lot, so cache it. A node gets created
+ # in the context of a specific environment and it doesn't
+ # get "moved" to a different environment, so caching this
+ # value is safe.
+ executor = self.get_executor()
+ build_env = executor.get_build_env()
+ self._build_env = build_env
+ return self._build_env
def set_executor(self, executor):
"""Set the action executor for this node."""
@@ -295,6 +304,7 @@ class Node:
def builder_set(self, builder):
self.builder = builder
+ self._src_scanners = {} # cached scanners are based on the builder
def has_builder(self):
"""Return whether this Node has a builder or not.
@@ -421,23 +431,57 @@ class Node:
self.implicit_factory_cache[path] = n
return n
- def get_source_scanner(self, node):
+ def get_source_scanner(self, node, build_env):
"""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.
+
+ build_env is the build environment (it's self.get_build_env(),
+ but the caller always knows this so it can give it
+ to us).
+
+ Implies self.has_builder() is true; again, expect to only be
+ called from locations where this is already verified.
+
+ This function may be called very often; it attempts to cache
+ the scanner found to improve performance.
"""
+ # Called from scan() for each child (node) of this node
+ # (self). The scan() may be called multiple times, so this
+ # gets called a multiple of those times; caching results is
+ # good. Index results based on the id of the child; can
+ # ignore build_env parameter for the index because it's passed
+ # as an optimization of an already-determined value, not as a
+ # changing parameter.
+
+ key = str(id(node)) + '|' + str(id(build_env))
+ try:
+ return self._src_scanners[key]
+ except AttributeError:
+ self._src_scanners = {}
+ except KeyError:
+ pass
+
if not self.has_builder():
- return None # if not buildable, can't have sources...
+ self._src_scanners[key] = None
+ return None
+
try:
scanner = self.builder.source_scanner
if scanner:
+ self._src_scanners[key] = scanner
return scanner
except AttributeError:
pass
- # No scanner specified by builder, try env['SCANNERS']
- return self.get_build_env().get_scanner(node.scanner_key())
+ # Not cached, so go look up a scanner from env['SCANNERS']
+ # based on the node's scanner key (usually the file
+ # extension).
+
+ scanner = build_env.get_scanner(node.scanner_key())
+ self._src_scanners[key] = scanner
+ return scanner
def scan(self):
"""Scan this node's dependents for implicit dependencies."""
@@ -473,7 +517,7 @@ class Node:
self.del_binfo()
for child in self.children(scan=0):
- scanner = self.get_source_scanner(child)
+ scanner = self.get_source_scanner(child, build_env)
if scanner:
deps = child.get_implicit_deps(build_env, scanner, self)
self._add_child(self.implicit, self.implicit_dict, deps)
@@ -833,7 +877,7 @@ class Node:
if self.is_derived() and self.env:
env = self.get_build_env()
for s in self.sources:
- scanner = self.get_source_scanner(s)
+ scanner = self.get_source_scanner(s, env)
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)