diff options
Diffstat (limited to 'engine/SCons/Node/__init__.py')
| -rw-r--r-- | engine/SCons/Node/__init__.py | 98 | 
1 files changed, 54 insertions, 44 deletions
diff --git a/engine/SCons/Node/__init__.py b/engine/SCons/Node/__init__.py index 889e7a4..5455bd6 100644 --- a/engine/SCons/Node/__init__.py +++ b/engine/SCons/Node/__init__.py @@ -43,13 +43,18 @@ 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 a56bbd8c09fb219ab8a9673330ffcd55279219d0 2019-03-26 23:16:31 bdeegan" +__revision__ = "src/engine/SCons/Node/__init__.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan"  import os  import collections  import copy  from itertools import chain +try: +    from itertools import zip_longest +except ImportError: +    from itertools import izip_longest as zip_longest +  import SCons.Debug  from SCons.Debug import logInstanceCreation  import SCons.Executor @@ -103,9 +108,9 @@ implicit_deps_changed = 0  # A variable that can be set to an interface-specific function be called  # to annotate a Node with information about its creation. -def do_nothing(node): pass +def do_nothing_node(node): pass -Annotate = do_nothing +Annotate = do_nothing_node  # Gets set to 'True' if we're running in interactive mode. Is  # currently used to release parts of a target's info during @@ -248,25 +253,10 @@ _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  # -def changed_since_last_build_node(node, target, prev_ni): +def changed_since_last_build_node(node, target, prev_ni, repo_node=None):      """      Must be overridden in a specific subclass to return True if this @@ -287,7 +277,7 @@ def changed_since_last_build_node(node, target, prev_ni):      raise NotImplementedError -def changed_since_last_build_alias(node, target, prev_ni): +def changed_since_last_build_alias(node, target, prev_ni, repo_node=None):      cur_csig = node.get_csig()      try:          return cur_csig != prev_ni.csig @@ -295,24 +285,24 @@ def changed_since_last_build_alias(node, target, prev_ni):          return 1 -def changed_since_last_build_entry(node, target, prev_ni): +def changed_since_last_build_entry(node, target, prev_ni, repo_node=None):      node.disambiguate() -    return _decider_map[node.changed_since_last_build](node, target, prev_ni) +    return _decider_map[node.changed_since_last_build](node, target, prev_ni, repo_node) -def changed_since_last_build_state_changed(node, target, prev_ni): +def changed_since_last_build_state_changed(node, target, prev_ni, repo_node=None):      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_source(node, target, prev_ni, repo_node=None): +    return target.get_build_env().decide_source(node, target, prev_ni, repo_node) -def decide_target(node, target, prev_ni): -    return target.get_build_env().decide_target(node, target, prev_ni) +def decide_target(node, target, prev_ni, repo_node=None): +    return target.get_build_env().decide_target(node, target, prev_ni, repo_node) -def changed_since_last_build_python(node, target, prev_ni): +def changed_since_last_build_python(node, target, prev_ni, repo_node=None):      cur_csig = node.get_csig()      try:          return cur_csig != prev_ni.csig @@ -529,6 +519,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)):      __slots__ = ['sources',                   'sources_set', +                 'target_peers',                   '_specific_sources',                   'depends',                   'depends_set', @@ -784,6 +775,25 @@ class Node(object, with_metaclass(NoSlotsPyPy)):          for parent in self.waiting_parents:              parent.implicit = None +            # Handle issue where builder emits more than one target and +            # the source file for the builder is generated. +            # in that case only the first target was getting it's .implicit +            # cleared when the source file is built (second scan).  +            # leaving only partial implicits from scan before source file is generated +            # typically the compiler only. Then scanned files are appended +            # This is persisted to sconsign and rebuild causes false rebuilds +            # because the ordering of the implicit list then changes to what it +            # should have been. +            # This is at least the following bugs +            # https://github.com/SCons/scons/issues/2811 +            # https://jira.mongodb.org/browse/SERVER-33111 +            try: +                for peer in parent.target_peers: +                    peer.implicit = None +            except AttributeError: +                pass + +          self.clear()          if self.pseudo: @@ -1160,7 +1170,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 s not in ignore_set]          else:              sources = executor.get_unignored_sources(self, self.ignore) @@ -1480,17 +1490,11 @@ class Node(object, with_metaclass(NoSlotsPyPy)):              result = True          for child, prev_ni in zip(children, then): -            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 +            if _decider_map[child.changed_since_last_build](child, self, prev_ni, node): +                if t: Trace(': %s changed' % child) +                result = True          if self.has_builder(): -            import SCons.Util              contents = self.get_executor().get_contents()              newsig = SCons.Util.MD5signature(contents)              if bi.bactsig != newsig: @@ -1647,14 +1651,14 @@ class Node(object, with_metaclass(NoSlotsPyPy)):          lines = [] -        removed = [x for x in old_bkids if not x in new_bkids] +        removed = [x for x in old_bkids if x not in new_bkids]          if 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: +            if k not in old_bkids:                  lines.append("`%s' is a new dependency\n" % stringify(k))              else:                  try: @@ -1666,9 +1670,16 @@ class Node(object, with_metaclass(NoSlotsPyPy)):                      lines.append("`%s' changed\n" % stringify(k))          if len(lines) == 0 and old_bkids != new_bkids: -            lines.append("the dependency order changed:\n" + -                         "%sold: %s\n" % (' '*15, list(map(stringify, old_bkids))) + -                         "%snew: %s\n" % (' '*15, list(map(stringify, new_bkids)))) +            lines.append("the dependency order changed:\n") +            lines.append("->Sources\n") +            for (o,n) in zip_longest(old.bsources, new.bsources, fillvalue=None): +                lines.append("Old:%s\tNew:%s\n"%(o,n)) +            lines.append("->Depends\n") +            for (o,n) in zip_longest(old.bdepends, new.bdepends, fillvalue=None): +                lines.append("Old:%s\tNew:%s\n"%(o,n)) +            lines.append("->Implicit\n") +            for (o,n) in zip_longest(old.bimplicit, new.bimplicit, fillvalue=None): +                lines.append("Old:%s\tNew:%s\n"%(o,n))          if len(lines) == 0:              def fmt_with_title(title, strlines): @@ -1711,7 +1722,6 @@ class Walker(object):      This is depth-first, children are visited before the parent.      The Walker object can be initialized with any node, and      returns the next node on the descent with each get_next() call. -    'kids_func' is an optional function that will be called to      get the children of a node instead of calling 'children'.      'cycle_func' is an optional function that will be called      when a cycle is detected.  | 
