Fix use of timestamps with --implicit-cache. (Anthony Roach)
[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
51 from SCons.Debug import logInstanceCreation
52 import SCons.Sig
53 import SCons.Util
54
55 # Node states
56 #
57 # These are in "priority" order, so that the maximum value for any
58 # child/dependency of a node represents the state of that node if
59 # it has no builder of its own.  The canonical example is a file
60 # system directory, which is only up to date if all of its children
61 # were up to date.
62 pending = 1
63 executing = 2
64 up_to_date = 3
65 executed = 4
66 failed = 5
67 stack = 6 # nodes that are in the current Taskmaster execution stack
68
69 # controls whether implicit depedencies are cached:
70 implicit_cache = 0
71
72 # controls whether implicit dep changes are ignored:
73 implicit_deps_unchanged = 0
74
75 # controls whether the cached implicit deps are ignored:
76 implicit_deps_changed = 0
77
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
82 Annotate = do_nothing
83
84 class Node:
85     """The base Node class, for entities that we know how to
86     build, or use to build other Nodes.
87     """
88
89     class Attrs:
90         pass
91
92     def __init__(self):
93         if __debug__: logInstanceCreation(self, 'Node')
94         # Note that we no longer explicitly initialize a self.builder
95         # attribute to None here.  That's because the self.builder
96         # attribute may be created on-the-fly later by a subclass (the
97         # canonical example being a builder to fetch a file from a
98         # source code system like CVS or Subversion).
99
100         # Each list of children that we maintain is accompanied by a
101         # dictionary used to look up quickly whether a node is already
102         # present in the list.  Empirical tests showed that it was
103         # fastest to maintain them as side-by-side Node attributes in
104         # this way, instead of wrapping up each list+dictionary pair in
105         # a class.  (Of course, we could always still do that in the
106         # future if we had a good reason to...).
107         self.sources = []       # source files used to build node
108         self.sources_dict = {}
109         self.depends = []       # explicit dependencies (from Depends)
110         self.depends_dict = {}
111         self.ignore = []        # dependencies to ignore
112         self.ignore_dict = {}
113         self.implicit = None    # implicit (scanned) dependencies (None means not scanned yet)
114         self.parents = {}
115         self.wkids = None       # Kids yet to walk, when it's an array
116         self.target_scanner = None      # explicit scanner from this node's Builder
117         self.source_scanner = None      # source scanner
118
119         self.env = None
120         self.state = None
121         self.precious = None
122         self.always_build = None
123         self.found_includes = {}
124         self.includes = None
125         self.overrides = {}     # construction variable overrides for building this node
126         self.attributes = self.Attrs() # Generic place to stick information about the Node.
127         self.side_effect = 0 # true iff this node is a side effect
128         self.side_effects = [] # the side effects of building this target
129         self.pre_actions = []
130         self.post_actions = []
131         self.linked = 0 # is this node linked to the build directory? 
132
133         # Let the interface in which the build engine is embedded
134         # annotate this Node with its own info (like a description of
135         # what line in what file created the node, for example).
136         Annotate(self)
137
138     def get_suffix(self):
139         return ''
140
141     def generate_build_dict(self):
142         """Return an appropriate dictionary of values for building
143         this Node."""
144         return {}
145
146     def get_build_env(self):
147         """Fetch the appropriate Environment to build this node."""
148         executor = self.get_executor()
149         return executor.get_build_env()
150
151     def set_executor(self, executor):
152         """Set the action executor for this node."""
153         self.executor = executor
154
155     def get_executor(self, create=1):
156         """Fetch the action executor for this node.  Create one if
157         there isn't already one, and requested to do so."""
158         try:
159             executor = self.executor
160         except AttributeError:
161             if not create:
162                 raise
163             import SCons.Executor
164             executor = SCons.Executor.Executor(self.builder,
165                                                self.builder.env,
166                                                {},
167                                                [self],
168                                                self.sources)
169             self.executor = executor
170         return executor
171
172     def _for_each_action(self, func):
173         """Call a function for each action required to build a node.
174
175         The purpose here is to have one place for the logic that
176         collects and executes all of the actions for a node's builder,
177         even though multiple sections of code elsewhere need this logic
178         to do different things."""
179         if not self.has_builder():
180             return
181         executor = self.get_executor()
182         executor(self, func)
183
184     def retrieve_from_cache(self):
185         """Try to retrieve the node's content from a cache
186
187         This method is called from multiple threads in a parallel build,
188         so only do thread safe stuff here. Do thread unsafe stuff in
189         built().
190
191         Returns true iff the node was successfully retrieved.
192         """
193         return 0
194         
195     def build(self):
196         """Actually build the node.
197
198         This method is called from multiple threads in a parallel build,
199         so only do thread safe stuff here. Do thread unsafe stuff in
200         built().
201         """
202         def do_action(action, targets, sources, env, s=self):
203             stat = action(targets, sources, env)
204             if stat:
205                 raise SCons.Errors.BuildError(node = s,
206                                               errstr = "Error %d" % stat)
207         self._for_each_action(do_action)
208
209     def built(self):
210         """Called just after this node is sucessfully built."""
211         self.store_binfo()
212
213         # Clear out the implicit dependency caches:
214         # XXX this really should somehow be made more general and put
215         #     under the control of the scanners.
216         if self.source_scanner:
217             self.found_includes = {}
218             self.includes = None
219
220             def get_parents(node, parent): return node.get_parents()
221             def clear_cache(node, parent):
222                 node.implicit = None
223                 node.del_binfo()
224             w = Walker(self, get_parents, ignore_cycle, clear_cache)
225             while w.next(): pass
226
227         # clear out the content signature, since the contents of this
228         # node were presumably just changed:
229         self.del_csig()
230
231     def postprocess(self):
232         """Clean up anything we don't need to hang onto after we've
233         been built."""
234         try:
235             executor = self.get_executor(create=None)
236         except AttributeError:
237             pass
238         else:
239             executor.cleanup()
240
241     def clear(self):
242         """Completely clear a Node of all its cached state (so that it
243         can be re-evaluated by interfaces that do continuous integration
244         builds).
245         """
246         self.set_state(None)
247         self.del_binfo()
248         self.del_csig()
249         try:
250             delattr(self, '_calculated_sig')
251         except AttributeError:
252             pass
253         try:
254             delattr(self, '_tempbsig')
255         except AttributeError:
256             pass
257         self.includes = None
258         self.found_includes = {}
259         self.implicit = None
260
261     def visited(self):
262         """Called just after this node has been visited
263         without requiring a build.."""
264         pass
265
266     def depends_on(self, nodes):
267         """Does this node depend on any of 'nodes'?"""
268         for node in nodes:
269             if node in self.children():
270                 return 1
271
272         return 0
273
274     def builder_set(self, builder):
275         self.builder = builder
276
277     def has_builder(self):
278         """Return whether this Node has a builder or not.
279
280         In Boolean tests, this turns out to be a *lot* more efficient
281         than simply examining the builder attribute directly ("if
282         node.builder: ..."). When the builder attribute is examined
283         directly, it ends up calling __getattr__ for both the __len__
284         and __nonzero__ attributes on instances of our Builder Proxy
285         class(es), generating a bazillion extra calls and slowing
286         things down immensely.
287         """
288         try:
289             b = self.builder
290         except AttributeError:
291             # There was no explicit builder for this Node, so initialize
292             # the self.builder attribute to None now.
293             self.builder = None
294             b = self.builder
295         return not b is None
296
297     def is_derived(self):
298         """
299         Returns true iff this node is derived (i.e. built).
300
301         This should return true only for nodes whose path should be in
302         the build directory when duplicate=0 and should contribute their build
303         signatures when they are used as source files to other derived files. For
304         example: source with source builders are not derived in this sense,
305         and hence should not return true.
306         """
307         return self.has_builder() or self.side_effect
308
309     def is_pseudo_derived(self):
310         """
311         Returns true iff this node is built, but should use a source path
312         when duplicate=0 and should contribute a content signature (i.e.
313         source signature) when used as a source for other derived files.
314         """
315         return 0
316
317     def alter_targets(self):
318         """Return a list of alternate targets for this Node.
319         """
320         return [], None
321
322     def get_found_includes(self, env, scanner, target):
323         """Return the scanned include lines (implicit dependencies)
324         found in this node.
325
326         The default is no implicit dependencies.  We expect this method
327         to be overridden by any subclass that can be scanned for
328         implicit dependencies.
329         """
330         return []
331
332     def get_implicit_deps(self, env, scanner, target):
333         """Return a list of implicit dependencies for this node.
334
335         This method exists to handle recursive invocation of the scanner
336         on the implicit dependencies returned by the scanner, if the
337         scanner's recursive flag says that we should.
338         """
339         if not scanner:
340             return []
341
342         try:
343             recurse = scanner.recursive
344         except AttributeError:
345             recurse = None
346
347         nodes = [self]
348         seen = {}
349         seen[self] = 1
350         deps = []
351         while nodes:
352            n = nodes.pop(0)
353            d = filter(lambda x, seen=seen: not seen.has_key(x),
354                       n.get_found_includes(env, scanner, target))
355            if d:
356                deps.extend(d)
357                for n in d:
358                    seen[n] = 1
359                if recurse:
360                    nodes.extend(d)
361
362         return deps
363
364     # cache used to make implicit_factory fast.
365     implicit_factory_cache = {}
366     
367     def implicit_factory(self, path):
368         """
369         Turn a cache implicit dependency path into a node.
370         This is called so many times that doing caching
371         here is a significant perforamnce boost.
372         """
373         try:
374             return self.implicit_factory_cache[path]
375         except KeyError:
376             n = self.builder.source_factory(path)
377             self.implicit_factory_cache[path] = n
378             return n
379
380     def scan(self):
381         """Scan this node's dependents for implicit dependencies."""
382         # Don't bother scanning non-derived files, because we don't
383         # care what their dependencies are.
384         # Don't scan again, if we already have scanned.
385         if not self.implicit is None:
386             return
387         self.implicit = []
388         self.implicit_dict = {}
389         self._children_reset()
390         if not self.has_builder():
391             return
392
393         build_env = self.get_build_env()
394
395         if implicit_cache and not implicit_deps_changed:
396             implicit = self.get_stored_implicit()
397             if implicit is not None:
398                 implicit = map(self.implicit_factory, implicit)
399                 self._add_child(self.implicit, self.implicit_dict, implicit)
400                 calc = build_env.get_calculator()
401                 if implicit_deps_unchanged or calc.current(self, calc.bsig(self)):
402                     return
403                 else:
404                     # one of this node's sources has changed, so
405                     # we need to recalculate the implicit deps,
406                     # and the bsig:
407                     self.implicit = []
408                     self.implicit_dict = {}
409                     self._children_reset()
410                     self.del_binfo()
411
412         for child in self.children(scan=0):
413             scanner = child.source_scanner
414             if scanner:
415                 self._add_child(self.implicit,
416                                 self.implicit_dict,
417                                 child.get_implicit_deps(build_env,
418                                                         scanner,
419                                                         self))
420
421         # scan this node itself for implicit dependencies
422         self._add_child(self.implicit,
423                         self.implicit_dict,
424                         self.get_implicit_deps(build_env,
425                                                self.target_scanner,
426                                                self))
427
428         if implicit_cache:
429             self.store_implicit()
430
431     def scanner_key(self):
432         return None
433
434     def env_set(self, env, safe=0):
435         if safe and self.env:
436             return
437         self.env = env
438
439     def calculator(self):
440         import SCons.Defaults
441         
442         env = self.env or SCons.Defaults.DefaultEnvironment()
443         return env.get_calculator()
444
445     def calc_signature(self, calc):
446         """
447         Select and calculate the appropriate build signature for a node.
448
449         self - the node
450         calc - the signature calculation module
451         returns - the signature
452         """
453         try:
454             return self._calculated_sig
455         except AttributeError:
456             if self.is_derived():
457                 import SCons.Defaults
458                 
459                 env = self.env or SCons.Defaults.DefaultEnvironment()
460                 if env.use_build_signature():
461                     sig = self.rfile().calc_bsig(calc, self)
462                 else:
463                     sig = self.rfile().calc_csig(calc, self)
464             elif not self.rexists():
465                 sig = None
466             else:
467                 sig = self.rfile().calc_csig(calc, self)
468             self._calculated_sig = sig
469             return sig
470
471     def calc_bsig(self, calc, cache=None):
472         """Return the node's build signature, calculating it first
473         if necessary.
474
475         Note that we don't save it in the "real" build signature
476         attribute if we have to calculate it here; the "real" build
477         signature only gets updated after a file is actually built.
478         """
479         if cache is None: cache = self
480         try:
481             return cache.bsig
482         except AttributeError:
483             try:
484                 return cache._tempbsig
485             except AttributeError:
486                 cache._tempbsig = calc.bsig(self, cache)
487                 return cache._tempbsig
488
489     def get_bsig(self):
490         """Get the node's build signature (based on the signatures
491         of its dependency files and build information)."""
492         try:
493             return self.bsig
494         except AttributeError:
495             return None
496
497     def set_bsig(self, bsig):
498         """Set the node's build signature (based on the signatures
499         of its dependency files and build information)."""
500         self.bsig = bsig
501
502     def get_binfo(self):
503         """Get the node's build signature (based on the signatures
504         of its dependency files and build information)."""
505         result = []
506         for attr in ['bsig', 'bkids', 'bkidsigs', 'bact', 'bactsig']:
507             try:
508                 r = getattr(self, attr)
509             except AttributeError:
510                 r = None
511             result.append(r)
512         return tuple(result)
513
514     def set_binfo(self, bsig, bkids, bkidsigs, bact, bactsig):
515         """Set the node's build signature (based on the signatures
516         of its dependency files and build information)."""
517         self.bsig = bsig
518         self.bkids = bkids
519         self.bkidsigs = bkidsigs
520         self.bact = bact
521         self.bactsig = bactsig
522         try:
523             delattr(self, '_tempbsig')
524         except AttributeError:
525             pass
526
527     def store_binfo(self):
528         """Make the build signature permanent (that is, store it in the
529         .sconsign file or equivalent)."""
530         pass
531
532     def get_stored_binfo(self):
533         return (None, None, None, None, None)
534
535     def del_binfo(self):
536         """Delete the bsig from this node."""
537         for attr in ['bsig', 'bkids', 'bkidsigs', 'bact', 'bactsig']:
538             try:
539                 delattr(self, attr)
540             except AttributeError:
541                 pass
542
543     def get_csig(self):
544         """Get the signature of the node's content."""
545         try:
546             return self.csig
547         except AttributeError:
548             return None
549
550     def calc_csig(self, calc, cache=None):
551         """Return the node's content signature, calculating it first
552         if necessary.
553         """
554         if cache is None: cache = self
555         try:
556             return cache.csig
557         except AttributeError:
558             cache.csig = calc.csig(self, cache)
559             return cache.csig
560
561     def set_csig(self, csig):
562         """Set the signature of the node's content."""
563         self.csig = csig
564
565     def store_csig(self):
566         """Make the content signature permanent (that is, store it in the
567         .sconsign file or equivalent)."""
568         pass
569
570     def del_csig(self):
571         """Delete the csig from this node."""
572         try:
573             delattr(self, 'csig')
574         except AttributeError:
575             pass
576
577     def get_prevsiginfo(self):
578         """Fetch the previous signature information from the
579         .sconsign entry."""
580         return SCons.Sig._SConsign.null_siginfo
581
582     def get_timestamp(self):
583         return 0
584
585     def store_timestamp(self):
586         """Make the timestamp permanent (that is, store it in the
587         .sconsign file or equivalent)."""
588         pass
589
590     def store_implicit(self):
591         """Make the implicit deps permanent (that is, store them in the
592         .sconsign file or equivalent)."""
593         pass
594
595     def get_stored_implicit(self):
596         """Fetch the stored implicit dependencies"""
597         return None
598
599     def set_precious(self, precious = 1):
600         """Set the Node's precious value."""
601         self.precious = precious
602
603     def set_always_build(self, always_build = 1):
604         """Set the Node's always_build value."""
605         self.always_build = always_build
606
607     def exists(self):
608         """Does this node exists?"""
609         # All node exist by default:
610         return 1
611     
612     def rexists(self):
613         """Does this node exist locally or in a repositiory?"""
614         # There are no repositories by default:
615         return self.exists()
616     
617     def prepare(self):
618         """Prepare for this Node to be created.
619         The default implemenation checks that all children either exist
620         or are derived.
621         """
622         def missing(node):
623             return not node.is_derived() and \
624                    not node.is_pseudo_derived() and \
625                    not node.linked and \
626                    not node.rexists()
627         missing_sources = filter(missing, self.children())
628         if missing_sources:
629             desc = "Source `%s' not found, needed by target `%s'." % (missing_sources[0], self)
630             raise SCons.Errors.StopError, desc
631
632     def remove(self):
633         """Remove this Node:  no-op by default."""
634         return None
635
636     def add_dependency(self, depend):
637         """Adds dependencies."""
638         try:
639             self._add_child(self.depends, self.depends_dict, depend)
640         except TypeError, e:
641             e = e.args[0]
642             if SCons.Util.is_List(e):
643                 s = map(str, e)
644             else:
645                 s = str(e)
646             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)))
647
648     def add_ignore(self, depend):
649         """Adds dependencies to ignore."""
650         try:
651             self._add_child(self.ignore, self.ignore_dict, depend)
652         except TypeError, e:
653             e = e.args[0]
654             if SCons.Util.is_List(e):
655                 s = map(str, e)
656             else:
657                 s = str(e)
658             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)))
659
660     def add_source(self, source):
661         """Adds sources."""
662         try:
663             self._add_child(self.sources, self.sources_dict, source)
664         except TypeError, e:
665             e = e.args[0]
666             if SCons.Util.is_List(e):
667                 s = map(str, e)
668             else:
669                 s = str(e)
670             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)))
671
672     def _add_child(self, collection, dict, child):
673         """Adds 'child' to 'collection', first checking 'dict' to see
674         if it's already present."""
675         if type(child) is not type([]):
676             child = [child]
677         for c in child:
678             if not isinstance(c, Node):
679                 raise TypeError, c
680         added = None
681         for c in child:
682             if not dict.has_key(c):
683                 collection.append(c)
684                 dict[c] = 1
685                 added = 1
686             c.parents[self] = 1
687         if added:
688             self._children_reset()
689
690     def add_wkid(self, wkid):
691         """Add a node to the list of kids waiting to be evaluated"""
692         if self.wkids != None:
693             self.wkids.append(wkid)
694
695     def _children_reset(self):
696         try:
697             delattr(self, '_children')
698         except AttributeError:
699             pass
700
701     def children(self, scan=1):
702         """Return a list of the node's direct children, minus those
703         that are ignored by this node."""
704         if scan:
705             self.scan()
706         try:
707             return self._children
708         except AttributeError:
709             c = filter(lambda x, i=self.ignore: x not in i,
710                               self.all_children(scan=0))
711             self._children = c
712             return c
713
714     def all_children(self, scan=1):
715         """Return a list of all the node's direct children."""
716         # The return list may contain duplicate Nodes, especially in
717         # source trees where there are a lot of repeated #includes
718         # of a tangle of .h files.  Profiling shows, however, that
719         # eliminating the duplicates with a brute-force approach that
720         # preserves the order (that is, something like:
721         #
722         #       u = []
723         #       for n in list:
724         #           if n not in u:
725         #               u.append(n)"
726         #
727         # takes more cycles than just letting the underlying methods
728         # hand back cached values if a Node's information is requested
729         # multiple times.  (Other methods of removing duplicates, like
730         # using dictionary keys, lose the order, and the only ordered
731         # dictionary patterns I found all ended up using "not in"
732         # internally anyway...)
733         if scan:
734             self.scan()
735         if self.implicit is None:
736             return self.sources + self.depends
737         else:
738             return self.sources + self.depends + self.implicit
739
740     def get_parents(self):
741         return self.parents.keys()
742
743     def set_state(self, state):
744         self.state = state
745
746     def get_state(self):
747         return self.state
748
749     def current(self, calc=None):
750         return None
751
752     def rfile(self):
753         return self
754
755     def rstr(self):
756         return str(self)
757
758     def is_literal(self):
759         """Always pass the string representation of a Node to
760         the command interpreter literally."""
761         return 1
762
763     def add_pre_action(self, act):
764         """Adds an Action performed on this Node only before
765         building it."""
766         self.pre_actions.append(act)
767
768     def add_post_action(self, act):
769         """Adds and Action performed on this Node only after
770         building it."""
771         self.post_actions.append(act)
772
773     def render_include_tree(self):
774         """
775         Return a text representation, suitable for displaying to the
776         user, of the include tree for the sources of this node.
777         """
778         if self.is_derived() and self.env:
779             env = self.get_build_env()
780             for s in self.sources:
781                 def f(node, env=env, scanner=s.source_scanner, target=self):
782                     return node.get_found_includes(env, scanner, target)
783                 return SCons.Util.render_tree(s, f, 1)
784         else:
785             return None
786
787     def get_abspath(self):
788         """
789         Return an absolute path to the Node.  This will return simply
790         str(Node) by default, but for Node types that have a concept of
791         relative path, this might return something different.
792         """
793         return str(self)
794
795     def for_signature(self):
796         """
797         Return a string representation of the Node that will always
798         be the same for this particular Node, no matter what.  This
799         is by contrast to the __str__() method, which might, for
800         instance, return a relative path for a file Node.  The purpose
801         of this method is to generate a value to be used in signature
802         calculation for the command line used to build a target, and
803         we use this method instead of str() to avoid unnecessary
804         rebuilds.  This method does not need to return something that
805         would actually work in a command line; it can return any kind of
806         nonsense, so long as it does not change.
807         """
808         return str(self)
809
810     def get_string(self, for_signature):
811         """This is a convenience function designed primarily to be
812         used in command generators (i.e., CommandGeneratorActions or
813         Environment variables that are callable), which are called
814         with a for_signature argument that is nonzero if the command
815         generator is being called to generate a signature for the
816         command line, which determines if we should rebuild or not.
817
818         Such command generators shoud use this method in preference
819         to str(Node) when converting a Node to a string, passing
820         in the for_signature parameter, such that we will call
821         Node.for_signature() or str(Node) properly, depending on whether
822         we are calculating a signature or actually constructing a
823         command line."""
824         if for_signature:
825             return self.for_signature()
826         return str(self)
827
828     def get_subst_proxy(self):
829         """
830         This method is expected to return an object that will function
831         exactly like this Node, except that it implements any additional
832         special features that we would like to be in effect for
833         Environment variable substitution.  The principle use is that
834         some Nodes would like to implement a __getattr__() method,
835         but putting that in the Node type itself has a tendency to kill
836         performance.  We instead put it in a proxy and return it from
837         this method.  It is legal for this method to return self
838         if no new functionality is needed for Environment substitution.
839         """
840         return self
841         
842
843 def get_children(node, parent): return node.children()
844 def ignore_cycle(node, stack): pass
845 def do_nothing(node, parent): pass
846
847 class Walker:
848     """An iterator for walking a Node tree.
849
850     This is depth-first, children are visited before the parent.
851     The Walker object can be initialized with any node, and
852     returns the next node on the descent with each next() call.
853     'kids_func' is an optional function that will be called to
854     get the children of a node instead of calling 'children'.
855     'cycle_func' is an optional function that will be called
856     when a cycle is detected.
857
858     This class does not get caught in node cycles caused, for example,
859     by C header file include loops.
860     """
861     def __init__(self, node, kids_func=get_children,
862                              cycle_func=ignore_cycle,
863                              eval_func=do_nothing):
864         self.kids_func = kids_func
865         self.cycle_func = cycle_func
866         self.eval_func = eval_func
867         node.wkids = copy.copy(kids_func(node, None))
868         self.stack = [node]
869         self.history = {} # used to efficiently detect and avoid cycles
870         self.history[node] = None
871
872     def next(self):
873         """Return the next node for this walk of the tree.
874
875         This function is intentionally iterative, not recursive,
876         to sidestep any issues of stack size limitations.
877         """
878
879         while self.stack:
880             if self.stack[-1].wkids:
881                 node = self.stack[-1].wkids.pop(0)
882                 if not self.stack[-1].wkids:
883                     self.stack[-1].wkids = None
884                 if self.history.has_key(node):
885                     self.cycle_func(node, self.stack)
886                 else:
887                     node.wkids = copy.copy(self.kids_func(node, self.stack[-1]))
888                     self.stack.append(node)
889                     self.history[node] = None
890             else:
891                 node = self.stack.pop()
892                 del self.history[node]
893                 if node:
894                     if self.stack:
895                         parent = self.stack[-1]
896                     else:
897                         parent = None
898                     self.eval_func(node, parent)
899                 return node
900
901     def is_done(self):
902         return not self.stack
903
904
905 arg2nodes_lookups = []