diff options
Diffstat (limited to 'src/engine/SCons/Node/__init__.py')
| -rw-r--r-- | src/engine/SCons/Node/__init__.py | 125 | 
1 files changed, 87 insertions, 38 deletions
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 793e101..5455bd6 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/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,12 +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 rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__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 @@ -102,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 @@ -139,6 +145,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 +162,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 @@ -249,7 +256,7 @@ _target_from_source_map = {0 : target_from_source_none,  #  # 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 @@ -269,27 +276,33 @@ 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      except AttributeError:          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): -    return (node.state != SCons.Node.up_to_date) +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_target(node, target, prev_ni): -    return target.get_build_env().decide_target(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 changed_since_last_build_python(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, repo_node=None):      cur_csig = node.get_csig()      try:          return cur_csig != prev_ni.csig @@ -380,6 +393,7 @@ class NodeInfoBase(object):          """          state = other.__getstate__()          self.__setstate__(state) +      def format(self, field_list=None, names=0):          if field_list is None:              try: @@ -505,6 +519,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)):      __slots__ = ['sources',                   'sources_set', +                 'target_peers',                   '_specific_sources',                   'depends',                   'depends_set', @@ -665,7 +680,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: @@ -760,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: @@ -1136,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) @@ -1145,13 +1179,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 +1251,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 +1490,12 @@ 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 _decider_map[child.changed_since_last_build](child, self, prev_ni, 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,29 +1644,42 @@ 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)          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 = 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: +            if k not 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" + -                         "%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): @@ -1672,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.  | 
