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 3a41ed6b288cee8d085373ad7fa02894e1903864 2019-01-23 17:30:35 bdeegan"
47
48 import os
49 import collections
50 import copy
51 from itertools import chain
52
53 import SCons.Debug
54 from SCons.Debug import logInstanceCreation
55 import SCons.Executor
56 import SCons.Memoize
57 import SCons.Util
58
59 from SCons.Debug import Trace
60
61 from SCons.compat import with_metaclass, NoSlotsPyPy
62
63 print_duplicate = 0
66 return str(obj.__class__).split('.')[-1]
67
68
69
70 do_store_info = True
71
72
73
74
75
76
77
78
79 no_state = 0
80 pending = 1
81 executing = 2
82 up_to_date = 3
83 executed = 4
84 failed = 5
85
86 StateString = {
87 0 : "no_state",
88 1 : "pending",
89 2 : "executing",
90 3 : "up_to_date",
91 4 : "executed",
92 5 : "failed",
93 }
94
95
96 implicit_cache = 0
97
98
99 implicit_deps_unchanged = 0
100
101
102 implicit_deps_changed = 0
107
108 Annotate = do_nothing
109
110
111
112
113 interactive = False
116 raise NotImplementedError
117
119 """
120 Returns true if this node is derived (i.e. built).
121 """
122 return node.has_builder() or node.side_effect
123
124 _is_derived_map = {0 : is_derived_none,
125 1 : is_derived_node}
128 raise NotImplementedError
129
132
134 return node.stat() is not None
135
136 -def exists_entry(node):
137 """Return if the Entry exists. Check the file system to see
138 what we should turn into first. Assume a file if there's no
139 directory."""
140 node.disambiguate()
141 return _exists_map[node._func_exists](node)
142
167
168 _exists_map = {0 : exists_none,
169 1 : exists_always,
170 2 : exists_base,
171 3 : exists_entry,
172 4 : exists_file}
176 raise NotImplementedError
177
180
183
184 _rexists_map = {0 : rexists_none,
185 1 : rexists_node,
186 2 : rexists_base}
187
188 -def get_contents_none(node):
189 raise NotImplementedError
190
192 """Fetch the contents of the entry. Returns the exact binary
193 contents of the file."""
194 try:
195 node = node.disambiguate(must_exist=1)
196 except SCons.Errors.UserError:
197
198
199
200
201
202 return ''
203 else:
204 return _get_contents_map[node._func_get_contents](node)
205
207 """Return content signatures and names of all our children
208 separated by new-lines. Ensure that the nodes are sorted."""
209 contents = []
210 for n in sorted(node.children(), key=lambda t: t.name):
211 contents.append('%s %s\n' % (n.get_csig(), n.name))
212 return ''.join(contents)
213
215 if not node.rexists():
216 return b''
217 fname = node.rfile().get_abspath()
218 try:
219 with open(fname, "rb") as fp:
220 contents = fp.read()
221 except EnvironmentError as e:
222 if not e.filename:
223 e.filename = fname
224 raise
225 return contents
226
227 _get_contents_map = {0 : get_contents_none,
228 1 : get_contents_entry,
229 2 : get_contents_dir,
230 3 : get_contents_file}
233 raise NotImplementedError
234
237
238 _target_from_source_map = {0 : target_from_source_none,
239 1 : target_from_source_base}
240
241
242
243
244
245
246
247
248
249
250
251
252 -class DeciderNeedsNode(Exception):
253 """
254 Indicate that the decider needs the node as well as the target and the dependency.
255 Normally the node and the target are the same, but in the case of repository
256 They may be different. Also the NodeInfo is retrieved from the node
257 """
259 """
260 :param call_this_decider: to return the decider to call directly since deciders
261 are called through several levels of indirection
262 """
263 self.decider = call_this_decider
264
270 """
271
272 Must be overridden in a specific subclass to return True if this
273 Node (a dependency) has changed since the last time it was used
274 to build the specified target. prev_ni is this Node's state (for
275 example, its file timestamp, length, maybe content signature)
276 as of the last time the target was built.
277
278 Note that this method is called through the dependency, not the
279 target, because a dependency Node must be able to use its own
280 logic to decide if it changed. For example, File Nodes need to
281 obey if we're configured to use timestamps, but Python Value Nodes
282 never use timestamps and always use the content. If this method
283 were called through the target, then each Node's implementation
284 of this method would have to have more complicated logic to
285 handle all the different Node types on which it might depend.
286 """
287 raise NotImplementedError
288
291 cur_csig = node.get_csig()
292 try:
293 return cur_csig != prev_ni.csig
294 except AttributeError:
295 return 1
296
297
298 -def changed_since_last_build_entry(node, target, prev_ni):
299 node.disambiguate()
300 return _decider_map[node.changed_since_last_build](node, target, prev_ni)
301
305
308 return target.get_build_env().decide_source(node, target, prev_ni)
309
312 return target.get_build_env().decide_target(node, target, prev_ni)
313
316 cur_csig = node.get_csig()
317 try:
318 return cur_csig != prev_ni.csig
319 except AttributeError:
320 return 1
321
322
323
324
325
326 _decider_map = {0 : changed_since_last_build_node,
327 1 : changed_since_last_build_alias,
328 2 : changed_since_last_build_entry,
329 3 : changed_since_last_build_state_changed,
330 4 : decide_source,
331 5 : decide_target,
332 6 : changed_since_last_build_python}
333
334 do_store_info = True
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350 -def store_info_pass(node):
352
360
361
362 store_info_map = {0 : store_info_pass,
363 1 : store_info_file}
368 """
369 The generic base class for signature information for a Node.
370
371 Node subclasses should subclass NodeInfoBase to provide their own
372 logic for dealing with their own Node-specific signature information.
373 """
374 __slots__ = ('__weakref__',)
375 current_version_id = 2
376
378 try:
379 field_list = self.field_list
380 except AttributeError:
381 return
382 for f in field_list:
383 try:
384 delattr(self, f)
385 except AttributeError:
386 pass
387 try:
388 func = getattr(node, 'get_' + f)
389 except AttributeError:
390 pass
391 else:
392 setattr(self, f, func())
393
396
398 """
399 Merge the fields of another object into this object. Already existing
400 information is overwritten by the other instance's data.
401 WARNING: If a '__dict__' slot is added, it should be updated instead of
402 replaced.
403 """
404 state = other.__getstate__()
405 self.__setstate__(state)
406
429
431 """
432 Return all fields that shall be pickled. Walk the slots in the class
433 hierarchy and add those to the state dictionary. If a '__dict__' slot is
434 available, copy all entries to the dictionary. Also include the version
435 id, which is fixed for all instances of a class.
436 """
437 state = getattr(self, '__dict__', {}).copy()
438 for obj in type(self).mro():
439 for name in getattr(obj,'__slots__',()):
440 if hasattr(self, name):
441 state[name] = getattr(self, name)
442
443 state['_version_id'] = self.current_version_id
444 try:
445 del state['__weakref__']
446 except KeyError:
447 pass
448 return state
449
451 """
452 Restore the attributes from a pickled state. The version is discarded.
453 """
454
455 del state['_version_id']
456
457 for key, value in state.items():
458 if key not in ('__weakref__',):
459 setattr(self, key, value)
460
463 """
464 The generic base class for build information for a Node.
465
466 This is what gets stored in a .sconsign file for each target file.
467 It contains a NodeInfo instance for this node (signature information
468 that's specific to the type of Node) and direct attributes for the
469 generic build stuff we have to track: sources, explicit dependencies,
470 implicit dependencies, and action information.
471 """
472 __slots__ = ("bsourcesigs", "bdependsigs", "bimplicitsigs", "bactsig",
473 "bsources", "bdepends", "bact", "bimplicit", "__weakref__")
474 current_version_id = 2
475
483
485 """
486 Merge the fields of another object into this object. Already existing
487 information is overwritten by the other instance's data.
488 WARNING: If a '__dict__' slot is added, it should be updated instead of
489 replaced.
490 """
491 state = other.__getstate__()
492 self.__setstate__(state)
493
495 """
496 Return all fields that shall be pickled. Walk the slots in the class
497 hierarchy and add those to the state dictionary. If a '__dict__' slot is
498 available, copy all entries to the dictionary. Also include the version
499 id, which is fixed for all instances of a class.
500 """
501 state = getattr(self, '__dict__', {}).copy()
502 for obj in type(self).mro():
503 for name in getattr(obj,'__slots__',()):
504 if hasattr(self, name):
505 state[name] = getattr(self, name)
506
507 state['_version_id'] = self.current_version_id
508 try:
509 del state['__weakref__']
510 except KeyError:
511 pass
512 return state
513
515 """
516 Restore the attributes from a pickled state.
517 """
518
519 del state['_version_id']
520 for key, value in state.items():
521 if key not in ('__weakref__',):
522 setattr(self, key, value)
523
524
525 -class Node(object, with_metaclass(NoSlotsPyPy)):
526 """The base Node class, for entities that we know how to
527 build, or use to build other Nodes.
528 """
529
530 __slots__ = ['sources',
531 'sources_set',
532 '_specific_sources',
533 'depends',
534 'depends_set',
535 'ignore',
536 'ignore_set',
537 'prerequisites',
538 'implicit',
539 'waiting_parents',
540 'waiting_s_e',
541 'ref_count',
542 'wkids',
543 'env',
544 'state',
545 'precious',
546 'noclean',
547 'nocache',
548 'cached',
549 'always_build',
550 'includes',
551 'attributes',
552 'side_effect',
553 'side_effects',
554 'linked',
555 '_memo',
556 'executor',
557 'binfo',
558 'ninfo',
559 'builder',
560 'is_explicit',
561 'implicit_set',
562 'changed_since_last_build',
563 'store_info',
564 'pseudo',
565 '_tags',
566 '_func_is_derived',
567 '_func_exists',
568 '_func_rexists',
569 '_func_get_contents',
570 '_func_target_from_source']
571
573 __slots__ = ('shared', '__dict__')
574
575
633
636
639
640 @SCons.Memoize.CountMethodCall
651
655
659
680
690
692 """Remove cached executor; forces recompute when needed."""
693 try:
694 delattr(self, 'executor')
695 except AttributeError:
696 pass
697
699 """Try to push a node into a cache
700 """
701 pass
702
704 """Try to retrieve the node's content from a cache
705
706 This method is called from multiple threads in a parallel build,
707 so only do thread safe stuff here. Do thread unsafe stuff in
708 built().
709
710 Returns true if the node was successfully retrieved.
711 """
712 return 0
713
714
715
716
717
719 """Get a Node ready for evaluation.
720
721 This is called before the Taskmaster decides if the Node is
722 up-to-date or not. Overriding this method allows for a Node
723 subclass to be disambiguated if necessary, or for an implicit
724 source builder to be attached.
725 """
726 pass
727
729 """Prepare for this Node to be built.
730
731 This is called after the Taskmaster has decided that the Node
732 is out-of-date and must be rebuilt, but before actually calling
733 the method to build the Node.
734
735 This default implementation checks that explicit or implicit
736 dependencies either exist or are derived, and initializes the
737 BuildInfo structure that will hold the information about how
738 this node is, uh, built.
739
740 (The existence of source files is checked separately by the
741 Executor, which aggregates checks for all of the targets built
742 by a specific action.)
743
744 Overriding this method allows for for a Node subclass to remove
745 the underlying file from the file system. Note that subclass
746 methods should call this base class method to get the child
747 check and the BuildInfo structure.
748 """
749 if self.depends is not None:
750 for d in self.depends:
751 if d.missing():
752 msg = "Explicit dependency `%s' not found, needed by target `%s'."
753 raise SCons.Errors.StopError(msg % (d, self))
754 if self.implicit is not None:
755 for i in self.implicit:
756 if i.missing():
757 msg = "Implicit dependency `%s' not found, needed by target `%s'."
758 raise SCons.Errors.StopError(msg % (i, self))
759 self.binfo = self.get_binfo()
760
762 """Actually build the node.
763
764 This is called by the Taskmaster after it's decided that the
765 Node is out-of-date and must be rebuilt, and after the prepare()
766 method has gotten everything, uh, prepared.
767
768 This method is called from multiple threads in a parallel build,
769 so only do thread safe stuff here. Do thread unsafe stuff
770 in built().
771
772 """
773 try:
774 self.get_executor()(self, **kw)
775 except SCons.Errors.BuildError as e:
776 e.node = self
777 raise
778
797
810
812 """Called just after this node has been marked
813 up-to-date or was built completely.
814
815 This is where we try to release as many target node infos
816 as possible for clean builds and update runs, in order
817 to minimize the overall memory consumption.
818
819 By purging attributes that aren't needed any longer after
820 a Node (=File) got built, we don't have to care that much how
821 many KBytes a Node actually requires...as long as we free
822 the memory shortly afterwards.
823
824 @see: built() and File.release_target_info()
825 """
826 pass
827
828
829
830
831
834
836 """
837 Returns the number of nodes added to our waiting parents list:
838 1 if we add a unique waiting parent, 0 if not. (Note that the
839 returned values are intended to be used to increment a reference
840 count, so don't think you can "clean up" this function by using
841 True and False instead...)
842 """
843 wp = self.waiting_parents
844 if node in wp:
845 return 0
846 wp.add(node)
847 return 1
848
849 - def postprocess(self):
850 """Clean up anything we don't need to hang onto after we've
851 been built."""
852 self.executor_cleanup()
853 self.waiting_parents = set()
854
856 """Completely clear a Node of all its cached state (so that it
857 can be re-evaluated by interfaces that do continuous integration
858 builds).
859 """
860
861
862
863 self.del_binfo()
864 self.clear_memoized_values()
865 self.ninfo = self.new_ninfo()
866 self.executor_cleanup()
867 try:
868 delattr(self, '_calculated_sig')
869 except AttributeError:
870 pass
871 self.includes = None
872
875
882
884 """Return whether this Node has a builder or not.
885
886 In Boolean tests, this turns out to be a *lot* more efficient
887 than simply examining the builder attribute directly ("if
888 node.builder: ..."). When the builder attribute is examined
889 directly, it ends up calling __getattr__ for both the __len__
890 and __nonzero__ attributes on instances of our Builder Proxy
891 class(es), generating a bazillion extra calls and slowing
892 things down immensely.
893 """
894 try:
895 b = self.builder
896 except AttributeError:
897
898
899 b = self.builder = None
900 return b is not None
901
904
906 """Return whether this Node has an explicit builder
907
908 This allows an internal Builder created by SCons to be marked
909 non-explicit, so that it can be overridden by an explicit
910 builder that the user supplies (the canonical example being
911 directories)."""
912 try:
913 return self.is_explicit
914 except AttributeError:
915 self.is_explicit = None
916 return self.is_explicit
917
919 """Return the set builder, or a specified default value"""
920 try:
921 return self.builder
922 except AttributeError:
923 return default_builder
924
925 multiple_side_effect_has_builder = has_builder
926
928 """
929 Returns true if this node is derived (i.e. built).
930
931 This should return true only for nodes whose path should be in
932 the variant directory when duplicate=0 and should contribute their build
933 signatures when they are used as source files to other derived files. For
934 example: source with source builders are not derived in this sense,
935 and hence should not return true.
936 """
937 return _is_derived_map[self._func_is_derived](self)
938
940 """Return a list of alternate targets for this Node.
941 """
942 return [], None
943
945 """Return the scanned include lines (implicit dependencies)
946 found in this node.
947
948 The default is no implicit dependencies. We expect this method
949 to be overridden by any subclass that can be scanned for
950 implicit dependencies.
951 """
952 return []
953
955 """Return a list of implicit dependencies for this node.
956
957 This method exists to handle recursive invocation of the scanner
958 on the implicit dependencies returned by the scanner, if the
959 scanner's recursive flag says that we should.
960 """
961 nodes = [self]
962 seen = set(nodes)
963 dependencies = []
964 path_memo = {}
965
966 root_node_scanner = self._get_scanner(env, initial_scanner, None, kw)
967
968 while nodes:
969 node = nodes.pop(0)
970
971 scanner = node._get_scanner(env, initial_scanner, root_node_scanner, kw)
972 if not scanner:
973 continue
974
975 try:
976 path = path_memo[scanner]
977 except KeyError:
978 path = path_func(scanner)
979 path_memo[scanner] = path
980
981 included_deps = [x for x in node.get_found_includes(env, scanner, path) if x not in seen]
982 if included_deps:
983 dependencies.extend(included_deps)
984 seen.update(included_deps)
985 nodes.extend(scanner.recurse_nodes(included_deps))
986
987 return dependencies
988
989 - def _get_scanner(self, env, initial_scanner, root_node_scanner, kw):
990 if initial_scanner:
991
992 scanner = initial_scanner.select(self)
993 else:
994
995 scanner = self.get_env_scanner(env, kw)
996 if scanner:
997 scanner = scanner.select(self)
998
999 if not scanner:
1000
1001
1002 scanner = root_node_scanner
1003
1004 return scanner
1005
1008
1010 return self.builder.target_scanner
1011
1013 """Fetch the source scanner for the specified node
1014
1015 NOTE: "self" is the target being built, "node" is
1016 the source file for which we want to fetch the scanner.
1017
1018 Implies self.has_builder() is true; again, expect to only be
1019 called from locations where this is already verified.
1020
1021 This function may be called very often; it attempts to cache
1022 the scanner found to improve performance.
1023 """
1024 scanner = None
1025 try:
1026 scanner = self.builder.source_scanner
1027 except AttributeError:
1028 pass
1029 if not scanner:
1030
1031
1032
1033 scanner = self.get_env_scanner(self.get_build_env())
1034 if scanner:
1035 scanner = scanner.select(node)
1036 return scanner
1037
1044
1093
1096
1098 """Selects a scanner for this Node.
1099
1100 This is a separate method so it can be overridden by Node
1101 subclasses (specifically, Node.FS.Dir) that *must* use their
1102 own Scanner and don't select one the Scanner.Selector that's
1103 configured for the target.
1104 """
1105 return scanner.select(self)
1106
1108 if safe and self.env:
1109 return
1110 self.env = env
1111
1112
1113
1114
1115
1116 NodeInfo = NodeInfoBase
1117 BuildInfo = BuildInfoBase
1118
1122
1129
1133
1185
1187 """Delete the build info from this node."""
1188 try:
1189 delattr(self, 'binfo')
1190 except AttributeError:
1191 pass
1192
1200
1203
1206
1208 """Fetch the stored implicit dependencies"""
1209 return None
1210
1211
1212
1213
1214
1218
1220 """Set the Node's precious value."""
1221 self.pseudo = pseudo
1222
1224 """Set the Node's noclean value."""
1225
1226
1227 self.noclean = noclean and 1 or 0
1228
1230 """Set the Node's nocache value."""
1231
1232
1233 self.nocache = nocache and 1 or 0
1234
1238
1242
1247
1248 - def get_contents(self):
1249 """Fetch the contents of the entry."""
1250 return _get_contents_map[self._func_get_contents](self)
1251
1256
1258 """Remove this Node: no-op by default."""
1259 return None
1260
1262 """Adds dependencies."""
1263 try:
1264 self._add_child(self.depends, self.depends_set, depend)
1265 except TypeError as e:
1266 e = e.args[0]
1267 if SCons.Util.is_List(e):
1268 s = list(map(str, e))
1269 else:
1270 s = str(e)
1271 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)))
1272
1279
1281 """Adds dependencies to ignore."""
1282 try:
1283 self._add_child(self.ignore, self.ignore_set, depend)
1284 except TypeError as e:
1285 e = e.args[0]
1286 if SCons.Util.is_List(e):
1287 s = list(map(str, e))
1288 else:
1289 s = str(e)
1290 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)))
1291
1305
1307 """Adds 'child' to 'collection', first checking 'set' to see if it's
1308 already present."""
1309 added = None
1310 for c in child:
1311 if c not in set:
1312 set.add(c)
1313 collection.append(c)
1314 added = 1
1315 if added:
1316 self._children_reset()
1317
1321
1323 """Add a node to the list of kids waiting to be evaluated"""
1324 if self.wkids is not None:
1325 self.wkids.append(wkid)
1326
1332
1333 @SCons.Memoize.CountMethodCall
1369
1371 """Return a list of all the node's direct children."""
1372 if scan:
1373 self.scan()
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392 return list(chain.from_iterable([_f for _f in [self.sources, self.depends, self.implicit] if _f]))
1393
1395 """Return a list of the node's direct children, minus those
1396 that are ignored by this node."""
1397 if scan:
1398 self.scan()
1399 return self._children_get()
1400
1403
1406
1413
1424
1425 - def Tag(self, key, value):
1426 """ Add a user-defined tag. """
1427 if not self._tags:
1428 self._tags = {}
1429 self._tags[key] = value
1430
1432 """ Return a user-defined tag. """
1433 if not self._tags:
1434 return None
1435 return self._tags.get(key, None)
1436
1437 - def changed(self, node=None, allowcache=False):
1438 """
1439 Returns if the node is up-to-date with respect to the BuildInfo
1440 stored last time it was built. The default behavior is to compare
1441 it against our own previously stored BuildInfo, but the stored
1442 BuildInfo from another Node (typically one in a Repository)
1443 can be used instead.
1444
1445 Note that we now *always* check every dependency. We used to
1446 short-circuit the check by returning as soon as we detected
1447 any difference, but we now rely on checking every dependency
1448 to make sure that any necessary Node information (for example,
1449 the content signature of an #included .h file) is updated.
1450
1451 The allowcache option was added for supporting the early
1452 release of the executor/builder structures, right after
1453 a File target was built. When set to true, the return
1454 value of this changed method gets cached for File nodes.
1455 Like this, the executor isn't needed any longer for subsequent
1456 calls to changed().
1457
1458 @see: FS.File.changed(), FS.File.release_target_info()
1459 """
1460 t = 0
1461 if t: Trace('changed(%s [%s], %s)' % (self, classname(self), node))
1462 if node is None:
1463 node = self
1464
1465 result = False
1466
1467 bi = node.get_stored_info().binfo
1468 then = bi.bsourcesigs + bi.bdependsigs + bi.bimplicitsigs
1469 children = self.children()
1470
1471 diff = len(children) - len(then)
1472 if diff:
1473
1474
1475
1476
1477
1478 then.extend([None] * diff)
1479 if t: Trace(': old %s new %s' % (len(then), len(children)))
1480 result = True
1481
1482 for child, prev_ni in zip(children, then):
1483 try:
1484 if _decider_map[child.changed_since_last_build](child, self, prev_ni):
1485 if t: Trace(': %s changed' % child)
1486 result = True
1487 except DeciderNeedsNode as e:
1488 if e.decider(self, prev_ni, node=node):
1489 if t: Trace(': %s changed' % child)
1490 result = True
1491
1492 if self.has_builder():
1493 import SCons.Util
1494 contents = self.get_executor().get_contents()
1495 newsig = SCons.Util.MD5signature(contents)
1496 if bi.bactsig != newsig:
1497 if t: Trace(': bactsig %s != newsig %s' % (bi.bactsig, newsig))
1498 result = True
1499
1500 if not result:
1501 if t: Trace(': up to date')
1502
1503 if t: Trace('\n')
1504
1505 return result
1506
1508 """Default check for whether the Node is current: unknown Node
1509 subtypes are always out of date, so they will always get built."""
1510 return None
1511
1513 """Alternate check for whether the Node is current: If all of
1514 our children were up-to-date, then this Node was up-to-date, too.
1515
1516 The SCons.Node.Alias and SCons.Node.Python.Value subclasses
1517 rebind their current() method to this method."""
1518
1519 self.binfo = self.get_binfo()
1520 if self.always_build:
1521 return None
1522 state = 0
1523 for kid in self.children(None):
1524 s = kid.get_state()
1525 if s and (not state or s > state):
1526 state = s
1527 return (state == 0 or state == SCons.Node.up_to_date)
1528
1530 """Always pass the string representation of a Node to
1531 the command interpreter literally."""
1532 return 1
1533
1550 return SCons.Util.render_tree(s, f, 1)
1551 else:
1552 return None
1553
1555 """
1556 Return an absolute path to the Node. This will return simply
1557 str(Node) by default, but for Node types that have a concept of
1558 relative path, this might return something different.
1559 """
1560 return str(self)
1561
1563 """
1564 Return a string representation of the Node that will always
1565 be the same for this particular Node, no matter what. This
1566 is by contrast to the __str__() method, which might, for
1567 instance, return a relative path for a file Node. The purpose
1568 of this method is to generate a value to be used in signature
1569 calculation for the command line used to build a target, and
1570 we use this method instead of str() to avoid unnecessary
1571 rebuilds. This method does not need to return something that
1572 would actually work in a command line; it can return any kind of
1573 nonsense, so long as it does not change.
1574 """
1575 return str(self)
1576
1578 """This is a convenience function designed primarily to be
1579 used in command generators (i.e., CommandGeneratorActions or
1580 Environment variables that are callable), which are called
1581 with a for_signature argument that is nonzero if the command
1582 generator is being called to generate a signature for the
1583 command line, which determines if we should rebuild or not.
1584
1585 Such command generators should use this method in preference
1586 to str(Node) when converting a Node to a string, passing
1587 in the for_signature parameter, such that we will call
1588 Node.for_signature() or str(Node) properly, depending on whether
1589 we are calculating a signature or actually constructing a
1590 command line."""
1591 if for_signature:
1592 return self.for_signature()
1593 return str(self)
1594
1596 """
1597 This method is expected to return an object that will function
1598 exactly like this Node, except that it implements any additional
1599 special features that we would like to be in effect for
1600 Environment variable substitution. The principle use is that
1601 some Nodes would like to implement a __getattr__() method,
1602 but putting that in the Node type itself has a tendency to kill
1603 performance. We instead put it in a proxy and return it from
1604 this method. It is legal for this method to return self
1605 if no new functionality is needed for Environment substitution.
1606 """
1607 return self
1608
1610 if not self.exists():
1611 return "building `%s' because it doesn't exist\n" % self
1612
1613 if self.always_build:
1614 return "rebuilding `%s' because AlwaysBuild() is specified\n" % self
1615
1616 old = self.get_stored_info()
1617 if old is None:
1618 return None
1619
1620 old = old.binfo
1621 old.prepare_dependencies()
1622
1623 try:
1624 old_bkids = old.bsources + old.bdepends + old.bimplicit
1625 old_bkidsigs = old.bsourcesigs + old.bdependsigs + old.bimplicitsigs
1626 except AttributeError:
1627 return "Cannot explain why `%s' is being rebuilt: No previous build information found\n" % self
1628
1629 new = self.get_binfo()
1630
1631 new_bkids = new.bsources + new.bdepends + new.bimplicit
1632 new_bkidsigs = new.bsourcesigs + new.bdependsigs + new.bimplicitsigs
1633
1634 osig = dict(list(zip(old_bkids, old_bkidsigs)))
1635 nsig = dict(list(zip(new_bkids, new_bkidsigs)))
1636
1637
1638
1639
1640
1641
1642
1643 def stringify( s, E=self.dir.Entry):
1644 if hasattr( s, 'dir' ) :
1645 return str(E(s))
1646 return str(s)
1647
1648 lines = []
1649
1650 removed = [x for x in old_bkids if not x in new_bkids]
1651 if removed:
1652 removed = [stringify(r) for r in removed]
1653 fmt = "`%s' is no longer a dependency\n"
1654 lines.extend([fmt % s for s in removed])
1655
1656 for k in new_bkids:
1657 if not k in old_bkids:
1658 lines.append("`%s' is a new dependency\n" % stringify(k))
1659 else:
1660 try:
1661 changed = _decider_map[k.changed_since_last_build](k, self, osig[k])
1662 except DeciderNeedsNode as e:
1663 changed = e.decider(self, osig[k], node=self)
1664
1665 if changed:
1666 lines.append("`%s' changed\n" % stringify(k))
1667
1668 if len(lines) == 0 and old_bkids != new_bkids:
1669 lines.append("the dependency order changed:\n" +
1670 "%sold: %s\n" % (' '*15, list(map(stringify, old_bkids))) +
1671 "%snew: %s\n" % (' '*15, list(map(stringify, new_bkids))))
1672
1673 if len(lines) == 0:
1674 def fmt_with_title(title, strlines):
1675 lines = strlines.split('\n')
1676 sep = '\n' + ' '*(15 + len(title))
1677 return ' '*15 + title + sep.join(lines) + '\n'
1678 if old.bactsig != new.bactsig:
1679 if old.bact == new.bact:
1680 lines.append("the contents of the build action changed\n" +
1681 fmt_with_title('action: ', new.bact))
1682
1683
1684
1685 else:
1686 lines.append("the build action changed:\n" +
1687 fmt_with_title('old: ', old.bact) +
1688 fmt_with_title('new: ', new.bact))
1689
1690 if len(lines) == 0:
1691 return "rebuilding `%s' for unknown reasons\n" % self
1692
1693 preamble = "rebuilding `%s' because" % self
1694 if len(lines) == 1:
1695 return "%s %s" % (preamble, lines[0])
1696 else:
1697 lines = ["%s:\n" % preamble] + lines
1698 return ( ' '*11).join(lines)
1699
1702 return str(list(map(str, self.data)))
1703
1707
1709 """An iterator for walking a Node tree.
1710
1711 This is depth-first, children are visited before the parent.
1712 The Walker object can be initialized with any node, and
1713 returns the next node on the descent with each get_next() call.
1714 'kids_func' is an optional function that will be called to
1715 get the children of a node instead of calling 'children'.
1716 'cycle_func' is an optional function that will be called
1717 when a cycle is detected.
1718
1719 This class does not get caught in node cycles caused, for example,
1720 by C header file include loops.
1721 """
1722 - def __init__(self, node, kids_func=get_children,
1723 cycle_func=ignore_cycle,
1724 eval_func=do_nothing):
1725 self.kids_func = kids_func
1726 self.cycle_func = cycle_func
1727 self.eval_func = eval_func
1728 node.wkids = copy.copy(kids_func(node, None))
1729 self.stack = [node]
1730 self.history = {}
1731 self.history[node] = None
1732
1734 """Return the next node for this walk of the tree.
1735
1736 This function is intentionally iterative, not recursive,
1737 to sidestep any issues of stack size limitations.
1738 """
1739
1740 while self.stack:
1741 if self.stack[-1].wkids:
1742 node = self.stack[-1].wkids.pop(0)
1743 if not self.stack[-1].wkids:
1744 self.stack[-1].wkids = None
1745 if node in self.history:
1746 self.cycle_func(node, self.stack)
1747 else:
1748 node.wkids = copy.copy(self.kids_func(node, self.stack[-1]))
1749 self.stack.append(node)
1750 self.history[node] = None
1751 else:
1752 node = self.stack.pop()
1753 del self.history[node]
1754 if node:
1755 if self.stack:
1756 parent = self.stack[-1]
1757 else:
1758 parent = None
1759 self.eval_func(node, parent)
1760 return node
1761 return None
1762
1764 return not self.stack
1765
1766
1767 arg2nodes_lookups = []
1768
1769
1770
1771
1772
1773
1774