SCons.Node

Package SCons :: Package Node |
[hide private]
[frames] | no frames]

# Source Code for Package SCons.Node

       1  """SCons.Node
       2
       3  The Node package for the SCons software construction utility.
       4
       5  This is, in many ways, the heart of SCons.
       6
       7  A Node is where we encapsulate all of the dependency information about
       8  any thing that SCons can build, or about any thing which SCons can use
       9  to build some other thing.  The canonical "thing," of course, is a file,
      10  but a Node can also represent something remote (like a web page) or
      11  something completely abstract (like an Alias).
      12
      13  Each specific type of "thing" is specifically represented by a subclass
      14  of the Node base class:  Node.FS.File for files, Node.Alias for aliases,
      15  etc.  Dependency information is kept here in the base class, and
      16  information specific to files/aliases/etc. is in the subclass.  The
      17  goal, if we've done this correctly, is that any type of "thing" should
      18  be able to depend on any other type of "thing."
      19
      20  """
      21
      22  #
      23  # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
      24  #
      25  # Permission is hereby granted, free of charge, to any person obtaining
      26  # a copy of this software and associated documentation files (the
      27  # "Software"), to deal in the Software without restriction, including
      28  # without limitation the rights to use, copy, modify, merge, publish,
      29  # distribute, sublicense, and/or sell copies of the Software, and to
      30  # permit persons to whom the Software is furnished to do so, subject to
      31  # the following conditions:
      32  #
      33  # The above copyright notice and this permission notice shall be included
      34  # in all copies or substantial portions of the Software.
      35  #
      36  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
      37  # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
      38  # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      39  # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      40  # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      41  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      42  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      43  #
      44
      45  __revision__ = "src/engine/SCons/Node/__init__.py 2725 2008/03/31 12:52:02 knight"
      46
      47  import SCons.compat
      48
      49  import copy
      50  import string
      51  import UserList
      52
      53  from SCons.Debug import logInstanceCreation
      54  import SCons.Executor
      55  import SCons.Memoize
      56  import SCons.Util
      57
      58  from SCons.Debug import Trace
      59
      60 -def classname(obj):
      61      return string.split(str(obj.__class__), '.')[-1]
      62
      63  # Node states
      64  #
      65  # These are in "priority" order, so that the maximum value for any
      66  # child/dependency of a node represents the state of that node if
      67  # it has no builder of its own.  The canonical example is a file
      68  # system directory, which is only up to date if all of its children
      69  # were up to date.
      70  no_state = 0
      71  pending = 1
      72  executing = 2
      73  up_to_date = 3
      74  executed = 4
      75  failed = 5
      76
      77  StateString = {
      78      0 : "0",
      79      1 : "pending",
      80      2 : "executing",
      81      3 : "up_to_date",
      82      4 : "executed",
      83      5 : "failed",
      84  }
      85
      86  # controls whether implicit dependencies are cached:
      87  implicit_cache = 0
      88
      89  # controls whether implicit dep changes are ignored:
      90  implicit_deps_unchanged = 0
      91
      92  # controls whether the cached implicit deps are ignored:
      93  implicit_deps_changed = 0
      94
      95  # A variable that can be set to an interface-specific function be called
      96  # to annotate a Node with information about its creation.
      97 -def do_nothing(node): pass
      98
      99  Annotate = do_nothing
     100
     101  # Classes for signature info for Nodes.
     102
     103 -class NodeInfoBase:
     104      """
     105      The generic base class for signature information for a Node.
     106
     107      Node subclasses should subclass NodeInfoBase to provide their own
     108      logic for dealing with their own Node-specific signature information.
     109      """
     110      current_version_id = 1
     111 -    def __init__(self, node):
     112          # Create an object attribute from the class attribute so it ends up
     113          # in the pickled data in the .sconsign file.
     114          self._version_id = self.current_version_id
     115 -    def update(self, node):
     116          try:
     117              field_list = self.field_list
     118          except AttributeError:
     119              return
     120          for f in field_list:
     121              try:
     122                  delattr(self, f)
     123              except AttributeError:
     124                  pass
     125              try:
     126                  func = getattr(node, 'get_' + f)
     127              except AttributeError:
     128                  pass
     129              else:
     130                  setattr(self, f, func())
     131 -    def convert(self, node, val):
     132          pass
     133 -    def merge(self, other):
     134          self.__dict__.update(other.__dict__)
     135 -    def format(self, field_list=None, names=0):
     136          if field_list is None:
     137              try:
     138                  field_list = self.field_list
     139              except AttributeError:
     140                  field_list = self.__dict__.keys()
     141                  field_list.sort()
     142          fields = []
     143          for field in field_list:
     144              try:
     145                  f = getattr(self, field)
     146              except AttributeError:
     147                  f = None
     148              f = str(f)
     149              if names:
     150                  f = field + ': ' + f
     151              fields.append(f)
     152          return fields
     153
     154 -class BuildInfoBase:
     155      """
     156      The generic base class for build information for a Node.
     157
     158      This is what gets stored in a .sconsign file for each target file.
     159      It contains a NodeInfo instance for this node (signature information
     160      that's specific to the type of Node) and direct attributes for the
     161      generic build stuff we have to track:  sources, explicit dependencies,
     162      implicit dependencies, and action information.
     163      """
     164      current_version_id = 1
     165 -    def __init__(self, node):
     166          # Create an object attribute from the class attribute so it ends up
     167          # in the pickled data in the .sconsign file.
     168          self._version_id = self.current_version_id
     169          self.bsourcesigs = []
     170          self.bdependsigs = []
     171          self.bimplicitsigs = []
     172          self.bactsig = None
     173 -    def merge(self, other):
     174          self.__dict__.update(other.__dict__)
     175
     176 -class Node:
     177      """The base Node class, for entities that we know how to
     178      build, or use to build other Nodes.
     179      """
     180
     181      if SCons.Memoize.use_memoizer:
     182          __metaclass__ = SCons.Memoize.Memoized_Metaclass
     183
     184      memoizer_counters = []
     185
     186 -    class Attrs:
     187          pass
     188
     189 -    def __init__(self):
     190          if __debug__: logInstanceCreation(self, 'Node.Node')
     191          # Note that we no longer explicitly initialize a self.builder
     192          # attribute to None here.  That's because the self.builder
     193          # attribute may be created on-the-fly later by a subclass (the
     194          # canonical example being a builder to fetch a file from a
     195          # source code system like CVS or Subversion).
     196
     197          # Each list of children that we maintain is accompanied by a
     198          # dictionary used to look up quickly whether a node is already
     199          # present in the list.  Empirical tests showed that it was
     200          # fastest to maintain them as side-by-side Node attributes in
     201          # this way, instead of wrapping up each list+dictionary pair in
     202          # a class.  (Of course, we could always still do that in the
     203          # future if we had a good reason to...).
     204          self.sources = []       # source files used to build node
     205          self.sources_dict = {}
     206          self.depends = []       # explicit dependencies (from Depends)
     207          self.depends_dict = {}
     208          self.ignore = []        # dependencies to ignore
     209          self.ignore_dict = {}
     210          self.prerequisites = SCons.Util.UniqueList()
     211          self.implicit = None    # implicit (scanned) dependencies (None means not scanned yet)
     212          self.waiting_parents = {}
     213          self.waiting_s_e = {}
     214          self.ref_count = 0
     215          self.wkids = None       # Kids yet to walk, when it's an array
     216
     217          self.env = None
     218          self.state = no_state
     219          self.precious = None
     220          self.noclean = 0
     221          self.nocache = 0
     222          self.always_build = None
     223          self.found_includes = {}
     224          self.includes = None
     225          self.attributes = self.Attrs() # Generic place to stick information about the Node.
     226          self.side_effect = 0 # true iff this node is a side effect
     227          self.side_effects = [] # the side effects of building this target
     228          self.linked = 0 # is this node linked to the variant directory?
     229
     230          self.clear_memoized_values()
     231
     232          # Let the interface in which the build engine is embedded
     233          # annotate this Node with its own info (like a description of
     234          # what line in what file created the node, for example).
     235          Annotate(self)
     236
     237 -    def disambiguate(self, must_exist=None):
     238          return self
     239
     240 -    def get_suffix(self):
     241          return ''
     242
     243      memoizer_counters.append(SCons.Memoize.CountValue('get_build_env'))
     244
     245 -    def get_build_env(self):
     246          """Fetch the appropriate Environment to build this node.
     247          """
     248          try:
     249              return self._memo['get_build_env']
     250          except KeyError:
     251              pass
     252          result = self.get_executor().get_build_env()
     253          self._memo['get_build_env'] = result
     254          return result
     255
     256 -    def get_build_scanner_path(self, scanner):
     257          """Fetch the appropriate scanner path for this node."""
     258          return self.get_executor().get_build_scanner_path(scanner)
     259
     260 -    def set_executor(self, executor):
     261          """Set the action executor for this node."""
     262          self.executor = executor
     263
     264 -    def get_executor(self, create=1):
     265          """Fetch the action executor for this node.  Create one if
     266          there isn't already one, and requested to do so."""
     267          try:
     268              executor = self.executor
     269          except AttributeError:
     270              if not create:
     271                  raise
     272              try:
     273                  act = self.builder.action
     274              except AttributeError:
     275                  executor = SCons.Executor.Null(targets=[self])
     276              else:
     277                  executor = SCons.Executor.Executor(act,
     278                                                     self.env or self.builder.env,
     279                                                     [self.builder.overrides],
     280                                                     [self],
     281                                                     self.sources)
     282              self.executor = executor
     283          return executor
     284
     285 -    def executor_cleanup(self):
     286          """Let the executor clean up any cached information."""
     287          try:
     288              executor = self.get_executor(create=None)
     289          except AttributeError:
     290              pass
     291          else:
     292              executor.cleanup()
     293
     294 -    def reset_executor(self):
     295          "Remove cached executor; forces recompute when needed."
     296          try:
     297              delattr(self, 'executor')
     298          except AttributeError:
     299              pass
     300
     301 -    def retrieve_from_cache(self):
     302          """Try to retrieve the node's content from a cache
     303
     304          This method is called from multiple threads in a parallel build,
     305          so only do thread safe stuff here. Do thread unsafe stuff in
     306          built().
     307
     308          Returns true iff the node was successfully retrieved.
     309          """
     310          return 0
     311
     312      #
     313      # Taskmaster interface subsystem
     314      #
     315
     316 -    def make_ready(self):
     317          """Get a Node ready for evaluation.
     318
     319          This is called before the Taskmaster decides if the Node is
     320          up-to-date or not.  Overriding this method allows for a Node
     321          subclass to be disambiguated if necessary, or for an implicit
     322          source builder to be attached.
     323          """
     324          pass
     325
     326 -    def prepare(self):
     327          """Prepare for this Node to be built.
     328
     329          This is called after the Taskmaster has decided that the Node
     330          is out-of-date and must be rebuilt, but before actually calling
     331          the method to build the Node.
     332
     333          This default implemenation checks that all children either exist
     334          or are derived, and initializes the BuildInfo structure that
     335          will hold the information about how this node is, uh, built.
     336
     337          Overriding this method allows for for a Node subclass to remove
     338          the underlying file from the file system.  Note that subclass
     339          methods should call this base class method to get the child
     340          check and the BuildInfo structure.
     341          """
     342          l = self.depends
     343          if not self.implicit is None:
     344              l = l + self.implicit
     345          missing_sources = self.get_executor().get_missing_sources() \
     346                            + filter(lambda c: c.missing(), l)
     347          if missing_sources:
     348              desc = "Source `%s' not found, needed by target `%s'." % (missing_sources[0], self)
     349              raise SCons.Errors.StopError, desc
     350
     351          self.binfo = self.get_binfo()
     352
     353 -    def build(self, **kw):
     354          """Actually build the node.
     355
     356          This is called by the Taskmaster after it's decided that the
     357          Node is out-of-date and must be rebuilt, and after the prepare()
     358          method has gotten everything, uh, prepared.
     359
     360          This method is called from multiple threads in a parallel build,
     361          so only do thread safe stuff here. Do thread unsafe stuff
     362          in built().
     363
     364          """
     365          try:
     366              apply(self.get_executor(), (self,), kw)
     367          except SCons.Errors.BuildError, e:
     368              e.node = self
     369              raise
     370
     371 -    def built(self):
     372          """Called just after this node is successfully built."""
     373
     374          # Clear the implicit dependency caches of any Nodes
     375          # waiting for this Node to be built.
     376          for parent in self.waiting_parents.keys():
     377              parent.implicit = None
     378
     379          self.clear()
     380
     381          self.ninfo.update(self)
     382
     383 -    def visited(self):
     384          """Called just after this node has been visited (with or
     385          without a build)."""
     386          try:
     387              binfo = self.binfo
     388          except AttributeError:
     389              # Apparently this node doesn't need build info, so
     390              # don't bother calculating or storing it.
     391              pass
     392          else:
     393              self.ninfo.update(self)
     394              self.store_info()
     395
     396      #
     397      #
     398      #
     399
     400 -    def add_to_waiting_s_e(self, node):
     401          self.waiting_s_e[node] = 1
     402
     403 -    def add_to_waiting_parents(self, node):
     404          """
     405          Returns the number of nodes added to our waiting parents list:
     406          1 if we add a unique waiting parent, 0 if not.  (Note that the
     407          returned values are intended to be used to increment a reference
     408          count, so don't think you can "clean up" this function by using
     409          True and False instead...)
     410          """
     411          wp = self.waiting_parents
     412          if wp.has_key(node):
     413              result = 0
     414          else:
     415              result = 1
     416          wp[node] = 1
     417          return result
     418
     419 -    def call_for_all_waiting_parents(self, func):
     420          func(self)
     421          for parent in self.waiting_parents.keys():
     422              parent.call_for_all_waiting_parents(func)
     423
     424 -    def postprocess(self):
     425          """Clean up anything we don't need to hang onto after we've
     426          been built."""
     427          self.executor_cleanup()
     428          self.waiting_parents = {}
     429
     430 -    def clear(self):
     431          """Completely clear a Node of all its cached state (so that it
     432          can be re-evaluated by interfaces that do continuous integration
     433          builds).
     434          """
     435          # The del_binfo() call here isn't necessary for normal execution,
     436          # but is for interactive mode, where we might rebuild the same
     437          # target and need to start from scratch.
     438          self.del_binfo()
     439          self.clear_memoized_values()
     440          self.ninfo = self.new_ninfo()
     441          self.executor_cleanup()
     442          try:
     443              delattr(self, '_calculated_sig')
     444          except AttributeError:
     445              pass
     446          self.includes = None
     447          self.found_includes = {}
     448
     449 -    def clear_memoized_values(self):
     450          self._memo = {}
     451
     452 -    def builder_set(self, builder):
     453          self.builder = builder
     454          try:
     455              del self.executor
     456          except AttributeError:
     457              pass
     458
     459 -    def has_builder(self):
     460          """Return whether this Node has a builder or not.
     461
     462          In Boolean tests, this turns out to be a *lot* more efficient
     463          than simply examining the builder attribute directly ("if
     464          node.builder: ..."). When the builder attribute is examined
     465          directly, it ends up calling __getattr__ for both the __len__
     466          and __nonzero__ attributes on instances of our Builder Proxy
     467          class(es), generating a bazillion extra calls and slowing
     468          things down immensely.
     469          """
     470          try:
     471              b = self.builder
     472          except AttributeError:
     473              # There was no explicit builder for this Node, so initialize
     474              # the self.builder attribute to None now.
     475              b = self.builder = None
     476          return not b is None
     477
     478 -    def set_explicit(self, is_explicit):
     479          self.is_explicit = is_explicit
     480
     481 -    def has_explicit_builder(self):
     482          """Return whether this Node has an explicit builder
     483
     484          This allows an internal Builder created by SCons to be marked
     485          non-explicit, so that it can be overridden by an explicit
     486          builder that the user supplies (the canonical example being
     487          directories)."""
     488          try:
     489              return self.is_explicit
     490          except AttributeError:
     491              self.is_explicit = None
     492              return self.is_explicit
     493
     494 -    def get_builder(self, default_builder=None):
     495          """Return the set builder, or a specified default value"""
     496          try:
     497              return self.builder
     498          except AttributeError:
     499              return default_builder
     500
     501      multiple_side_effect_has_builder = has_builder
     502
     503 -    def is_derived(self):
     504          """
     505          Returns true iff this node is derived (i.e. built).
     506
     507          This should return true only for nodes whose path should be in
     508          the variant directory when duplicate=0 and should contribute their build
     509          signatures when they are used as source files to other derived files. For
     510          example: source with source builders are not derived in this sense,
     511          and hence should not return true.
     512          """
     513          return self.has_builder() or self.side_effect
     514
     515 -    def alter_targets(self):
     516          """Return a list of alternate targets for this Node.
     517          """
     518          return [], None
     519
     520 -    def get_found_includes(self, env, scanner, path):
     521          """Return the scanned include lines (implicit dependencies)
     522          found in this node.
     523
     524          The default is no implicit dependencies.  We expect this method
     525          to be overridden by any subclass that can be scanned for
     526          implicit dependencies.
     527          """
     528          return []
     529
     530 -    def get_implicit_deps(self, env, scanner, path):
     531          """Return a list of implicit dependencies for this node.
     532
     533          This method exists to handle recursive invocation of the scanner
     534          on the implicit dependencies returned by the scanner, if the
     535          scanner's recursive flag says that we should.
     536          """
     537          if not scanner:
     538              return []
     539
     540          # Give the scanner a chance to select a more specific scanner
     541          # for this Node.
     542          #scanner = scanner.select(self)
     543
     544          nodes = [self]
     545          seen = {}
     546          seen[self] = 1
     547          deps = []
     548          while nodes:
     549              n = nodes.pop(0)
     550              d = filter(lambda x, seen=seen: not seen.has_key(x),
     551                         n.get_found_includes(env, scanner, path))
     552              if d:
     553                  deps.extend(d)
     554                  for n in d:
     555                      seen[n] = 1
     556                  nodes.extend(scanner.recurse_nodes(d))
     557
     558          return deps
     559
     560 -    def get_env_scanner(self, env, kw={}):
     561          return env.get_scanner(self.scanner_key())
     562
     563 -    def get_target_scanner(self):
     564          return self.builder.target_scanner
     565
     566 -    def get_source_scanner(self, node):
     567          """Fetch the source scanner for the specified node
     568
     569          NOTE:  "self" is the target being built, "node" is
     570          the source file for which we want to fetch the scanner.
     571
     572          Implies self.has_builder() is true; again, expect to only be
     573          called from locations where this is already verified.
     574
     575          This function may be called very often; it attempts to cache
     576          the scanner found to improve performance.
     577          """
     578          scanner = None
     579          try:
     580              scanner = self.builder.source_scanner
     581          except AttributeError:
     582              pass
     583          if not scanner:
     584              # The builder didn't have an explicit scanner, so go look up
     585              # a scanner from env['SCANNERS'] based on the node's scanner
     586              # key (usually the file extension).
     587              scanner = self.get_env_scanner(self.get_build_env())
     588          if scanner:
     589              scanner = scanner.select(node)
     590          return scanner
     591
     592 -    def add_to_implicit(self, deps):
     593          if not hasattr(self, 'implicit') or self.implicit is None:
     594              self.implicit = []
     595              self.implicit_dict = {}
     596              self._children_reset()
     597          self._add_child(self.implicit, self.implicit_dict, deps)
     598
     599 -    def scan(self):
     600          """Scan this node's dependents for implicit dependencies."""
     601          # Don't bother scanning non-derived files, because we don't
     602          # care what their dependencies are.
     603          # Don't scan again, if we already have scanned.
     604          if not self.implicit is None:
     605              return
     606          self.implicit = []
     607          self.implicit_dict = {}
     608          self._children_reset()
     609          if not self.has_builder():
     610              return
     611
     612          build_env = self.get_build_env()
     613          executor = self.get_executor()
     614
     615          # Here's where we implement --implicit-cache.
     616          if implicit_cache and not implicit_deps_changed:
     617              implicit = self.get_stored_implicit()
     618              if implicit is not None:
     619                  # We now add the implicit dependencies returned from the
     620                  # stored .sconsign entry to have already been converted
     621                  # to Nodes for us.  (We used to run them through a
     622                  # source_factory function here.)
     623
     624                  # Update all of the targets with them.  This
     625                  # essentially short-circuits an N*M scan of the
     626                  # sources for each individual target, which is a hell
     627                  # of a lot more efficient.
     628                  for tgt in executor.targets:
     629                      tgt.add_to_implicit(implicit)
     630
     631                  if implicit_deps_unchanged or self.is_up_to_date():
     632                      return
     633                  # one of this node's sources has changed,
     634                  # so we must recalculate the implicit deps:
     635                  self.implicit = []
     636                  self.implicit_dict = {}
     637
     638          # Have the executor scan the sources.
     639          executor.scan_sources(self.builder.source_scanner)
     640
     641          # If there's a target scanner, have the executor scan the target
     642          # node itself and associated targets that might be built.
     643          scanner = self.get_target_scanner()
     644          if scanner:
     645              executor.scan_targets(scanner)
     646
     647 -    def scanner_key(self):
     648          return None
     649
     650 -    def select_scanner(self, scanner):
     651          """Selects a scanner for this Node.
     652
     653          This is a separate method so it can be overridden by Node
     654          subclasses (specifically, Node.FS.Dir) that *must* use their
     655          own Scanner and don't select one the Scanner.Selector that's
     656          configured for the target.
     657          """
     658          return scanner.select(self)
     659
     660 -    def env_set(self, env, safe=0):
     661          if safe and self.env:
     662              return
     663          self.env = env
     664
     665      #
     666      # SIGNATURE SUBSYSTEM
     667      #
     668
     669      NodeInfo = NodeInfoBase
     670      BuildInfo = BuildInfoBase
     671
     672 -    def new_ninfo(self):
     673          ninfo = self.NodeInfo(self)
     674          return ninfo
     675
     676 -    def get_ninfo(self):
     677          try:
     678              return self.ninfo
     679          except AttributeError:
     680              self.ninfo = self.new_ninfo()
     681              return self.ninfo
     682
     683 -    def new_binfo(self):
     684          binfo = self.BuildInfo(self)
     685          return binfo
     686
     687 -    def get_binfo(self):
     688          """
     689          Fetch a node's build information.
     690
     691          node - the node whose sources will be collected
     692          cache - alternate node to use for the signature cache
     693          returns - the build signature
     694
     695          This no longer handles the recursive descent of the
     696          node's children's signatures.  We expect that they're
     697          already built and updated by someone else, if that's
     698          what's wanted.
     699          """
     700          try:
     701              return self.binfo
     702          except AttributeError:
     703              pass
     704
     705          binfo = self.new_binfo()
     706          self.binfo = binfo
     707
     708          executor = self.get_executor()
     709
     710          sources = executor.get_unignored_sources(self.ignore)
     711
     712          depends = self.depends
     713          implicit = self.implicit or []
     714
     715          if self.ignore:
     716              depends = filter(self.do_not_ignore, depends)
     717              implicit = filter(self.do_not_ignore, implicit)
     718
     719          def get_ninfo(node):
     720              return node.get_ninfo()
     721
     722          sourcesigs = map(get_ninfo, sources)
     723          dependsigs = map(get_ninfo, depends)
     724          implicitsigs = map(get_ninfo, implicit)
     725
     726          if self.has_builder():
     727              binfo.bact = str(executor)
     728              binfo.bactsig = SCons.Util.MD5signature(executor.get_contents())
     729
     730          binfo.bsources = sources
     731          binfo.bdepends = depends
     732          binfo.bimplicit = implicit
     733
     734          binfo.bsourcesigs = sourcesigs
     735          binfo.bdependsigs = dependsigs
     736          binfo.bimplicitsigs = implicitsigs
     737
     738          return binfo
     739
     740 -    def del_binfo(self):
     741          """Delete the build info from this node."""
     742          try:
     743              delattr(self, 'binfo')
     744          except AttributeError:
     745              pass
     746
     747 -    def get_csig(self):
     748          try:
     749              return self.ninfo.csig
     750          except AttributeError:
     751              ninfo = self.get_ninfo()
     752              ninfo.csig = SCons.Util.MD5signature(self.get_contents())
     753              return self.ninfo.csig
     754
     755 -    def get_cachedir_csig(self):
     756          return self.get_csig()
     757
     758 -    def store_info(self):
     759          """Make the build signature permanent (that is, store it in the
     760          .sconsign file or equivalent)."""
     761          pass
     762
     763 -    def do_not_store_info(self):
     764          pass
     765
     766 -    def get_stored_info(self):
     767          return None
     768
     769 -    def get_stored_implicit(self):
     770          """Fetch the stored implicit dependencies"""
     771          return None
     772
     773      #
     774      #
     775      #
     776
     777 -    def set_precious(self, precious = 1):
     778          """Set the Node's precious value."""
     779          self.precious = precious
     780
     781 -    def set_noclean(self, noclean = 1):
     782          """Set the Node's noclean value."""
     783          # Make sure noclean is an integer so the --debug=stree
     784          # output in Util.py can use it as an index.
     785          self.noclean = noclean and 1 or 0
     786
     787 -    def set_nocache(self, nocache = 1):
     788          """Set the Node's nocache value."""
     789          # Make sure nocache is an integer so the --debug=stree
     790          # output in Util.py can use it as an index.
     791          self.nocache = nocache and 1 or 0
     792
     793 -    def set_always_build(self, always_build = 1):
     794          """Set the Node's always_build value."""
     795          self.always_build = always_build
     796
     797 -    def exists(self):
     798          """Does this node exists?"""
     799          # All node exist by default:
     800          return 1
     801
     802 -    def rexists(self):
     803          """Does this node exist locally or in a repositiory?"""
     804          # There are no repositories by default:
     805          return self.exists()
     806
     807 -    def missing(self):
     808          return not self.is_derived() and \
     809                 not self.linked and \
     810                 not self.rexists()
     811
     812 -    def remove(self):
     813          """Remove this Node:  no-op by default."""
     814          return None
     815
     816 -    def add_dependency(self, depend):
     817          """Adds dependencies."""
     818          try:
     819              self._add_child(self.depends, self.depends_dict, depend)
     820          except TypeError, e:
     821              e = e.args[0]
     822              if SCons.Util.is_List(e):
     823                  s = map(str, e)
     824              else:
     825                  s = str(e)
     826              raise SCons.Errors.UserError("attempted to add a non-Node dependency to %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e)))
     827
     828 -    def add_prerequisite(self, prerequisite):
     829          """Adds prerequisites"""
     830          self.prerequisites.extend(prerequisite)
     831          self._children_reset()
     832
     833 -    def add_ignore(self, depend):
     834          """Adds dependencies to ignore."""
     835          try:
     836              self._add_child(self.ignore, self.ignore_dict, depend)
     837          except TypeError, e:
     838              e = e.args[0]
     839              if SCons.Util.is_List(e):
     840                  s = map(str, e)
     841              else:
     842                  s = str(e)
     843              raise SCons.Errors.UserError("attempted to ignore a non-Node dependency of %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e)))
     844
     845 -    def add_source(self, source):
     846          """Adds sources."""
     847          try:
     848              self._add_child(self.sources, self.sources_dict, source)
     849          except TypeError, e:
     850              e = e.args[0]
     851              if SCons.Util.is_List(e):
     852                  s = map(str, e)
     853              else:
     854                  s = str(e)
     855              raise SCons.Errors.UserError("attempted to add a non-Node as source of %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e)))
     856
     857 -    def _add_child(self, collection, dict, child):
     858          """Adds 'child' to 'collection', first checking 'dict' to see
     859          if it's already present."""
     860          #if type(child) is not type([]):
     861          #    child = [child]
     862          #for c in child:
     863          #    if not isinstance(c, Node):
     864          #        raise TypeError, c
     865          added = None
     866          for c in child:
     867              if not dict.has_key(c):
     868                  collection.append(c)
     869                  dict[c] = 1
     870                  added = 1
     871          if added:
     872              self._children_reset()
     873
     874 -    def add_wkid(self, wkid):
     875          """Add a node to the list of kids waiting to be evaluated"""
     876          if self.wkids != None:
     877              self.wkids.append(wkid)
     878
     879 -    def _children_reset(self):
     880          self.clear_memoized_values()
     881          # We need to let the Executor clear out any calculated
     882          # build info that it's cached so we can re-calculate it.
     883          self.executor_cleanup()
     884
     885 -    def do_not_ignore(self, node):
     886          return node not in self.ignore
     887
     888 -    def _all_children_get(self):
     889          # The return list may contain duplicate Nodes, especially in
     890          # source trees where there are a lot of repeated #includes
     891          # of a tangle of .h files.  Profiling shows, however, that
     892          # eliminating the duplicates with a brute-force approach that
     893          # preserves the order (that is, something like:
     894          #
     895          #       u = []
     896          #       for n in list:
     897          #           if n not in u:
     898          #               u.append(n)"
     899          #
     900          # takes more cycles than just letting the underlying methods
     901          # hand back cached values if a Node's information is requested
     902          # multiple times.  (Other methods of removing duplicates, like
     903          # using dictionary keys, lose the order, and the only ordered
     904          # dictionary patterns I found all ended up using "not in"
     905          # internally anyway...)
     906          if self.implicit is None:
     907              return self.sources + self.depends
     908          else:
     909              return self.sources + self.depends + self.implicit
     910
     911      memoizer_counters.append(SCons.Memoize.CountValue('_children_get'))
     912
     913 -    def _children_get(self):
     914          try:
     915              return self._memo['children_get']
     916          except KeyError:
     917              pass
     918          children = self._all_children_get()
     919          if self.ignore:
     920              children = filter(self.do_not_ignore, children)
     921          self._memo['children_get'] = children
     922          return children
     923
     924 -    def all_children(self, scan=1):
     925          """Return a list of all the node's direct children."""
     926          if scan:
     927              self.scan()
     928          return self._all_children_get()
     929
     930 -    def children(self, scan=1):
     931          """Return a list of the node's direct children, minus those
     932          that are ignored by this node."""
     933          if scan:
     934              self.scan()
     935          return self._children_get()
     936
     937 -    def set_state(self, state):
     938          self.state = state
     939
     940 -    def get_state(self):
     941          return self.state
     942
     943 -    def state_has_changed(self, target, prev_ni):
     944          return (self.state != SCons.Node.up_to_date)
     945
     946 -    def get_env(self):
     947          env = self.env
     948          if not env:
     949              import SCons.Defaults
     950              env = SCons.Defaults.DefaultEnvironment()
     951          return env
     952
     953 -    def changed_since_last_build(self, target, prev_ni):
     954          """
     955
     956          Must be overridden in a specific subclass to return True if this
     957          Node (a dependency) has changed since the last time it was used
     958          to build the specified target.  prev_ni is this Node's state (for
     959          example, its file timestamp, length, maybe content signature)
     960          as of the last time the target was built.
     961
     962          Note that this method is called through the dependency, not the
     963          target, because a dependency Node must be able to use its own
     964          logic to decide if it changed.  For example, File Nodes need to
     965          obey if we're configured to use timestamps, but Python Value Nodes
     966          never use timestamps and always use the content.  If this method
     967          were called through the target, then each Node's implementation
     968          of this method would have to have more complicated logic to
     969          handle all the different Node types on which it might depend.
     970          """
     971          raise NotImplementedError
     972
     973 -    def Decider(self, function):
     974          SCons.Util.AddMethod(self, function, 'changed_since_last_build')
     975
     976 -    def changed(self, node=None):
     977          """
     978          Returns if the node is up-to-date with respect to the BuildInfo
     979          stored last time it was built.  The default behavior is to compare
     980          it against our own previously stored BuildInfo, but the stored
     981          BuildInfo from another Node (typically one in a Repository)
     982          can be used instead.
     983
     984          Note that we now *always* check every dependency.  We used to
     985          short-circuit the check by returning as soon as we detected
     986          any difference, but we now rely on checking every dependency
     987          to make sure that any necessary Node information (for example,
     988          the content signature of an #included .h file) is updated.
     989          """
     990          t = 0
     991          if t: Trace('changed(%s [%s], %s)' % (self, classname(self), node))
     992          if node is None:
     993              node = self
     994
     995          result = False
     996
     997          bi = node.get_stored_info().binfo
     998          then = bi.bsourcesigs + bi.bdependsigs + bi.bimplicitsigs
     999          children = self.children()
    1000
    1001          diff = len(children) - len(then)
    1002          if diff:
    1003              # The old and new dependency lists are different lengths.
    1004              # This always indicates that the Node must be rebuilt.
    1005              # We also extend the old dependency list with enough None
    1006              # entries to equal the new dependency list, for the benefit
    1007              # of the loop below that updates node information.
    1008              then.extend([None] * diff)
    1009              if t: Trace(': old %s new %s' % (len(then), len(children)))
    1010              result = True
    1011
    1012          for child, prev_ni in zip(children, then):
    1013              if child.changed_since_last_build(self, prev_ni):
    1014                  if t: Trace(': %s changed' % child)
    1015                  result = True
    1016
    1017          contents = self.get_executor().get_contents()
    1018          if self.has_builder():
    1019              import SCons.Util
    1020              newsig = SCons.Util.MD5signature(contents)
    1021              if bi.bactsig != newsig:
    1022                  if t: Trace(': bactsig %s != newsig %s' % (bi.bactsig, newsig))
    1023                  result = True
    1024
    1025          if not result:
    1026              if t: Trace(': up to date')
    1027
    1028          if t: Trace('\n')
    1029
    1030          return result
    1031
    1032 -    def is_up_to_date(self):
    1033          """Default check for whether the Node is current: unknown Node
    1034          subtypes are always out of date, so they will always get built."""
    1035          return None
    1036
    1037 -    def children_are_up_to_date(self):
    1038          """Alternate check for whether the Node is current:  If all of
    1039          our children were up-to-date, then this Node was up-to-date, too.
    1040
    1041          The SCons.Node.Alias and SCons.Node.Python.Value subclasses
    1042          rebind their current() method to this method."""
    1043          # Allow the children to calculate their signatures.
    1044          self.binfo = self.get_binfo()
    1045          if self.always_build:
    1046              return None
    1047          state = 0
    1048          for kid in self.children(None):
    1049              s = kid.get_state()
    1050              if s and (not state or s > state):
    1051                  state = s
    1052          return (state == 0 or state == SCons.Node.up_to_date)
    1053
    1054 -    def is_literal(self):
    1055          """Always pass the string representation of a Node to
    1056          the command interpreter literally."""
    1057          return 1
    1058
    1059 -    def render_include_tree(self):
    1060          """
    1061          Return a text representation, suitable for displaying to the
    1062          user, of the include tree for the sources of this node.
    1063          """
    1064          if self.is_derived() and self.env:
    1065              env = self.get_build_env()
    1066              for s in self.sources:
    1067                  scanner = self.get_source_scanner(s)
    1068                  path = self.get_build_scanner_path(scanner)
    1069                  def f(node, env=env, scanner=scanner, path=path):
    1070                      return node.get_found_includes(env, scanner, path)
    1071                  return SCons.Util.render_tree(s, f, 1)
    1072          else:
    1073              return None
    1074
    1075 -    def get_abspath(self):
    1076          """
    1077          Return an absolute path to the Node.  This will return simply
    1078          str(Node) by default, but for Node types that have a concept of
    1079          relative path, this might return something different.
    1080          """
    1081          return str(self)
    1082
    1083 -    def for_signature(self):
    1084          """
    1085          Return a string representation of the Node that will always
    1086          be the same for this particular Node, no matter what.  This
    1087          is by contrast to the __str__() method, which might, for
    1088          instance, return a relative path for a file Node.  The purpose
    1089          of this method is to generate a value to be used in signature
    1090          calculation for the command line used to build a target, and
    1091          we use this method instead of str() to avoid unnecessary
    1092          rebuilds.  This method does not need to return something that
    1093          would actually work in a command line; it can return any kind of
    1094          nonsense, so long as it does not change.
    1095          """
    1096          return str(self)
    1097
    1098 -    def get_string(self, for_signature):
    1099          """This is a convenience function designed primarily to be
    1100          used in command generators (i.e., CommandGeneratorActions or
    1101          Environment variables that are callable), which are called
    1102          with a for_signature argument that is nonzero if the command
    1103          generator is being called to generate a signature for the
    1104          command line, which determines if we should rebuild or not.
    1105
    1106          Such command generators should use this method in preference
    1107          to str(Node) when converting a Node to a string, passing
    1108          in the for_signature parameter, such that we will call
    1109          Node.for_signature() or str(Node) properly, depending on whether
    1110          we are calculating a signature or actually constructing a
    1111          command line."""
    1112          if for_signature:
    1113              return self.for_signature()
    1114          return str(self)
    1115
    1116 -    def get_subst_proxy(self):
    1117          """
    1118          This method is expected to return an object that will function
    1119          exactly like this Node, except that it implements any additional
    1120          special features that we would like to be in effect for
    1121          Environment variable substitution.  The principle use is that
    1122          some Nodes would like to implement a __getattr__() method,
    1123          but putting that in the Node type itself has a tendency to kill
    1124          performance.  We instead put it in a proxy and return it from
    1125          this method.  It is legal for this method to return self
    1126          if no new functionality is needed for Environment substitution.
    1127          """
    1128          return self
    1129
    1130 -    def explain(self):
    1131          if not self.exists():
    1132              return "building `%s' because it doesn't exist\n" % self
    1133
    1134          if self.always_build:
    1135              return "rebuilding `%s' because AlwaysBuild() is specified\n" % self
    1136
    1137          old = self.get_stored_info()
    1138          if old is None:
    1139              return None
    1140
    1141          old = old.binfo
    1142          old.prepare_dependencies()
    1143
    1144          try:
    1145              old_bkids    = old.bsources    + old.bdepends    + old.bimplicit
    1146              old_bkidsigs = old.bsourcesigs + old.bdependsigs + old.bimplicitsigs
    1147          except AttributeError:
    1148              return "Cannot explain why `%s' is being rebuilt: No previous build information found\n" % self
    1149
    1150          new = self.get_binfo()
    1151
    1152          new_bkids    = new.bsources    + new.bdepends    + new.bimplicit
    1153          new_bkidsigs = new.bsourcesigs + new.bdependsigs + new.bimplicitsigs
    1154
    1155          osig = dict(zip(old_bkids, old_bkidsigs))
    1156          nsig = dict(zip(new_bkids, new_bkidsigs))
    1157
    1158          # The sources and dependencies we'll want to report are all stored
    1159          # as relative paths to this target's directory, but we want to
    1160          # report them relative to the top-level SConstruct directory,
    1161          # so we only print them after running them through this lambda
    1162          # to turn them into the right relative Node and then return
    1163          # its string.
    1164          def stringify( s, E=self.dir.Entry ) :
    1165              if hasattr( s, 'dir' ) :
    1166                  return str(E(s))
    1167              return str(s)
    1168
    1169          lines = []
    1170
    1171          removed = filter(lambda x, nk=new_bkids: not x in nk, old_bkids)
    1172          if removed:
    1173              removed = map(stringify, removed)
    1174              fmt = "`%s' is no longer a dependency\n"
    1175              lines.extend(map(lambda s, fmt=fmt: fmt % s, removed))
    1176
    1177          for k in new_bkids:
    1178              if not k in old_bkids:
    1179                  lines.append("`%s' is a new dependency\n" % stringify(k))
    1180              elif k.changed_since_last_build(self, osig[k]):
    1181                  lines.append("`%s' changed\n" % stringify(k))
    1182
    1183          if len(lines) == 0 and old_bkids != new_bkids:
    1184              lines.append("the dependency order changed:\n" +
    1185                           "%sold: %s\n" % (' '*15, map(stringify, old_bkids)) +
    1186                           "%snew: %s\n" % (' '*15, map(stringify, new_bkids)))
    1187
    1188          if len(lines) == 0:
    1189              def fmt_with_title(title, strlines):
    1190                  lines = string.split(strlines, '\n')
    1191                  sep = '\n' + ' '*(15 + len(title))
    1192                  return ' '*15 + title + string.join(lines, sep) + '\n'
    1193              if old.bactsig != new.bactsig:
    1194                  if old.bact == new.bact:
    1195                      lines.append("the contents of the build action changed\n" +
    1196                                   fmt_with_title('action: ', new.bact))
    1197                  else:
    1198                      lines.append("the build action changed:\n" +
    1199                                   fmt_with_title('old: ', old.bact) +
    1200                                   fmt_with_title('new: ', new.bact))
    1201
    1202          if len(lines) == 0:
    1203              return "rebuilding `%s' for unknown reasons\n" % self
    1204
    1205          preamble = "rebuilding `%s' because" % self
    1206          if len(lines) == 1:
    1207              return "%s %s"  % (preamble, lines[0])
    1208          else:
    1209              lines = ["%s:\n" % preamble] + lines
    1210              return string.join(lines, ' '*11)
    1211
    1212  try:
    1213      [].extend(UserList.UserList([]))
    1214  except TypeError:
    1215      # Python 1.5.2 doesn't allow a list to be extended by list-like
    1216      # objects (such as UserList instances), so just punt and use
    1217      # real lists.
    1218 -    def NodeList(l):
    1219          return l
    1220  else:
    1221 -    class NodeList(UserList.UserList):
    1222 -        def __str__(self):
    1223              return str(map(str, self.data))
    1224
    1225 -def get_children(node, parent): return node.children()
    1226 -def ignore_cycle(node, stack): pass
    1227 -def do_nothing(node, parent): pass
    1228
    1229 -class Walker:
    1230      """An iterator for walking a Node tree.
    1231
    1232      This is depth-first, children are visited before the parent.
    1233      The Walker object can be initialized with any node, and
    1234      returns the next node on the descent with each next() call.
    1235      'kids_func' is an optional function that will be called to
    1236      get the children of a node instead of calling 'children'.
    1237      'cycle_func' is an optional function that will be called
    1238      when a cycle is detected.
    1239
    1240      This class does not get caught in node cycles caused, for example,
    1241      by C header file include loops.
    1242      """
    1243 -    def __init__(self, node, kids_func=get_children,
    1244                               cycle_func=ignore_cycle,
    1245                               eval_func=do_nothing):
    1246          self.kids_func = kids_func
    1247          self.cycle_func = cycle_func
    1248          self.eval_func = eval_func
    1249          node.wkids = copy.copy(kids_func(node, None))
    1250          self.stack = [node]
    1251          self.history = {} # used to efficiently detect and avoid cycles
    1252          self.history[node] = None
    1253
    1254 -    def next(self):
    1255          """Return the next node for this walk of the tree.
    1256
    1257          This function is intentionally iterative, not recursive,
    1258          to sidestep any issues of stack size limitations.
    1259          """
    1260
    1261          while self.stack:
    1262              if self.stack[-1].wkids:
    1263                  node = self.stack[-1].wkids.pop(0)
    1264                  if not self.stack[-1].wkids:
    1265                      self.stack[-1].wkids = None
    1266                  if self.history.has_key(node):
    1267                      self.cycle_func(node, self.stack)
    1268                  else:
    1269                      node.wkids = copy.copy(self.kids_func(node, self.stack[-1]))
    1270                      self.stack.append(node)
    1271                      self.history[node] = None
    1272              else:
    1273                  node = self.stack.pop()
    1274                  del self.history[node]
    1275                  if node:
    1276                      if self.stack:
    1277                          parent = self.stack[-1]
    1278                      else:
    1279                          parent = None
    1280                      self.eval_func(node, parent)
    1281                  return node
    1282          return None
    1283
    1284 -    def is_done(self):
    1285          return not self.stack
    1286
    1287
    1288  arg2nodes_lookups = []
    1289