diff options
Diffstat (limited to 'engine/SCons/Node/__init__.py')
-rw-r--r-- | engine/SCons/Node/__init__.py | 81 |
1 files changed, 60 insertions, 21 deletions
diff --git a/engine/SCons/Node/__init__.py b/engine/SCons/Node/__init__.py index 299673f..889e7a4 100644 --- a/engine/SCons/Node/__init__.py +++ b/engine/SCons/Node/__init__.py @@ -22,7 +22,7 @@ be able to depend on any other type of "thing." from __future__ import print_function # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -43,8 +43,9 @@ from __future__ import print_function # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Node/__init__.py 74b2c53bc42290e911b334a6b44f187da698a668 2017/11/14 13:16:53 bdbaddog" +__revision__ = "src/engine/SCons/Node/__init__.py a56bbd8c09fb219ab8a9673330ffcd55279219d0 2019-03-26 23:16:31 bdeegan" +import os import collections import copy from itertools import chain @@ -139,6 +140,7 @@ def exists_entry(node): node.disambiguate() return _exists_map[node._func_exists](node) + def exists_file(node): # Duplicate from source path if we are set up to do this. if node.duplicate and not node.is_derived() and not node.linked: @@ -155,7 +157,7 @@ def exists_file(node): # The source file does not exist. Make sure no old # copy remains in the variant directory. if print_duplicate: - print("dup: no src for %s, unlinking old variant copy"%self) + print("dup: no src for %s, unlinking old variant copy" % node) if exists_base(node) or node.islink(): node.fs.unlink(node.get_internal_path()) # Return None explicitly because the Base.exists() call @@ -246,6 +248,21 @@ _target_from_source_map = {0 : target_from_source_none, # used by it. # + +class DeciderNeedsNode(Exception): + """ + Indicate that the decider needs the node as well as the target and the dependency. + Normally the node and the target are the same, but in the case of repository + They may be different. Also the NodeInfo is retrieved from the node + """ + def __init__(self, call_this_decider): + """ + :param call_this_decider: to return the decider to call directly since deciders + are called through several levels of indirection + """ + self.decider = call_this_decider + + # # First, the single decider functions # @@ -269,6 +286,7 @@ def changed_since_last_build_node(node, target, prev_ni): """ raise NotImplementedError + def changed_since_last_build_alias(node, target, prev_ni): cur_csig = node.get_csig() try: @@ -276,19 +294,24 @@ def changed_since_last_build_alias(node, target, prev_ni): except AttributeError: return 1 + def changed_since_last_build_entry(node, target, prev_ni): node.disambiguate() return _decider_map[node.changed_since_last_build](node, target, prev_ni) + def changed_since_last_build_state_changed(node, target, prev_ni): - return (node.state != SCons.Node.up_to_date) + return node.state != SCons.Node.up_to_date + def decide_source(node, target, prev_ni): return target.get_build_env().decide_source(node, target, prev_ni) + def decide_target(node, target, prev_ni): return target.get_build_env().decide_target(node, target, prev_ni) + def changed_since_last_build_python(node, target, prev_ni): cur_csig = node.get_csig() try: @@ -380,6 +403,7 @@ class NodeInfoBase(object): """ state = other.__getstate__() self.__setstate__(state) + def format(self, field_list=None, names=0): if field_list is None: try: @@ -665,7 +689,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): executor.cleanup() def reset_executor(self): - "Remove cached executor; forces recompute when needed." + """Remove cached executor; forces recompute when needed.""" try: delattr(self, 'executor') except AttributeError: @@ -1136,7 +1160,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): binfo.bactsig = SCons.Util.MD5signature(executor.get_contents()) if self._specific_sources: - sources = [ s for s in self.sources if not s in ignore_set] + sources = [s for s in self.sources if not s in ignore_set] else: sources = executor.get_unignored_sources(self, self.ignore) @@ -1145,13 +1169,17 @@ class Node(object, with_metaclass(NoSlotsPyPy)): binfo.bsources = [s for s in sources if s not in seen and not seen.add(s)] binfo.bsourcesigs = [s.get_ninfo() for s in binfo.bsources] + binfo.bdepends = [d for d in self.depends if d not in ignore_set] + binfo.bdependsigs = [d.get_ninfo() for d in self.depends] - binfo.bdepends = self.depends - binfo.bdependsigs = [d.get_ninfo() for d in self.depends if d not in ignore_set] - - binfo.bimplicit = self.implicit or [] - binfo.bimplicitsigs = [i.get_ninfo() for i in binfo.bimplicit if i not in ignore_set] - + # Because self.implicit is initialized to None (and not empty list []) + # we have to handle this case + if not self.implicit: + binfo.bimplicit = [] + binfo.bimplicitsigs = [] + else: + binfo.bimplicit = [i for i in self.implicit if i not in ignore_set] + binfo.bimplicitsigs = [i.get_ninfo() for i in binfo.bimplicit] return binfo @@ -1213,7 +1241,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): return _exists_map[self._func_exists](self) def rexists(self): - """Does this node exist locally or in a repositiory?""" + """Does this node exist locally or in a repository?""" # There are no repositories by default: return _rexists_map[self._func_rexists](self) @@ -1452,13 +1480,18 @@ class Node(object, with_metaclass(NoSlotsPyPy)): result = True for child, prev_ni in zip(children, then): - if _decider_map[child.changed_since_last_build](child, self, prev_ni): - if t: Trace(': %s changed' % child) - result = True + try: + if _decider_map[child.changed_since_last_build](child, self, prev_ni): + if t: Trace(': %s changed' % child) + result = True + except DeciderNeedsNode as e: + if e.decider(self, prev_ni, node=node): + if t: Trace(': %s changed' % child) + result = True - contents = self.get_executor().get_contents() if self.has_builder(): import SCons.Util + contents = self.get_executor().get_contents() newsig = SCons.Util.MD5signature(contents) if bi.bactsig != newsig: if t: Trace(': bactsig %s != newsig %s' % (bi.bactsig, newsig)) @@ -1607,7 +1640,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): # so we only print them after running them through this lambda # to turn them into the right relative Node and then return # its string. - def stringify( s, E=self.dir.Entry ) : + def stringify( s, E=self.dir.Entry): if hasattr( s, 'dir' ) : return str(E(s)) return str(s) @@ -1616,15 +1649,21 @@ class Node(object, with_metaclass(NoSlotsPyPy)): removed = [x for x in old_bkids if not x in new_bkids] if removed: - removed = list(map(stringify, removed)) + removed = [stringify(r) for r in removed] fmt = "`%s' is no longer a dependency\n" lines.extend([fmt % s for s in removed]) for k in new_bkids: if not k in old_bkids: lines.append("`%s' is a new dependency\n" % stringify(k)) - elif _decider_map[k.changed_since_last_build](k, self, osig[k]): - lines.append("`%s' changed\n" % stringify(k)) + else: + try: + changed = _decider_map[k.changed_since_last_build](k, self, osig[k]) + except DeciderNeedsNode as e: + changed = e.decider(self, osig[k], node=self) + + if changed: + lines.append("`%s' changed\n" % stringify(k)) if len(lines) == 0 and old_bkids != new_bkids: lines.append("the dependency order changed:\n" + |