1 """SCons.Executor
2
3 A module for executing actions with specific lists of target and source
4 Nodes.
5
6 """
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 from __future__ import print_function
30
31 __revision__ = "src/engine/SCons/Executor.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan"
32
33 import collections
34
35 import SCons.Debug
36 from SCons.Debug import logInstanceCreation
37 import SCons.Errors
38 import SCons.Memoize
39 import SCons.Util
40 from SCons.compat import with_metaclass, NoSlotsPyPy
43 """Remembers exact association between targets
44 and sources of executor."""
45
46 __slots__ = ('targets',
47 'sources')
48
49 - def __init__(self, targets=[], sources=[]):
52
53
54
55 -class TSList(collections.UserList):
56 """A class that implements $TARGETS or $SOURCES expansions by wrapping
57 an executor Method. This class is used in the Executor.lvars()
58 to delay creation of NodeList objects until they're needed.
59
60 Note that we subclass collections.UserList purely so that the
61 is_Sequence() function will identify an object of this class as
62 a list during variable expansion. We're not really using any
63 collections.UserList methods in practice.
64 """
68 nl = self.func()
69 return getattr(nl, attr)
71 nl = self.func()
72 return nl[i]
74 nl = self.func()
75 i, j = max(i, 0), max(j, 0)
76 return nl[i:j]
78 nl = self.func()
79 return str(nl)
81 nl = self.func()
82 return repr(nl)
83
85 """A class that implements $TARGET or $SOURCE expansions by wrapping
86 an Executor method.
87 """
91 n = self.func()
92 return getattr(n, attr)
94 n = self.func()
95 if n:
96 return str(n)
97 return ''
99 n = self.func()
100 if n:
101 return repr(n)
102 return ''
103
105 """
106 A function to return the results of a Node's rfile() method,
107 if it exists, and the Node itself otherwise (if it's a Value
108 Node, e.g.).
109 """
110 try:
111 rfile = node.rfile
112 except AttributeError:
113 return node
114 else:
115 return rfile()
116
120
140
141 _do_execute_map = {0 : execute_nothing,
142 1 : execute_action_list}
151
154
155 _execute_str_map = {0 : execute_null_str,
156 1 : execute_actions_str}
157
158
159 -class Executor(object, with_metaclass(NoSlotsPyPy)):
160 """A class for controlling instances of executing an action.
161
162 This largely exists to hold a single association of an action,
163 environment, list of environment override dictionaries, targets
164 and sources for later processing as needed.
165 """
166
167 __slots__ = ('pre_actions',
168 'post_actions',
169 'env',
170 'overridelist',
171 'batches',
172 'builder_kw',
173 '_memo',
174 'lvars',
175 '_changed_sources_list',
176 '_changed_targets_list',
177 '_unchanged_sources_list',
178 '_unchanged_targets_list',
179 'action_list',
180 '_do_execute',
181 '_execute_str')
182
183 - def __init__(self, action, env=None, overridelist=[{}],
184 targets=[], sources=[], builder_kw={}):
199
215
234
241
248
251
254
257
260
267
274
276 if not self.action_list:
277 return []
278 targets_string = self.action_list[0].get_targets(self.env, self)
279 if targets_string[0] == '$':
280 targets_string = targets_string[1:]
281 return self.get_lvars()[targets_string]
282
291
296
303
310
312 """Returns all unique children (dependencies) for all batches
313 of this Executor.
314
315 The Taskmaster can recognize when it's already evaluated a
316 Node, so we don't have to make this list unique for its intended
317 canonical use case, but we expect there to be a lot of redundancy
318 (long lists of batched .cc files #including the same .h files
319 over and over), so removing the duplicates once up front should
320 save the Taskmaster a lot of work.
321 """
322 result = SCons.Util.UniqueList([])
323 for target in self.get_all_targets():
324 result.extend(target.children())
325 return result
326
336
346
347 @SCons.Memoize.CountMethodCall
349 """Fetch or create the appropriate build Environment
350 for this Executor.
351 """
352 try:
353 return self._memo['get_build_env']
354 except KeyError:
355 pass
356
357
358
359
360
361
362 overrides = {}
363 for odict in self.overridelist:
364 overrides.update(odict)
365
366 import SCons.Defaults
367 env = self.env or SCons.Defaults.DefaultEnvironment()
368 build_env = env.Override(overrides)
369
370 self._memo['get_build_env'] = build_env
371
372 return build_env
373
385
391
392
393
394
395
398
401
403 """Add source files to this Executor's list. This is necessary
404 for "multi" Builders that can be called repeatedly to build up
405 a source file list for a given target."""
406
407 assert (len(self.batches) == 1)
408
409 sources = [x for x in sources if x not in self.batches[0].sources]
410 self.batches[0].sources.extend(sources)
411
414
416 """Add pair of associated target and source to this Executor's list.
417 This is necessary for "batch" Builders that can be called repeatedly
418 to build up a list of matching target and source files that will be
419 used in order to update multiple target files at once from multiple
420 corresponding source files, for tools like MSVC that support it."""
421 self.batches.append(Batch(targets, sources))
422
424 """
425 Preparatory checks for whether this Executor can go ahead
426 and (try to) build its targets.
427 """
428 for s in self.get_all_sources():
429 if s.missing():
430 msg = "Source `%s' not found, needed by target `%s'."
431 raise SCons.Errors.StopError(msg % (s, self.batches[0].targets[0]))
432
435
436 - def add_post_action(self, action):
437 self.post_actions.append(action)
438
439
440
443
448
449 @SCons.Memoize.CountMethodCall
450 - def get_contents(self):
451 """Fetch the signature contents. This is the main reason this
452 class exists, so we can compute this once and cache it regardless
453 of how many target or source Nodes there are.
454
455 Returns bytes
456 """
457 try:
458 return self._memo['get_contents']
459 except KeyError:
460 pass
461 env = self.get_build_env()
462
463 action_list = self.get_action_list()
464 all_targets = self.get_all_targets()
465 all_sources = self.get_all_sources()
466
467 result = bytearray("",'utf-8').join([action.get_contents(all_targets,
468 all_sources,
469 env)
470 for action in action_list])
471
472 self._memo['get_contents'] = result
473 return result
474
476 """Fetch a time stamp for this Executor. We don't have one, of
477 course (only files do), but this is the interface used by the
478 timestamp module.
479 """
480 return 0
481
485
490
491 - def scan(self, scanner, node_list):
512
514 return (node,) + tuple(ignore)
515
516 @SCons.Memoize.CountDictCall(_get_unignored_sources_key)
518 key = (node,) + tuple(ignore)
519 try:
520 memo_dict = self._memo['get_unignored_sources']
521 except KeyError:
522 memo_dict = {}
523 self._memo['get_unignored_sources'] = memo_dict
524 else:
525 try:
526 return memo_dict[key]
527 except KeyError:
528 pass
529
530 if node:
531
532
533 sourcelist = []
534 for b in self.batches:
535 if node in b.targets:
536 sourcelist = b.sources
537 break
538 else:
539 sourcelist = self.get_all_sources()
540 if ignore:
541 idict = {}
542 for i in ignore:
543 idict[i] = 1
544 sourcelist = [s for s in sourcelist if s not in idict]
545
546 memo_dict[key] = sourcelist
547
548 return sourcelist
549
561
562
563
564 _batch_executors = {}
568
572
573 nullenv = None
582
591
592 -class Null(object, with_metaclass(NoSlotsPyPy)):
593 """A null Executor, with a null build Environment, that does
594 nothing when the rest of the methods call it.
595
596 This might be able to disappear when we refactor things to
597 disassociate Builders from Nodes entirely, so we're not
598 going to worry about unit tests for this--at least for now.
599 """
600
601 __slots__ = ('pre_actions',
602 'post_actions',
603 'env',
604 'overridelist',
605 'batches',
606 'builder_kw',
607 '_memo',
608 'lvars',
609 '_changed_sources_list',
610 '_changed_targets_list',
611 '_unchanged_sources_list',
612 '_unchanged_targets_list',
613 'action_list',
614 '_do_execute',
615 '_execute_str')
616
647 - def get_contents(self):
655
656
657
658
662 - def add_post_action(self, action):
663 self._morph()
664 self.add_post_action(action)
668
669
670
671
672
673
674