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