__init__.py
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:46k
源码类别:

外挂编程

开发平台:

Windows_Unix

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