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