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 from __future__ import print_function
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 __revision__ = "src/engine/SCons/Node/__init__.py 74b2c53bc42290e911b334a6b44f187da698a668 2017/11/14 13:16:53 bdbaddog"
47
48 import collections
49 import copy
50 from itertools import chain
51
52 import SCons.Debug
53 from SCons.Debug import logInstanceCreation
54 import SCons.Executor
55 import SCons.Memoize
56 import SCons.Util
57
58 from SCons.Debug import Trace
59
60 from SCons.compat import with_metaclass, NoSlotsPyPy
61
62 print_duplicate = 0
65 return str(obj.__class__).split('.')[-1]
66
67
68
69 do_store_info = True
70
71
72
73
74
75
76
77
78 no_state = 0
79 pending = 1
80 executing = 2
81 up_to_date = 3
82 executed = 4
83 failed = 5
84
85 StateString = {
86 0 : "no_state",
87 1 : "pending",
88 2 : "executing",
89 3 : "up_to_date",
90 4 : "executed",
91 5 : "failed",
92 }
93
94
95 implicit_cache = 0
96
97
98 implicit_deps_unchanged = 0
99
100
101 implicit_deps_changed = 0
106
107 Annotate = do_nothing
108
109
110
111
112 interactive = False
115 raise NotImplementedError
116
118 """
119 Returns true if this node is derived (i.e. built).
120 """
121 return node.has_builder() or node.side_effect
122
123 _is_derived_map = {0 : is_derived_none,
124 1 : is_derived_node}
127 raise NotImplementedError
128
131
133 return node.stat() is not None
134
135 -def exists_entry(node):
136 """Return if the Entry exists. Check the file system to see
137 what we should turn into first. Assume a file if there's no
138 directory."""
139 node.disambiguate()
140 return _exists_map[node._func_exists](node)
141
165
166 _exists_map = {0 : exists_none,
167 1 : exists_always,
168 2 : exists_base,
169 3 : exists_entry,
170 4 : exists_file}
174 raise NotImplementedError
175
178
181
182 _rexists_map = {0 : rexists_none,
183 1 : rexists_node,
184 2 : rexists_base}
185
186 -def get_contents_none(node):
187 raise NotImplementedError
188
190 """Fetch the contents of the entry. Returns the exact binary
191 contents of the file."""
192 try:
193 node = node.disambiguate(must_exist=1)
194 except SCons.Errors.UserError:
195
196
197
198
199
200 return ''
201 else:
202 return _get_contents_map[node._func_get_contents](node)
203
205 """Return content signatures and names of all our children
206 separated by new-lines. Ensure that the nodes are sorted."""
207 contents = []
208 for n in sorted(node.children(), key=lambda t: t.name):
209 contents.append('%s %s\n' % (n.get_csig(), n.name))
210 return ''.join(contents)
211
213 if not node.rexists():
214 return b''
215 fname = node.rfile().get_abspath()
216 try:
217 with open(fname, "rb") as fp:
218 contents = fp.read()
219 except EnvironmentError as e:
220 if not e.filename:
221 e.filename = fname
222 raise
223 return contents
224
225 _get_contents_map = {0 : get_contents_none,
226 1 : get_contents_entry,
227 2 : get_contents_dir,
228 3 : get_contents_file}
231 raise NotImplementedError
232
235
236 _target_from_source_map = {0 : target_from_source_none,
237 1 : target_from_source_base}
253 """
254
255 Must be overridden in a specific subclass to return True if this
256 Node (a dependency) has changed since the last time it was used
257 to build the specified target. prev_ni is this Node's state (for
258 example, its file timestamp, length, maybe content signature)
259 as of the last time the target was built.
260
261 Note that this method is called through the dependency, not the
262 target, because a dependency Node must be able to use its own
263 logic to decide if it changed. For example, File Nodes need to
264 obey if we're configured to use timestamps, but Python Value Nodes
265 never use timestamps and always use the content. If this method
266 were called through the target, then each Node's implementation
267 of this method would have to have more complicated logic to
268 handle all the different Node types on which it might depend.
269 """
270 raise NotImplementedError
271
273 cur_csig = node.get_csig()
274 try:
275 return cur_csig != prev_ni.csig
276 except AttributeError:
277 return 1
278
279 -def changed_since_last_build_entry(node, target, prev_ni):
280 node.disambiguate()
281 return _decider_map[node.changed_since_last_build](node, target, prev_ni)
282
285
287 return target.get_build_env().decide_source(node, target, prev_ni)
288
290 return target.get_build_env().decide_target(node, target, prev_ni)
291
293 cur_csig = node.get_csig()
294 try:
295 return cur_csig != prev_ni.csig
296 except AttributeError:
297 return 1
298
299
300
301
302
303 _decider_map = {0 : changed_since_last_build_node,
304 1 : changed_since_last_build_alias,
305 2 : changed_since_last_build_entry,
306 3 : changed_since_last_build_state_changed,
307 4 : decide_source,
308 5 : decide_target,
309 6 : changed_since_last_build_python}
310
311 do_store_info = True
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 -def store_info_pass(node):
329
337
338
339 store_info_map = {0 : store_info_pass,
340 1 : store_info_file}
345 """
346 The generic base class for signature information for a Node.
347
348 Node subclasses should subclass NodeInfoBase to provide their own
349 logic for dealing with their own Node-specific signature information.
350 """
351 __slots__ = ('__weakref__',)
352 current_version_id = 2
353
355 try:
356 field_list = self.field_list
357 except AttributeError:
358 return
359 for f in field_list:
360 try:
361 delattr(self, f)
362 except AttributeError:
363 pass
364 try:
365 func = getattr(node, 'get_' + f)
366 except AttributeError:
367 pass
368 else:
369 setattr(self, f, func())
370
373
375 """
376 Merge the fields of another object into this object. Already existing
377 information is overwritten by the other instance's data.
378 WARNING: If a '__dict__' slot is added, it should be updated instead of
379 replaced.
380 """
381 state = other.__getstate__()
382 self.__setstate__(state)
405
407 """
408 Return all fields that shall be pickled. Walk the slots in the class
409 hierarchy and add those to the state dictionary. If a '__dict__' slot is
410 available, copy all entries to the dictionary. Also include the version
411 id, which is fixed for all instances of a class.
412 """
413 state = getattr(self, '__dict__', {}).copy()
414 for obj in type(self).mro():
415 for name in getattr(obj,'__slots__',()):
416 if hasattr(self, name):
417 state[name] = getattr(self, name)
418
419 state['_version_id'] = self.current_version_id
420 try:
421 del state['__weakref__']
422 except KeyError:
423 pass
424 return state
425
427 """
428 Restore the attributes from a pickled state. The version is discarded.
429 """
430
431 del state['_version_id']
432
433 for key, value in state.items():
434 if key not in ('__weakref__',):
435 setattr(self, key, value)
436
439 """
440 The generic base class for build information for a Node.
441
442 This is what gets stored in a .sconsign file for each target file.
443 It contains a NodeInfo instance for this node (signature information
444 that's specific to the type of Node) and direct attributes for the
445 generic build stuff we have to track: sources, explicit dependencies,
446 implicit dependencies, and action information.
447 """
448 __slots__ = ("bsourcesigs", "bdependsigs", "bimplicitsigs", "bactsig",
449 "bsources", "bdepends", "bact", "bimplicit", "__weakref__")
450 current_version_id = 2
451
459
461 """
462 Merge the fields of another object into this object. Already existing
463 information is overwritten by the other instance's data.
464 WARNING: If a '__dict__' slot is added, it should be updated instead of
465 replaced.
466 """
467 state = other.__getstate__()
468 self.__setstate__(state)
469
471 """
472 Return all fields that shall be pickled. Walk the slots in the class
473 hierarchy and add those to the state dictionary. If a '__dict__' slot is
474 available, copy all entries to the dictionary. Also include the version
475 id, which is fixed for all instances of a class.
476 """
477 state = getattr(self, '__dict__', {}).copy()
478 for obj in type(self).mro():
479 for name in getattr(obj,'__slots__',()):
480 if hasattr(self, name):
481 state[name] = getattr(self, name)
482
483 state['_version_id'] = self.current_version_id
484 try:
485 del state['__weakref__']
486 except KeyError:
487 pass
488 return state
489
491 """
492 Restore the attributes from a pickled state.
493 """
494
495 del state['_version_id']
496 for key, value in state.items():
497 if key not in ('__weakref__',):
498 setattr(self, key, value)
499
500
501 -class Node(object, with_metaclass(NoSlotsPyPy)):
502 """The base Node class, for entities that we know how to
503 build, or use to build other Nodes.
504 """
505
506 __slots__ = ['sources',
507 'sources_set',
508 '_specific_sources',
509 'depends',
510 'depends_set',
511 'ignore',
512 'ignore_set',
513 'prerequisites',
514 'implicit',
515 'waiting_parents',
516 'waiting_s_e',
517 'ref_count',
518 'wkids',
519 'env',
520 'state',
521 'precious',
522 'noclean',
523 'nocache',
524 'cached',
525 'always_build',
526 'includes',
527 'attributes',
528 'side_effect',
529 'side_effects',
530 'linked',
531 '_memo',
532 'executor',
533 'binfo',
534 'ninfo',
535 'builder',
536 'is_explicit',
537 'implicit_set',
538 'changed_since_last_build',
539 'store_info',
540 'pseudo',
541 '_tags',
542 '_func_is_derived',
543 '_func_exists',
544 '_func_rexists',
545 '_func_get_contents',
546 '_func_target_from_source']
547
549 __slots__ = ('shared', '__dict__')
550
551
609
612
615
616 @SCons.Memoize.CountMethodCall
627
631
635
656
666
668 "Remove cached executor; forces recompute when needed."
669 try:
670 delattr(self, 'executor')
671 except AttributeError:
672 pass
673
675 """Try to push a node into a cache
676 """
677 pass
678
680 """Try to retrieve the node's content from a cache
681
682 This method is called from multiple threads in a parallel build,
683 so only do thread safe stuff here. Do thread unsafe stuff in
684 built().
685
686 Returns true if the node was successfully retrieved.
687 """
688 return 0
689
690
691
692
693
695 """Get a Node ready for evaluation.
696
697 This is called before the Taskmaster decides if the Node is
698 up-to-date or not. Overriding this method allows for a Node
699 subclass to be disambiguated if necessary, or for an implicit
700 source builder to be attached.
701 """
702 pass
703
705 """Prepare for this Node to be built.
706
707 This is called after the Taskmaster has decided that the Node
708 is out-of-date and must be rebuilt, but before actually calling
709 the method to build the Node.
710
711 This default implementation checks that explicit or implicit
712 dependencies either exist or are derived, and initializes the
713 BuildInfo structure that will hold the information about how
714 this node is, uh, built.
715
716 (The existence of source files is checked separately by the
717 Executor, which aggregates checks for all of the targets built
718 by a specific action.)
719
720 Overriding this method allows for for a Node subclass to remove
721 the underlying file from the file system. Note that subclass
722 methods should call this base class method to get the child
723 check and the BuildInfo structure.
724 """
725 if self.depends is not None:
726 for d in self.depends:
727 if d.missing():
728 msg = "Explicit dependency `%s' not found, needed by target `%s'."
729 raise SCons.Errors.StopError(msg % (d, self))
730 if self.implicit is not None:
731 for i in self.implicit:
732 if i.missing():
733 msg = "Implicit dependency `%s' not found, needed by target `%s'."
734 raise SCons.Errors.StopError(msg % (i, self))
735 self.binfo = self.get_binfo()
736
738 """Actually build the node.
739
740 This is called by the Taskmaster after it's decided that the
741 Node is out-of-date and must be rebuilt, and after the prepare()
742 method has gotten everything, uh, prepared.
743
744 This method is called from multiple threads in a parallel build,
745 so only do thread safe stuff here. Do thread unsafe stuff
746 in built().
747
748 """
749 try:
750 self.get_executor()(self, **kw)
751 except SCons.Errors.BuildError as e:
752 e.node = self
753 raise
754
773
786
788 """Called just after this node has been marked
789 up-to-date or was built completely.
790
791 This is where we try to release as many target node infos
792 as possible for clean builds and update runs, in order
793 to minimize the overall memory consumption.
794
795 By purging attributes that aren't needed any longer after
796 a Node (=File) got built, we don't have to care that much how
797 many KBytes a Node actually requires...as long as we free
798 the memory shortly afterwards.
799
800 @see: built() and File.release_target_info()
801 """
802 pass
803
804
805
806
807
810
812 """
813 Returns the number of nodes added to our waiting parents list:
814 1 if we add a unique waiting parent, 0 if not. (Note that the
815 returned values are intended to be used to increment a reference
816 count, so don't think you can "clean up" this function by using
817 True and False instead...)
818 """
819 wp = self.waiting_parents
820 if node in wp:
821 return 0
822 wp.add(node)
823 return 1
824
825 - def postprocess(self):
826 """Clean up anything we don't need to hang onto after we've
827 been built."""
828 self.executor_cleanup()
829 self.waiting_parents = set()
830
832 """Completely clear a Node of all its cached state (so that it
833 can be re-evaluated by interfaces that do continuous integration
834 builds).
835 """
836
837
838
839 self.del_binfo()
840 self.clear_memoized_values()
841 self.ninfo = self.new_ninfo()
842 self.executor_cleanup()
843 try:
844 delattr(self, '_calculated_sig')
845 except AttributeError:
846 pass
847 self.includes = None
848
851
858
860 """Return whether this Node has a builder or not.
861
862 In Boolean tests, this turns out to be a *lot* more efficient
863 than simply examining the builder attribute directly ("if
864 node.builder: ..."). When the builder attribute is examined
865 directly, it ends up calling __getattr__ for both the __len__
866 and __nonzero__ attributes on instances of our Builder Proxy
867 class(es), generating a bazillion extra calls and slowing
868 things down immensely.
869 """
870 try:
871 b = self.builder
872 except AttributeError:
873
874
875 b = self.builder = None
876 return b is not None
877
880
882 """Return whether this Node has an explicit builder
883
884 This allows an internal Builder created by SCons to be marked
885 non-explicit, so that it can be overridden by an explicit
886 builder that the user supplies (the canonical example being
887 directories)."""
888 try:
889 return self.is_explicit
890 except AttributeError:
891 self.is_explicit = None
892 return self.is_explicit
893
895 """Return the set builder, or a specified default value"""
896 try:
897 return self.builder
898 except AttributeError:
899 return default_builder
900
901 multiple_side_effect_has_builder = has_builder
902
904 """
905 Returns true if this node is derived (i.e. built).
906
907 This should return true only for nodes whose path should be in
908 the variant directory when duplicate=0 and should contribute their build
909 signatures when they are used as source files to other derived files. For
910 example: source with source builders are not derived in this sense,
911 and hence should not return true.
912 """
913 return _is_derived_map[self._func_is_derived](self)
914
916 """Return a list of alternate targets for this Node.
917 """
918 return [], None
919
921 """Return the scanned include lines (implicit dependencies)
922 found in this node.
923
924 The default is no implicit dependencies. We expect this method
925 to be overridden by any subclass that can be scanned for
926 implicit dependencies.
927 """
928 return []
929
931 """Return a list of implicit dependencies for this node.
932
933 This method exists to handle recursive invocation of the scanner
934 on the implicit dependencies returned by the scanner, if the
935 scanner's recursive flag says that we should.
936 """
937 nodes = [self]
938 seen = set(nodes)
939 dependencies = []
940 path_memo = {}
941
942 root_node_scanner = self._get_scanner(env, initial_scanner, None, kw)
943
944 while nodes:
945 node = nodes.pop(0)
946
947 scanner = node._get_scanner(env, initial_scanner, root_node_scanner, kw)
948 if not scanner:
949 continue
950
951 try:
952 path = path_memo[scanner]
953 except KeyError:
954 path = path_func(scanner)
955 path_memo[scanner] = path
956
957 included_deps = [x for x in node.get_found_includes(env, scanner, path) if x not in seen]
958 if included_deps:
959 dependencies.extend(included_deps)
960 seen.update(included_deps)
961 nodes.extend(scanner.recurse_nodes(included_deps))
962
963 return dependencies
964
965 - def _get_scanner(self, env, initial_scanner, root_node_scanner, kw):
966 if initial_scanner:
967
968 scanner = initial_scanner.select(self)
969 else:
970
971 scanner = self.get_env_scanner(env, kw)
972 if scanner:
973 scanner = scanner.select(self)
974
975 if not scanner:
976
977
978 scanner = root_node_scanner
979
980 return scanner
981
984
986 return self.builder.target_scanner
987
989 """Fetch the source scanner for the specified node
990
991 NOTE: "self" is the target being built, "node" is
992 the source file for which we want to fetch the scanner.
993
994 Implies self.has_builder() is true; again, expect to only be
995 called from locations where this is already verified.
996
997 This function may be called very often; it attempts to cache
998 the scanner found to improve performance.
999 """
1000 scanner = None
1001 try:
1002 scanner = self.builder.source_scanner
1003 except AttributeError:
1004 pass
1005 if not scanner:
1006
1007
1008
1009 scanner = self.get_env_scanner(self.get_build_env())
1010 if scanner:
1011 scanner = scanner.select(node)
1012 return scanner
1013
1020
1069
1072
1074 """Selects a scanner for this Node.
1075
1076 This is a separate method so it can be overridden by Node
1077 subclasses (specifically, Node.FS.Dir) that *must* use their
1078 own Scanner and don't select one the Scanner.Selector that's
1079 configured for the target.
1080 """
1081 return scanner.select(self)
1082
1084 if safe and self.env:
1085 return
1086 self.env = env
1087
1088
1089
1090
1091
1092 NodeInfo = NodeInfoBase
1093 BuildInfo = BuildInfoBase
1094
1098
1105
1109
1157
1159 """Delete the build info from this node."""
1160 try:
1161 delattr(self, 'binfo')
1162 except AttributeError:
1163 pass
1164
1172
1175
1178
1180 """Fetch the stored implicit dependencies"""
1181 return None
1182
1183
1184
1185
1186
1190
1192 """Set the Node's precious value."""
1193 self.pseudo = pseudo
1194
1196 """Set the Node's noclean value."""
1197
1198
1199 self.noclean = noclean and 1 or 0
1200
1202 """Set the Node's nocache value."""
1203
1204
1205 self.nocache = nocache and 1 or 0
1206
1210
1214
1219
1220 - def get_contents(self):
1221 """Fetch the contents of the entry."""
1222 return _get_contents_map[self._func_get_contents](self)
1223
1228
1230 """Remove this Node: no-op by default."""
1231 return None
1232
1234 """Adds dependencies."""
1235 try:
1236 self._add_child(self.depends, self.depends_set, depend)
1237 except TypeError as e:
1238 e = e.args[0]
1239 if SCons.Util.is_List(e):
1240 s = list(map(str, e))
1241 else:
1242 s = str(e)
1243 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)))
1244
1251
1253 """Adds dependencies to ignore."""
1254 try:
1255 self._add_child(self.ignore, self.ignore_set, depend)
1256 except TypeError as e:
1257 e = e.args[0]
1258 if SCons.Util.is_List(e):
1259 s = list(map(str, e))
1260 else:
1261 s = str(e)
1262 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)))
1263
1265 """Adds sources."""
1266 if self._specific_sources:
1267 return
1268 try:
1269 self._add_child(self.sources, self.sources_set, source)
1270 except TypeError as e:
1271 e = e.args[0]
1272 if SCons.Util.is_List(e):
1273 s = list(map(str, e))
1274 else:
1275 s = str(e)
1276 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)))
1277
1279 """Adds 'child' to 'collection', first checking 'set' to see if it's
1280 already present."""
1281 added = None
1282 for c in child:
1283 if c not in set:
1284 set.add(c)
1285 collection.append(c)
1286 added = 1
1287 if added:
1288 self._children_reset()
1289
1293
1295 """Add a node to the list of kids waiting to be evaluated"""
1296 if self.wkids is not None:
1297 self.wkids.append(wkid)
1298
1304
1305 @SCons.Memoize.CountMethodCall
1341
1343 """Return a list of all the node's direct children."""
1344 if scan:
1345 self.scan()
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364 return list(chain.from_iterable([_f for _f in [self.sources, self.depends, self.implicit] if _f]))
1365
1367 """Return a list of the node's direct children, minus those
1368 that are ignored by this node."""
1369 if scan:
1370 self.scan()
1371 return self._children_get()
1372
1375
1378
1385
1396
1397 - def Tag(self, key, value):
1398 """ Add a user-defined tag. """
1399 if not self._tags:
1400 self._tags = {}
1401 self._tags[key] = value
1402
1404 """ Return a user-defined tag. """
1405 if not self._tags:
1406 return None
1407 return self._tags.get(key, None)
1408
1409 - def changed(self, node=None, allowcache=False):
1410 """
1411 Returns if the node is up-to-date with respect to the BuildInfo
1412 stored last time it was built. The default behavior is to compare
1413 it against our own previously stored BuildInfo, but the stored
1414 BuildInfo from another Node (typically one in a Repository)
1415 can be used instead.
1416
1417 Note that we now *always* check every dependency. We used to
1418 short-circuit the check by returning as soon as we detected
1419 any difference, but we now rely on checking every dependency
1420 to make sure that any necessary Node information (for example,
1421 the content signature of an #included .h file) is updated.
1422
1423 The allowcache option was added for supporting the early
1424 release of the executor/builder structures, right after
1425 a File target was built. When set to true, the return
1426 value of this changed method gets cached for File nodes.
1427 Like this, the executor isn't needed any longer for subsequent
1428 calls to changed().
1429
1430 @see: FS.File.changed(), FS.File.release_target_info()
1431 """
1432 t = 0
1433 if t: Trace('changed(%s [%s], %s)' % (self, classname(self), node))
1434 if node is None:
1435 node = self
1436
1437 result = False
1438
1439 bi = node.get_stored_info().binfo
1440 then = bi.bsourcesigs + bi.bdependsigs + bi.bimplicitsigs
1441 children = self.children()
1442
1443 diff = len(children) - len(then)
1444 if diff:
1445
1446
1447
1448
1449
1450 then.extend([None] * diff)
1451 if t: Trace(': old %s new %s' % (len(then), len(children)))
1452 result = True
1453
1454 for child, prev_ni in zip(children, then):
1455 if _decider_map[child.changed_since_last_build](child, self, prev_ni):
1456 if t: Trace(': %s changed' % child)
1457 result = True
1458
1459 contents = self.get_executor().get_contents()
1460 if self.has_builder():
1461 import SCons.Util
1462 newsig = SCons.Util.MD5signature(contents)
1463 if bi.bactsig != newsig:
1464 if t: Trace(': bactsig %s != newsig %s' % (bi.bactsig, newsig))
1465 result = True
1466
1467 if not result:
1468 if t: Trace(': up to date')
1469
1470 if t: Trace('\n')
1471
1472 return result
1473
1475 """Default check for whether the Node is current: unknown Node
1476 subtypes are always out of date, so they will always get built."""
1477 return None
1478
1480 """Alternate check for whether the Node is current: If all of
1481 our children were up-to-date, then this Node was up-to-date, too.
1482
1483 The SCons.Node.Alias and SCons.Node.Python.Value subclasses
1484 rebind their current() method to this method."""
1485
1486 self.binfo = self.get_binfo()
1487 if self.always_build:
1488 return None
1489 state = 0
1490 for kid in self.children(None):
1491 s = kid.get_state()
1492 if s and (not state or s > state):
1493 state = s
1494 return (state == 0 or state == SCons.Node.up_to_date)
1495
1497 """Always pass the string representation of a Node to
1498 the command interpreter literally."""
1499 return 1
1500
1517 return SCons.Util.render_tree(s, f, 1)
1518 else:
1519 return None
1520
1522 """
1523 Return an absolute path to the Node. This will return simply
1524 str(Node) by default, but for Node types that have a concept of
1525 relative path, this might return something different.
1526 """
1527 return str(self)
1528
1530 """
1531 Return a string representation of the Node that will always
1532 be the same for this particular Node, no matter what. This
1533 is by contrast to the __str__() method, which might, for
1534 instance, return a relative path for a file Node. The purpose
1535 of this method is to generate a value to be used in signature
1536 calculation for the command line used to build a target, and
1537 we use this method instead of str() to avoid unnecessary
1538 rebuilds. This method does not need to return something that
1539 would actually work in a command line; it can return any kind of
1540 nonsense, so long as it does not change.
1541 """
1542 return str(self)
1543
1545 """This is a convenience function designed primarily to be
1546 used in command generators (i.e., CommandGeneratorActions or
1547 Environment variables that are callable), which are called
1548 with a for_signature argument that is nonzero if the command
1549 generator is being called to generate a signature for the
1550 command line, which determines if we should rebuild or not.
1551
1552 Such command generators should use this method in preference
1553 to str(Node) when converting a Node to a string, passing
1554 in the for_signature parameter, such that we will call
1555 Node.for_signature() or str(Node) properly, depending on whether
1556 we are calculating a signature or actually constructing a
1557 command line."""
1558 if for_signature:
1559 return self.for_signature()
1560 return str(self)
1561
1563 """
1564 This method is expected to return an object that will function
1565 exactly like this Node, except that it implements any additional
1566 special features that we would like to be in effect for
1567 Environment variable substitution. The principle use is that
1568 some Nodes would like to implement a __getattr__() method,
1569 but putting that in the Node type itself has a tendency to kill
1570 performance. We instead put it in a proxy and return it from
1571 this method. It is legal for this method to return self
1572 if no new functionality is needed for Environment substitution.
1573 """
1574 return self
1575
1577 if not self.exists():
1578 return "building `%s' because it doesn't exist\n" % self
1579
1580 if self.always_build:
1581 return "rebuilding `%s' because AlwaysBuild() is specified\n" % self
1582
1583 old = self.get_stored_info()
1584 if old is None:
1585 return None
1586
1587 old = old.binfo
1588 old.prepare_dependencies()
1589
1590 try:
1591 old_bkids = old.bsources + old.bdepends + old.bimplicit
1592 old_bkidsigs = old.bsourcesigs + old.bdependsigs + old.bimplicitsigs
1593 except AttributeError:
1594 return "Cannot explain why `%s' is being rebuilt: No previous build information found\n" % self
1595
1596 new = self.get_binfo()
1597
1598 new_bkids = new.bsources + new.bdepends + new.bimplicit
1599 new_bkidsigs = new.bsourcesigs + new.bdependsigs + new.bimplicitsigs
1600
1601 osig = dict(list(zip(old_bkids, old_bkidsigs)))
1602 nsig = dict(list(zip(new_bkids, new_bkidsigs)))
1603
1604
1605
1606
1607
1608
1609
1610 def stringify( s, E=self.dir.Entry ) :
1611 if hasattr( s, 'dir' ) :
1612 return str(E(s))
1613 return str(s)
1614
1615 lines = []
1616
1617 removed = [x for x in old_bkids if not x in new_bkids]
1618 if removed:
1619 removed = list(map(stringify, removed))
1620 fmt = "`%s' is no longer a dependency\n"
1621 lines.extend([fmt % s for s in removed])
1622
1623 for k in new_bkids:
1624 if not k in old_bkids:
1625 lines.append("`%s' is a new dependency\n" % stringify(k))
1626 elif _decider_map[k.changed_since_last_build](k, self, osig[k]):
1627 lines.append("`%s' changed\n" % stringify(k))
1628
1629 if len(lines) == 0 and old_bkids != new_bkids:
1630 lines.append("the dependency order changed:\n" +
1631 "%sold: %s\n" % (' '*15, list(map(stringify, old_bkids))) +
1632 "%snew: %s\n" % (' '*15, list(map(stringify, new_bkids))))
1633
1634 if len(lines) == 0:
1635 def fmt_with_title(title, strlines):
1636 lines = strlines.split('\n')
1637 sep = '\n' + ' '*(15 + len(title))
1638 return ' '*15 + title + sep.join(lines) + '\n'
1639 if old.bactsig != new.bactsig:
1640 if old.bact == new.bact:
1641 lines.append("the contents of the build action changed\n" +
1642 fmt_with_title('action: ', new.bact))
1643
1644
1645
1646 else:
1647 lines.append("the build action changed:\n" +
1648 fmt_with_title('old: ', old.bact) +
1649 fmt_with_title('new: ', new.bact))
1650
1651 if len(lines) == 0:
1652 return "rebuilding `%s' for unknown reasons\n" % self
1653
1654 preamble = "rebuilding `%s' because" % self
1655 if len(lines) == 1:
1656 return "%s %s" % (preamble, lines[0])
1657 else:
1658 lines = ["%s:\n" % preamble] + lines
1659 return ( ' '*11).join(lines)
1660
1663 return str(list(map(str, self.data)))
1664
1668
1670 """An iterator for walking a Node tree.
1671
1672 This is depth-first, children are visited before the parent.
1673 The Walker object can be initialized with any node, and
1674 returns the next node on the descent with each get_next() call.
1675 'kids_func' is an optional function that will be called to
1676 get the children of a node instead of calling 'children'.
1677 'cycle_func' is an optional function that will be called
1678 when a cycle is detected.
1679
1680 This class does not get caught in node cycles caused, for example,
1681 by C header file include loops.
1682 """
1683 - def __init__(self, node, kids_func=get_children,
1684 cycle_func=ignore_cycle,
1685 eval_func=do_nothing):
1686 self.kids_func = kids_func
1687 self.cycle_func = cycle_func
1688 self.eval_func = eval_func
1689 node.wkids = copy.copy(kids_func(node, None))
1690 self.stack = [node]
1691 self.history = {}
1692 self.history[node] = None
1693
1695 """Return the next node for this walk of the tree.
1696
1697 This function is intentionally iterative, not recursive,
1698 to sidestep any issues of stack size limitations.
1699 """
1700
1701 while self.stack:
1702 if self.stack[-1].wkids:
1703 node = self.stack[-1].wkids.pop(0)
1704 if not self.stack[-1].wkids:
1705 self.stack[-1].wkids = None
1706 if node in self.history:
1707 self.cycle_func(node, self.stack)
1708 else:
1709 node.wkids = copy.copy(self.kids_func(node, self.stack[-1]))
1710 self.stack.append(node)
1711 self.history[node] = None
1712 else:
1713 node = self.stack.pop()
1714 del self.history[node]
1715 if node:
1716 if self.stack:
1717 parent = self.stack[-1]
1718 else:
1719 parent = None
1720 self.eval_func(node, parent)
1721 return node
1722 return None
1723
1725 return not self.stack
1726
1727
1728 arg2nodes_lookups = []
1729
1730
1731
1732
1733
1734
1735