Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: third_party/scons/scons-local/SCons/Taskmaster.py

Issue 20025: Update SCons to latest checkpoint release, 1.2.0.d20090113.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # 1 #
2 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundat ion 2 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons F oundation
3 # 3 #
4 # Permission is hereby granted, free of charge, to any person obtaining 4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the 5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including 6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish, 7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to 8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to 9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions: 10 # the following conditions:
11 # 11 #
12 # The above copyright notice and this permission notice shall be included 12 # The above copyright notice and this permission notice shall be included
(...skipping 28 matching lines...) Expand all
41 which has Task subclasses that handle its specific behavior, 41 which has Task subclasses that handle its specific behavior,
42 like printing "`foo' is up to date" when a top-level target 42 like printing "`foo' is up to date" when a top-level target
43 doesn't need to be built, and handling the -c option by removing 43 doesn't need to be built, and handling the -c option by removing
44 targets as its "build" action. There is also a separate subclass 44 targets as its "build" action. There is also a separate subclass
45 for suppressing this output when the -q option is used. 45 for suppressing this output when the -q option is used.
46 46
47 The Taskmaster instantiates a Task object for each (set of) 47 The Taskmaster instantiates a Task object for each (set of)
48 target(s) that it decides need to be evaluated and/or built. 48 target(s) that it decides need to be evaluated and/or built.
49 """ 49 """
50 50
51 __revision__ = "src/engine/SCons/Taskmaster.py 3842 2008/12/20 22:59:52 scons" 51 __revision__ = "src/engine/SCons/Taskmaster.py 3897 2009/01/13 06:45:54 scons"
52 52
53 from itertools import chain 53 from itertools import chain
54 import operator 54 import operator
55 import string 55 import string
56 import sys 56 import sys
57 import traceback 57 import traceback
58 58
59 import SCons.Errors 59 import SCons.Errors
60 import SCons.Node 60 import SCons.Node
61 import SCons.Warnings
61 62
62 StateString = SCons.Node.StateString 63 StateString = SCons.Node.StateString
63 NODE_NO_STATE = SCons.Node.no_state 64 NODE_NO_STATE = SCons.Node.no_state
64 NODE_PENDING = SCons.Node.pending 65 NODE_PENDING = SCons.Node.pending
65 NODE_EXECUTING = SCons.Node.executing 66 NODE_EXECUTING = SCons.Node.executing
66 NODE_UP_TO_DATE = SCons.Node.up_to_date 67 NODE_UP_TO_DATE = SCons.Node.up_to_date
67 NODE_EXECUTED = SCons.Node.executed 68 NODE_EXECUTED = SCons.Node.executed
68 NODE_FAILED = SCons.Node.failed 69 NODE_FAILED = SCons.Node.failed
69 70
70 71
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 # Let the targets take care of any necessary preparations. 179 # Let the targets take care of any necessary preparations.
179 # This includes verifying that all of the necessary sources 180 # This includes verifying that all of the necessary sources
180 # and dependencies exist, removing the target file(s), etc. 181 # and dependencies exist, removing the target file(s), etc.
181 # 182 #
182 # As of April 2008, the get_executor().prepare() method makes 183 # As of April 2008, the get_executor().prepare() method makes
183 # sure that all of the aggregate sources necessary to build this 184 # sure that all of the aggregate sources necessary to build this
184 # Task's target(s) exist in one up-front check. The individual 185 # Task's target(s) exist in one up-front check. The individual
185 # target t.prepare() methods check that each target's explicit 186 # target t.prepare() methods check that each target's explicit
186 # or implicit dependencies exists, and also initialize the 187 # or implicit dependencies exists, and also initialize the
187 # .sconsign info. 188 # .sconsign info.
188 self.targets[0].get_executor().prepare() 189 executor = self.targets[0].get_executor()
189 for t in self.targets: 190 executor.prepare()
191 for t in executor.get_action_targets():
190 t.prepare() 192 t.prepare()
191 for s in t.side_effects: 193 for s in t.side_effects:
192 s.prepare() 194 s.prepare()
193 195
194 def get_target(self): 196 def get_target(self):
195 """Fetch the target being built or updated by this task. 197 """Fetch the target being built or updated by this task.
196 """ 198 """
197 return self.node 199 return self.node
198 200
199 def needs_execute(self): 201 def needs_execute(self):
200 """ 202 # TODO(deprecate): "return True" is the old default behavior;
201 Called to determine whether the task's execute() method should 203 # change it to NotImplementedError (after running through the
202 be run. 204 # Deprecation Cycle) so the desired behavior is explicitly
203 205 # determined by which concrete subclass is used.
204 This method allows one to skip the somethat costly execution 206 #raise NotImplementedError
205 of the execute() method in a seperate thread. For example, 207 msg = ('Direct use of the Taskmaster.Task class will be deprecated\n'
206 that would be unnecessary for up-to-date targets. 208 + '\tin a future release.')
207 """ 209 SCons.Warnings.warn(SCons.Warnings.TaskmasterNeedsExecuteWarning, msg)
208 return True 210 return True
209 211
210 def execute(self): 212 def execute(self):
211 """ 213 """
212 Called to execute the task. 214 Called to execute the task.
213 215
214 This method is called from multiple threads in a parallel build, 216 This method is called from multiple threads in a parallel build,
215 so only do thread safe stuff here. Do thread unsafe stuff in 217 so only do thread safe stuff here. Do thread unsafe stuff in
216 prepare(), executed() or failed(). 218 prepare(), executed() or failed().
217 """ 219 """
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 Task ready for execution. 496 Task ready for execution.
495 """ 497 """
496 exc = self.exc_info()[:] 498 exc = self.exc_info()[:]
497 try: 499 try:
498 exc_type, exc_value, exc_traceback = exc 500 exc_type, exc_value, exc_traceback = exc
499 except ValueError: 501 except ValueError:
500 exc_type, exc_value = exc 502 exc_type, exc_value = exc
501 exc_traceback = None 503 exc_traceback = None
502 raise exc_type, exc_value, exc_traceback 504 raise exc_type, exc_value, exc_traceback
503 505
506 class AlwaysTask(Task):
507 def needs_execute(self):
508 """
509 Always returns True (indicating this Task should always
510 be executed).
511
512 Subclasses that need this behavior (as opposed to the default
513 of only executing Nodes that are out of date w.r.t. their
514 dependencies) can use this as follows:
515
516 class MyTaskSubclass(SCons.Taskmaster.Task):
517 needs_execute = SCons.Taskmaster.Task.execute_always
518 """
519 return True
520
521 class OutOfDateTask(Task):
522 def needs_execute(self):
523 """
524 Returns True (indicating this Task should be executed) if this
525 Task's target state indicates it needs executing, which has
526 already been determined by an earlier up-to-date check.
527 """
528 return self.targets[0].get_state() == SCons.Node.executing
529
504 530
505 def find_cycle(stack, visited): 531 def find_cycle(stack, visited):
506 if stack[-1] in visited: 532 if stack[-1] in visited:
507 return None 533 return None
508 visited.add(stack[-1]) 534 visited.add(stack[-1])
509 for n in stack[-1].waiting_parents: 535 for n in stack[-1].waiting_parents:
510 stack.append(n) 536 stack.append(n)
511 if stack[0] == stack[-1]: 537 if stack[0] == stack[-1]:
512 return stack 538 return stack
513 if find_cycle(stack, visited): 539 if find_cycle(stack, visited):
514 return stack 540 return stack
515 stack.pop() 541 stack.pop()
516 return None 542 return None
517 543
518 544
519 class Taskmaster: 545 class Taskmaster:
520 """ 546 """
521 The Taskmaster for walking the dependency DAG. 547 The Taskmaster for walking the dependency DAG.
522 """ 548 """
523 549
524 def __init__(self, targets=[], tasker=Task, order=None, trace=None): 550 def __init__(self, targets=[], tasker=None, order=None, trace=None):
525 self.original_top = targets 551 self.original_top = targets
526 self.top_targets_left = targets[:] 552 self.top_targets_left = targets[:]
527 self.top_targets_left.reverse() 553 self.top_targets_left.reverse()
528 self.candidates = [] 554 self.candidates = []
555 if tasker is None:
556 tasker = OutOfDateTask
529 self.tasker = tasker 557 self.tasker = tasker
530 if not order: 558 if not order:
531 order = lambda l: l 559 order = lambda l: l
532 self.order = order 560 self.order = order
533 self.message = None 561 self.message = None
534 self.trace = trace 562 self.trace = trace
535 self.next_candidate = self.find_next_candidate 563 self.next_candidate = self.find_next_candidate
536 self.pending_children = set() 564 self.pending_children = set()
537 565
538 def find_next_candidate(self): 566 def find_next_candidate(self):
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 757
730 if state == NODE_NO_STATE: 758 if state == NODE_NO_STATE:
731 # Mark this node as being on the execution stack: 759 # Mark this node as being on the execution stack:
732 node.set_state(NODE_PENDING) 760 node.set_state(NODE_PENDING)
733 elif state > NODE_PENDING: 761 elif state > NODE_PENDING:
734 # Skip this node if it has already been evaluated: 762 # Skip this node if it has already been evaluated:
735 if S: S.already_handled = S.already_handled + 1 763 if S: S.already_handled = S.already_handled + 1
736 if T: T.write(self.trace_message(' already handled (execut ed)')) 764 if T: T.write(self.trace_message(' already handled (execut ed)'))
737 continue 765 continue
738 766
767 executor = node.get_executor()
768
739 try: 769 try:
740 children = node.children() 770 children = executor.get_all_children()
741 except SystemExit: 771 except SystemExit:
742 exc_value = sys.exc_info()[1] 772 exc_value = sys.exc_info()[1]
743 e = SCons.Errors.ExplicitExit(node, exc_value.code) 773 e = SCons.Errors.ExplicitExit(node, exc_value.code)
744 self.ready_exc = (SCons.Errors.ExplicitExit, e) 774 self.ready_exc = (SCons.Errors.ExplicitExit, e)
745 if T: T.write(self.trace_message(' SystemExit')) 775 if T: T.write(self.trace_message(' SystemExit'))
746 return node 776 return node
747 except Exception, e: 777 except Exception, e:
748 # We had a problem just trying to figure out the 778 # We had a problem just trying to figure out the
749 # children (like a child couldn't be linked in to a 779 # children (like a child couldn't be linked in to a
750 # VariantDir, or a Scanner threw something). Arrange to 780 # VariantDir, or a Scanner threw something). Arrange to
751 # raise the exception when the Task is "executed." 781 # raise the exception when the Task is "executed."
752 self.ready_exc = sys.exc_info() 782 self.ready_exc = sys.exc_info()
753 if S: S.problem = S.problem + 1 783 if S: S.problem = S.problem + 1
754 if T: T.write(self.trace_message(' exception %s while scan ning children.\n' % e)) 784 if T: T.write(self.trace_message(' exception %s while scan ning children.\n' % e))
755 return node 785 return node
756 786
757 children_not_visited = [] 787 children_not_visited = []
758 children_pending = set() 788 children_pending = set()
759 children_not_ready = [] 789 children_not_ready = []
760 children_failed = False 790 children_failed = False
761 791
762 for child in chain(children,node.prerequisites): 792 for child in chain(children, executor.get_all_prerequisites()):
763 childstate = child.get_state() 793 childstate = child.get_state()
764 794
765 if T: T.write(self.trace_message(' ' + self.trace_node(chi ld))) 795 if T: T.write(self.trace_message(' ' + self.trace_node(chi ld)))
766 796
767 if childstate == NODE_NO_STATE: 797 if childstate == NODE_NO_STATE:
768 children_not_visited.append(child) 798 children_not_visited.append(child)
769 elif childstate == NODE_PENDING: 799 elif childstate == NODE_PENDING:
770 children_pending.add(child) 800 children_pending.add(child)
771 elif childstate == NODE_FAILED: 801 elif childstate == NODE_FAILED:
772 children_failed = True 802 children_failed = True
(...skipping 23 matching lines...) Expand all
796 # target, the next time occurs through the other target. 826 # target, the next time occurs through the other target.
797 # 827 #
798 # Note that we can only have failed_children if the 828 # Note that we can only have failed_children if the
799 # --keep-going flag was used, because without it the build 829 # --keep-going flag was used, because without it the build
800 # will stop before diving in the other branch. 830 # will stop before diving in the other branch.
801 # 831 #
802 # Note that even if one of the children fails, we still 832 # Note that even if one of the children fails, we still
803 # added the other children to the list of candidate nodes 833 # added the other children to the list of candidate nodes
804 # to keep on building (--keep-going). 834 # to keep on building (--keep-going).
805 if children_failed: 835 if children_failed:
806 node.set_state(NODE_FAILED) 836 for n in executor.get_action_targets():
837 n.set_state(NODE_FAILED)
807 838
808 if S: S.child_failed = S.child_failed + 1 839 if S: S.child_failed = S.child_failed + 1
809 if T: T.write(self.trace_message('****** %s\n' % self.trace_node (node))) 840 if T: T.write(self.trace_message('****** %s\n' % self.trace_node (node)))
810 continue 841 continue
811 842
812 if children_not_ready: 843 if children_not_ready:
813 for child in children_not_ready: 844 for child in children_not_ready:
814 # We're waiting on one or more derived targets 845 # We're waiting on one or more derived targets
815 # that have not yet finished building. 846 # that have not yet finished building.
816 if S: S.not_built = S.not_built + 1 847 if S: S.not_built = S.not_built + 1
(...skipping 10 matching lines...) Expand all
827 for pc in children_pending: 858 for pc in children_pending:
828 T.write(self.trace_message(' adding %s to the pend ing children set\n' % 859 T.write(self.trace_message(' adding %s to the pend ing children set\n' %
829 self.trace_node(pc))) 860 self.trace_node(pc)))
830 self.pending_children = self.pending_children | children_pending 861 self.pending_children = self.pending_children | children_pending
831 862
832 continue 863 continue
833 864
834 # Skip this node if it has side-effects that are 865 # Skip this node if it has side-effects that are
835 # currently being built: 866 # currently being built:
836 wait_side_effects = False 867 wait_side_effects = False
837 for se in node.side_effects: 868 for se in executor.get_action_side_effects():
838 if se.get_state() == NODE_EXECUTING: 869 if se.get_state() == NODE_EXECUTING:
839 se.add_to_waiting_s_e(node) 870 se.add_to_waiting_s_e(node)
840 wait_side_effects = True 871 wait_side_effects = True
841 872
842 if wait_side_effects: 873 if wait_side_effects:
843 if S: S.side_effects = S.side_effects + 1 874 if S: S.side_effects = S.side_effects + 1
844 continue 875 continue
845 876
846 # The default when we've gotten through all of the checks above: 877 # The default when we've gotten through all of the checks above:
847 # this node is ready to be built. 878 # this node is ready to be built.
(...skipping 18 matching lines...) Expand all
866 Returns the next task to be executed. 897 Returns the next task to be executed.
867 898
868 This simply asks for the next Node to be evaluated, and then wraps 899 This simply asks for the next Node to be evaluated, and then wraps
869 it in the specific Task subclass with which we were initialized. 900 it in the specific Task subclass with which we were initialized.
870 """ 901 """
871 node = self._find_next_ready_node() 902 node = self._find_next_ready_node()
872 903
873 if node is None: 904 if node is None:
874 return None 905 return None
875 906
876 tlist = node.get_executor().targets 907 tlist = node.get_executor().get_all_targets()
877 908
878 task = self.tasker(self, tlist, node in self.original_top, node) 909 task = self.tasker(self, tlist, node in self.original_top, node)
879 try: 910 try:
880 task.make_ready() 911 task.make_ready()
881 except: 912 except:
882 # We had a problem just trying to get this task ready (like 913 # We had a problem just trying to get this task ready (like
883 # a child couldn't be linked in to a VariantDir when deciding 914 # a child couldn't be linked in to a VariantDir when deciding
884 # whether this node is current). Arrange to raise the 915 # whether this node is current). Arrange to raise the
885 # exception when the Task is "executed." 916 # exception when the Task is "executed."
886 self.ready_exc = sys.exc_info() 917 self.ready_exc = sys.exc_info()
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 desc = 'Found dependency cycle(s):\n' 1007 desc = 'Found dependency cycle(s):\n'
977 for node, cycle in nclist: 1008 for node, cycle in nclist:
978 if cycle: 1009 if cycle:
979 desc = desc + " " + string.join(map(str, cycle), " -> ") + "\n" 1010 desc = desc + " " + string.join(map(str, cycle), " -> ") + "\n"
980 else: 1011 else:
981 desc = desc + \ 1012 desc = desc + \
982 " Internal Error: no cycle found for node %s (%s) in state %s\n" % \ 1013 " Internal Error: no cycle found for node %s (%s) in state %s\n" % \
983 (node, repr(node), StateString[node.get_state()]) 1014 (node, repr(node), StateString[node.get_state()])
984 1015
985 raise SCons.Errors.UserError, desc 1016 raise SCons.Errors.UserError, desc
OLDNEW
« no previous file with comments | « third_party/scons/scons-local/SCons/Subst.py ('k') | third_party/scons/scons-local/SCons/Tool/386asm.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698