summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/Node/__init__.py')
-rw-r--r--src/engine/SCons/Node/__init__.py606
1 files changed, 242 insertions, 364 deletions
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index e73e5f3..38cff92 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -48,10 +48,8 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import copy
import string
-import UserList
from SCons.Debug import logInstanceCreation
-import SCons.Executor
import SCons.SConsign
import SCons.Util
@@ -62,7 +60,6 @@ import SCons.Util
# it has no builder of its own. The canonical example is a file
# system directory, which is only up to date if all of its children
# were up to date.
-no_state = 0
pending = 1
executing = 2
up_to_date = 3
@@ -70,17 +67,7 @@ executed = 4
failed = 5
stack = 6 # nodes that are in the current Taskmaster execution stack
-StateString = {
- 0 : "0",
- 1 : "pending",
- 2 : "executing",
- 3 : "up_to_date",
- 4 : "executed",
- 5 : "failed",
- 6 : "stack",
-}
-
-# controls whether implicit dependencies are cached:
+# controls whether implicit depedencies are cached:
implicit_cache = 0
# controls whether implicit dep changes are ignored:
@@ -95,69 +82,20 @@ def do_nothing(node): pass
Annotate = do_nothing
-# Classes for signature info for Nodes.
-
-class NodeInfo:
- """
- A generic class for signature information for a Node.
-
- We actually expect that modules containing Node subclasses will also
- subclass NodeInfo, to provide their own logic for dealing with their
- own Node-specific signature information.
- """
- def __init__(self):
- """A null initializer so that subclasses have a superclass
- initialization method to call for future use.
- """
- pass
- def __cmp__(self, other):
- return cmp(self.__dict__, other.__dict__)
- def update(self, node):
- pass
- def merge(self, other):
- for key, val in other.__dict__.items():
- self.__dict__[key] = val
-
class BuildInfo:
- """
- The generic build information for a Node.
-
- This is what gets stored in a .sconsign file for each target file.
- It contains a NodeInfo instance for this node (signature information
- that's specific to the type of Node) and direct attributes for the
- generic build stuff we have to track: sources, explicit dependencies,
- implicit dependencies, and action information.
- """
- def __init__(self, node):
- self.ninfo = node.new_ninfo()
- self.bsourcesigs = []
- self.bdependsigs = []
- self.bimplicitsigs = []
- self.bactsig = None
def __cmp__(self, other):
- return cmp(self.ninfo, other.ninfo)
- def merge(self, other):
- for key, val in other.__dict__.items():
- try:
- merge = self.__dict__[key].merge
- except (AttributeError, KeyError):
- self.__dict__[key] = val
- else:
- merge(val)
+ return cmp(self.__dict__, other.__dict__)
class Node:
"""The base Node class, for entities that we know how to
build, or use to build other Nodes.
"""
- if SCons.Memoize.use_memoizer:
- __metaclass__ = SCons.Memoize.Memoized_Metaclass
-
class Attrs:
pass
def __init__(self):
- if __debug__: logInstanceCreation(self, 'Node.Node')
+ if __debug__: logInstanceCreation(self, 'Node')
# Note that we no longer explicitly initialize a self.builder
# attribute to None here. That's because the self.builder
# attribute may be created on-the-fly later by a subclass (the
@@ -180,13 +118,17 @@ class Node:
self.implicit = None # implicit (scanned) dependencies (None means not scanned yet)
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
+ self.backup_source_scanner = None
self.env = None
- self.state = no_state
+ self.state = None
self.precious = None
self.always_build = None
self.found_includes = {}
self.includes = None
+ self.overrides = {} # construction variable overrides for building this node
self.attributes = self.Attrs() # Generic place to stick information about the Node.
self.side_effect = 0 # true iff this node is a side effect
self.side_effects = [] # the side effects of building this target
@@ -202,14 +144,15 @@ class Node:
def get_suffix(self):
return ''
- def get_build_env(self):
- """Fetch the appropriate Environment to build this node.
- __cacheable__"""
- return self.get_executor().get_build_env()
+ def generate_build_dict(self):
+ """Return an appropriate dictionary of values for building
+ this Node."""
+ return {}
- def get_build_scanner_path(self, scanner):
- """Fetch the appropriate scanner path for this node."""
- return self.get_executor().get_build_scanner_path(scanner)
+ 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."""
@@ -223,35 +166,15 @@ class Node:
except AttributeError:
if not create:
raise
- try:
- act = self.builder.action
- except AttributeError:
- executor = SCons.Executor.Null(targets=[self])
- else:
- executor = SCons.Executor.Executor(act,
- self.env or self.builder.env,
- [self.builder.overrides],
- [self],
- self.sources)
+ import SCons.Executor
+ executor = SCons.Executor.Executor(self.builder.action,
+ self.builder.env,
+ [self.builder.overrides],
+ [self],
+ self.sources)
self.executor = executor
return executor
- def executor_cleanup(self):
- """Let the executor clean up any cached information."""
- try:
- executor = self.get_executor(create=None)
- except AttributeError:
- pass
- else:
- executor.cleanup()
-
- def reset_executor(self):
- "Remove cached executor; forces recompute when needed."
- try:
- delattr(self, 'executor')
- except AttributeError:
- pass
-
def retrieve_from_cache(self):
"""Try to retrieve the node's content from a cache
@@ -270,15 +193,15 @@ class Node:
so only do thread safe stuff here. Do thread unsafe stuff in
built().
"""
- def exitstatfunc(stat, node=self):
- if stat:
- msg = "Error %d" % stat
- raise SCons.Errors.BuildError(node=node, errstr=msg)
+ if not self.has_builder():
+ return
+ def errfunc(stat, node=self):
+ raise SCons.Errors.BuildError(node=node, errstr="Error %d" % stat)
executor = self.get_executor()
- apply(executor, (self, exitstatfunc), kw)
+ apply(executor, (self, errfunc), kw)
def built(self):
- """Called just after this node is successfully built."""
+ """Called just after this node is sucessfully built."""
# Clear the implicit dependency caches of any Nodes
# waiting for this Node to be built.
@@ -287,27 +210,30 @@ class Node:
parent.del_binfo()
try:
- new = self.binfo
+ new_binfo = self.binfo
except AttributeError:
# Node arrived here without build info; apparently it
# doesn't need it, so don't bother calculating or storing
# it.
- new = None
+ new_binfo = None
# Reset this Node's cached state since it was just built and
# various state has changed.
+ save_state = self.get_state()
self.clear()
+ self.set_state(save_state)
+
+ # Had build info, so it should be stored in the signature
+ # cache. However, if the build info included a content
+ # signature then it should be recalculated before being
+ # stored.
- if new:
- # It had build info, so it should be stored in the signature
- # cache. However, if the build info included a content
- # signature then it must be recalculated before being stored.
- if hasattr(new.ninfo, 'csig'):
- self.get_csig()
+ if new_binfo:
+ if hasattr(new_binfo, 'csig'):
+ new_binfo = self.gen_binfo() # sets self.binfo
else:
- new.ninfo.update(self)
- self.binfo = new
- self.store_info(self.binfo)
+ self.binfo = new_binfo
+ self.store_info(new_binfo)
def add_to_waiting_parents(self, node):
self.waiting_parents.append(node)
@@ -320,16 +246,21 @@ class Node:
def postprocess(self):
"""Clean up anything we don't need to hang onto after we've
been built."""
- self.executor_cleanup()
+ try:
+ executor = self.get_executor(create=None)
+ except AttributeError:
+ pass
+ else:
+ executor.cleanup()
def clear(self):
"""Completely clear a Node of all its cached state (so that it
can be re-evaluated by interfaces that do continuous integration
builds).
- __reset_cache__
"""
- self.executor_cleanup()
+ self.set_state(None)
self.del_binfo()
+ self.del_cinfo()
try:
delattr(self, '_calculated_sig')
except AttributeError:
@@ -345,8 +276,15 @@ class Node:
without requiring a build.."""
pass
+ def depends_on(self, nodes):
+ """Does this node depend on any of 'nodes'?"""
+ for node in nodes:
+ if node in self.children():
+ return 1
+
+ return 0
+
def builder_set(self, builder):
- "__cache_reset__"
self.builder = builder
def has_builder(self):
@@ -369,9 +307,6 @@ class Node:
b = self.builder
return not b is None
- def set_explicit(self, is_explicit):
- self.is_explicit = is_explicit
-
def has_explicit_builder(self):
"""Return whether this Node has an explicit builder
@@ -379,18 +314,7 @@ class Node:
non-explicit, so that it can be overridden by an explicit
builder that the user supplies (the canonical example being
directories)."""
- try:
- return self.is_explicit
- except AttributeError:
- self.is_explicit = None
- return self.is_explicit
-
- def get_builder(self, default_builder=None):
- """Return the set builder, or a specified default value"""
- try:
- return self.builder
- except AttributeError:
- return default_builder
+ return self.has_builder() and self.builder.is_explicit
multiple_side_effect_has_builder = has_builder
@@ -403,7 +327,6 @@ class Node:
signatures when they are used as source files to other derived files. For
example: source with source builders are not derived in this sense,
and hence should not return true.
- __cacheable__
"""
return self.has_builder() or self.side_effect
@@ -420,7 +343,7 @@ class Node:
"""
return [], None
- def get_found_includes(self, env, scanner, path):
+ def get_found_includes(self, env, scanner, target):
"""Return the scanned include lines (implicit dependencies)
found in this node.
@@ -430,7 +353,7 @@ class Node:
"""
return []
- def get_implicit_deps(self, env, scanner, path):
+ def get_implicit_deps(self, env, scanner, target):
"""Return a list of implicit dependencies for this node.
This method exists to handle recursive invocation of the scanner
@@ -444,57 +367,59 @@ class Node:
# for this Node.
scanner = scanner.select(self)
+ try:
+ recurse = scanner.recursive
+ except AttributeError:
+ recurse = None
+
nodes = [self]
seen = {}
seen[self] = 1
deps = []
while nodes:
- n = nodes.pop(0)
- d = filter(lambda x, seen=seen: not seen.has_key(x),
- n.get_found_includes(env, scanner, path))
- if d:
- deps.extend(d)
- for n in d:
- seen[n] = 1
- nodes.extend(scanner.recurse_nodes(d))
+ n = nodes.pop(0)
+ d = filter(lambda x, seen=seen: not seen.has_key(x),
+ n.get_found_includes(env, scanner, target))
+ if d:
+ deps.extend(d)
+ for n in d:
+ seen[n] = 1
+ if recurse:
+ nodes.extend(d)
return deps
- def get_scanner(self, env, kw={}):
- return env.get_scanner(self.scanner_key())
+ # cache used to make implicit_factory fast.
+ implicit_factory_cache = {}
+
+ def implicit_factory(self, path):
+ """
+ Turn a cache implicit dependency path into a node.
+ This is called so many times that doing caching
+ here is a significant performance boost.
+ """
+ try:
+ return self.implicit_factory_cache[path]
+ except KeyError:
+ n = self.builder.source_factory(path)
+ 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.
-
- 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.
"""
- scanner = None
+ if self.source_scanner:
+ return self.source_scanner
try:
scanner = self.builder.source_scanner
+ if scanner:
+ return scanner
except AttributeError:
pass
- if not scanner:
- # The builder didn't have an explicit scanner, so go look up
- # a scanner from env['SCANNERS'] based on the node's scanner
- # key (usually the file extension).
- scanner = self.get_scanner(self.get_build_env())
- if scanner:
- scanner = scanner.select(node)
- return scanner
-
- def add_to_implicit(self, deps):
- if not hasattr(self, 'implicit') or self.implicit is None:
- self.implicit = []
- self.implicit_dict = {}
- self._children_reset()
- self._add_child(self.implicit, self.implicit_dict, deps)
+ return node.backup_source_scanner or None
def scan(self):
"""Scan this node's dependents for implicit dependencies."""
@@ -514,44 +439,34 @@ class Node:
# Here's where we implement --implicit-cache.
if implicit_cache and not implicit_deps_changed:
implicit = self.get_stored_implicit()
- if implicit:
- factory = build_env.get_factory(self.builder.source_factory)
- nodes = []
- for i in implicit:
- try:
- n = factory(i)
- except TypeError:
- # The implicit dependency was cached as one type
- # of Node last time, but the configuration has
- # changed (probably) and it's a different type
- # this time. Just ignore the mismatch and go
- # with what our current configuration says the
- # Node is.
- pass
- else:
- nodes.append(n)
- self._add_child(self.implicit, self.implicit_dict, nodes)
+ if implicit is not None:
+ implicit = map(self.implicit_factory, implicit)
+ self._add_child(self.implicit, self.implicit_dict, implicit)
calc = build_env.get_calculator()
- if implicit_deps_unchanged or self.current(calc):
+ if implicit_deps_unchanged or self.current(calc, scan=0):
return
- # one of this node's sources has changed, so
- # we need to recalculate the implicit deps,
- # and the bsig:
- self.implicit = []
- self.implicit_dict = {}
- self._children_reset()
- self.del_binfo()
-
- executor = self.get_executor()
-
- # Have the executor scan the sources.
- executor.scan_sources(self.builder.source_scanner)
+ else:
+ # one of this node's sources has changed, so
+ # we need to recalculate the implicit deps,
+ # and the bsig:
+ self.implicit = []
+ self.implicit_dict = {}
+ self._children_reset()
+ self.del_binfo()
+
+ for child in self.children(scan=0):
+ scanner = self.get_source_scanner(child)
+ if scanner:
+ 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
+ deps = self.get_implicit_deps(build_env, self.target_scanner, self)
+ self._add_child(self.implicit, self.implicit_dict, deps)
- # If there's a target scanner, have the executor scan the target
- # node itself and associated targets that might be built.
- scanner = self.builder.target_scanner
- if scanner:
- executor.scan_targets(scanner)
+ # XXX See note above re: --implicit-cache.
+ #if implicit_cache:
+ # self.store_implicit()
def scanner_key(self):
return None
@@ -561,10 +476,6 @@ class Node:
return
self.env = env
- #
- # SIGNATURE SUBSYSTEM
- #
-
def calculator(self):
import SCons.Defaults
@@ -574,42 +485,46 @@ class Node:
def calc_signature(self, calc=None):
"""
Select and calculate the appropriate build signature for a node.
- __cacheable__
self - the node
calc - the signature calculation module
returns - the signature
"""
- if self.is_derived():
- import SCons.Defaults
-
- env = self.env or SCons.Defaults.DefaultEnvironment()
- if env.use_build_signature():
- return self.get_bsig(calc)
- elif not self.rexists():
- return None
- return self.get_csig(calc)
-
- def new_ninfo(self):
- return NodeInfo()
-
- def new_binfo(self):
- return BuildInfo(self)
-
- def get_binfo(self):
try:
- return self.binfo
+ return self._calculated_sig
except AttributeError:
- self.binfo = self.new_binfo()
- return self.binfo
+ if self.is_derived():
+ import SCons.Defaults
+
+ env = self.env or SCons.Defaults.DefaultEnvironment()
+ if env.use_build_signature():
+ sig = self.calc_bsig(calc)
+ else:
+ sig = self.calc_csig(calc)
+ elif not self.rexists():
+ sig = None
+ else:
+ sig = self.calc_csig(calc)
+ self._calculated_sig = sig
+ return sig
+
+ def new_binfo(self):
+ return BuildInfo()
def del_binfo(self):
- """Delete the build info from this node."""
+ """Delete the bsig from this node."""
try:
delattr(self, 'binfo')
except AttributeError:
pass
+ def calc_bsig(self, calc=None):
+ try:
+ return self.binfo.bsig
+ except AttributeError:
+ self.binfo = self.gen_binfo(calc)
+ return self.binfo.bsig
+
def gen_binfo(self, calc=None, scan=1):
"""
Generate a node's build signature, the digested signatures
@@ -623,70 +538,68 @@ class Node:
node's children's signatures. We expect that they're
already built and updated by someone else, if that's
what's wanted.
- __cacheable__
"""
if calc is None:
calc = self.calculator()
- binfo = self.get_binfo()
+ binfo = self.new_binfo()
if scan:
self.scan()
- executor = self.get_executor()
+ sources = self.filter_ignore(self.sources)
+ depends = self.filter_ignore(self.depends)
+ if self.implicit is None:
+ implicit = []
+ else:
+ implicit = self.filter_ignore(self.implicit)
+
def calc_signature(node, calc=calc):
return node.calc_signature(calc)
-
- sources = executor.process_sources(None, self.ignore)
- sourcesigs = executor.process_sources(calc_signature, self.ignore)
-
- depends = self.depends
- implicit = self.implicit or []
-
- if self.ignore:
- depends = filter(self.do_not_ignore, depends)
- implicit = filter(self.do_not_ignore, implicit)
-
+ sourcesigs = map(calc_signature, sources)
dependsigs = map(calc_signature, depends)
implicitsigs = map(calc_signature, implicit)
sigs = sourcesigs + dependsigs + implicitsigs
if self.has_builder():
- binfo.bact = str(executor)
+ executor = self.get_executor()
+ binfo.bact = executor.strfunction()
binfo.bactsig = calc.module.signature(executor)
sigs.append(binfo.bactsig)
- binfo.bsources = sources
- binfo.bdepends = depends
- binfo.bimplicit = implicit
+ binfo.bsources = map(str, sources)
+ binfo.bdepends = map(str, depends)
+ binfo.bimplicit = map(str, implicit)
binfo.bsourcesigs = sourcesigs
binfo.bdependsigs = dependsigs
binfo.bimplicitsigs = implicitsigs
- binfo.ninfo.bsig = calc.module.collect(filter(None, sigs))
+ binfo.bsig = calc.module.collect(filter(None, sigs))
return binfo
- def get_bsig(self, calc=None):
- binfo = self.get_binfo()
+ def del_cinfo(self):
try:
- return binfo.ninfo.bsig
+ del self.binfo.csig
except AttributeError:
- self.binfo = self.gen_binfo(calc)
- return self.binfo.ninfo.bsig
+ pass
- def get_csig(self, calc=None):
- binfo = self.get_binfo()
+ def calc_csig(self, calc=None):
try:
- return binfo.ninfo.csig
+ binfo = self.binfo
+ except AttributeError:
+ binfo = self.binfo = self.new_binfo()
+ try:
+ return binfo.csig
except AttributeError:
if calc is None:
calc = self.calculator()
- csig = binfo.ninfo.csig = calc.module.signature(self)
- return csig
+ binfo.csig = calc.module.signature(self)
+ self.store_info(binfo)
+ return binfo.csig
def store_info(self, obj):
"""Make the build signature permanent (that is, store it in the
@@ -700,10 +613,6 @@ class Node:
"""Fetch the stored implicit dependencies"""
return None
- #
- #
- #
-
def set_precious(self, precious = 1):
"""Set the Node's precious value."""
self.precious = precious
@@ -721,24 +630,18 @@ class Node:
"""Does this node exist locally or in a repositiory?"""
# There are no repositories by default:
return self.exists()
-
- def missing(self):
- """__cacheable__"""
- return not self.is_derived() and \
- not self.is_pseudo_derived() and \
- not self.linked and \
- not self.rexists()
def prepare(self):
"""Prepare for this Node to be created.
The default implemenation checks that all children either exist
or are derived.
"""
- l = self.depends
- if not self.implicit is None:
- l = l + self.implicit
- missing_sources = self.get_executor().get_missing_sources() \
- + filter(lambda c: c.missing(), l)
+ def missing(node):
+ return not node.is_derived() and \
+ not node.is_pseudo_derived() and \
+ not node.linked and \
+ not node.rexists()
+ missing_sources = filter(missing, self.children())
if missing_sources:
desc = "Source `%s' not found, needed by target `%s'." % (missing_sources[0], self)
raise SCons.Errors.StopError, desc
@@ -806,15 +709,33 @@ class Node:
self.wkids.append(wkid)
def _children_reset(self):
- "__cache_reset__"
- # We need to let the Executor clear out any calculated
- # bsig info that it's cached so we can re-calculate it.
- self.executor_cleanup()
+ try:
+ delattr(self, '_children')
+ except AttributeError:
+ pass
- def do_not_ignore(self, node):
- return node not in self.ignore
+ def filter_ignore(self, nodelist):
+ ignore = self.ignore
+ result = []
+ for node in nodelist:
+ if node not in ignore:
+ result.append(node)
+ return result
- def _all_children_get(self):
+ def children(self, scan=1):
+ """Return a list of the node's direct children, minus those
+ that are ignored by this node."""
+ if scan:
+ self.scan()
+ try:
+ return self._children
+ except AttributeError:
+ c = self.all_children(scan=0)
+ self._children = self.filter_ignore(c)
+ return self._children
+
+ def all_children(self, scan=1):
+ """Return a list of all the node's direct children."""
# The return list may contain duplicate Nodes, especially in
# source trees where there are a lot of repeated #includes
# of a tangle of .h files. Profiling shows, however, that
@@ -832,31 +753,13 @@ class Node:
# using dictionary keys, lose the order, and the only ordered
# dictionary patterns I found all ended up using "not in"
# internally anyway...)
+ if scan:
+ self.scan()
if self.implicit is None:
return self.sources + self.depends
else:
return self.sources + self.depends + self.implicit
- def _children_get(self):
- "__cacheable__"
- children = self._all_children_get()
- if self.ignore:
- children = filter(self.do_not_ignore, children)
- return children
-
- def all_children(self, scan=1):
- """Return a list of all the node's direct children."""
- if scan:
- self.scan()
- return self._all_children_get()
-
- def children(self, scan=1):
- """Return a list of the node's direct children, minus those
- that are ignored by this node."""
- if scan:
- self.scan()
- return self._children_get()
-
def set_state(self, state):
self.state = state
@@ -876,8 +779,6 @@ class Node:
rebind their current() method to this method."""
# Allow the children to calculate their signatures.
self.binfo = self.gen_binfo(calc)
- if self.always_build:
- return None
state = 0
for kid in self.children(None):
s = kid.get_state()
@@ -890,6 +791,16 @@ class Node:
the command interpreter literally."""
return 1
+ def add_pre_action(self, act):
+ """Adds an Action performed on this Node only before
+ building it."""
+ self.pre_actions.append(act)
+
+ def add_post_action(self, act):
+ """Adds and Action performed on this Node only after
+ building it."""
+ self.post_actions.append(act)
+
def render_include_tree(self):
"""
Return a text representation, suitable for displaying to the
@@ -899,9 +810,8 @@ class Node:
env = self.get_build_env()
for s in self.sources:
scanner = self.get_source_scanner(s)
- path = self.get_build_scanner_path(scanner)
- def f(node, env=env, scanner=scanner, path=path):
- return node.get_found_includes(env, scanner, path)
+ 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:
return None
@@ -974,63 +884,53 @@ class Node:
result[k] = s
try:
- osig = {}
- dictify(osig, old.bsources, old.bsourcesigs)
- dictify(osig, old.bdepends, old.bdependsigs)
- dictify(osig, old.bimplicit, old.bimplicitsigs)
+ old_bkids = old.bsources + old.bdepends + old.bimplicit
except AttributeError:
return "Cannot explain why `%s' is being rebuilt: No previous build information found\n" % self
- new = self.get_binfo()
-
- nsig = {}
- dictify(nsig, new.bsources, new.bsourcesigs)
- dictify(nsig, new.bdepends, new.bdependsigs)
- dictify(nsig, new.bimplicit, new.bimplicitsigs)
-
- old_bkids = old.bsources + old.bdepends + old.bimplicit
- new_bkids = new.bsources + new.bdepends + new.bimplicit
+ osig = {}
+ dictify(osig, old.bsources, old.bsourcesigs)
+ dictify(osig, old.bdepends, old.bdependsigs)
+ dictify(osig, old.bimplicit, old.bimplicitsigs)
- # The sources and dependencies we'll want to report are all stored
- # as relative paths to this target's directory, but we want to
- # report them relative to the top-level SConstruct directory,
- # so we only print them after running them through this lambda
- # to turn them into the right relative Node and then return
- # its string.
- stringify = lambda s, E=self.dir.Entry: str(E(s))
+ new_bsources = map(str, self.binfo.bsources)
+ new_bdepends = map(str, self.binfo.bdepends)
+ new_bimplicit = map(str, self.binfo.bimplicit)
- lines = []
+ nsig = {}
+ dictify(nsig, new_bsources, self.binfo.bsourcesigs)
+ dictify(nsig, new_bdepends, self.binfo.bdependsigs)
+ dictify(nsig, new_bimplicit, self.binfo.bimplicitsigs)
- removed = filter(lambda x, nk=new_bkids: not x in nk, old_bkids)
- if removed:
- removed = map(stringify, removed)
- fmt = "`%s' is no longer a dependency\n"
- lines.extend(map(lambda s, fmt=fmt: fmt % s, removed))
+ new_bkids = new_bsources + new_bdepends + new_bimplicit
+ lines = map(lambda x: "`%s' is no longer a dependency\n" % x,
+ filter(lambda x, nk=new_bkids: not x in nk, old_bkids))
for k in new_bkids:
if not k in old_bkids:
- lines.append("`%s' is a new dependency\n" % stringify(k))
+ lines.append("`%s' is a new dependency\n" % k)
elif osig[k] != nsig[k]:
- lines.append("`%s' changed\n" % stringify(k))
+ lines.append("`%s' changed\n" % k)
if len(lines) == 0 and old_bkids != new_bkids:
lines.append("the dependency order changed:\n" +
- "%sold: %s\n" % (' '*15, map(stringify, old_bkids)) +
- "%snew: %s\n" % (' '*15, map(stringify, new_bkids)))
+ "%sold: %s\n" % (' '*15, old_bkids) +
+ "%snew: %s\n" % (' '*15, new_bkids))
if len(lines) == 0:
+ newact, newactsig = self.binfo.bact, self.binfo.bactsig
def fmt_with_title(title, strlines):
lines = string.split(strlines, '\n')
sep = '\n' + ' '*(15 + len(title))
return ' '*15 + title + string.join(lines, sep) + '\n'
- if old.bactsig != new.bactsig:
- if old.bact == new.bact:
+ if old.bactsig != newactsig:
+ if old.bact == newact:
lines.append("the contents of the build action changed\n" +
- fmt_with_title('action: ', new.bact))
+ fmt_with_title('action: ', newact))
else:
lines.append("the build action changed:\n" +
fmt_with_title('old: ', old.bact) +
- fmt_with_title('new: ', new.bact))
+ fmt_with_title('new: ', newact))
if len(lines) == 0:
return "rebuilding `%s' for unknown reasons\n" % self
@@ -1042,28 +942,6 @@ class Node:
lines = ["%s:\n" % preamble] + lines
return string.join(lines, ' '*11)
-l = [1]
-ul = UserList.UserList([2])
-try:
- l.extend(ul)
-except TypeError:
- def NodeList(l):
- return l
-else:
- class NodeList(UserList.UserList):
- def __str__(self):
- return str(map(str, self.data))
-del l
-del ul
-
-if SCons.Memoize.use_old_memoization():
- _Base = Node
- class Node(SCons.Memoize.Memoizer, _Base):
- def __init__(self, *args, **kw):
- apply(_Base.__init__, (self,)+args, kw)
- SCons.Memoize.Memoizer.__init__(self)
-
-
def get_children(node, parent): return node.children()
def ignore_cycle(node, stack): pass
def do_nothing(node, parent): pass