summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Taskmaster.py
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-10-24 14:18:02 (GMT)
committerSteven Knight <knight@baldmt.com>2001-10-24 14:18:02 (GMT)
commit6a98a941a75eab2e4c22fa3e19cb973046f613b6 (patch)
treefbedd2a2caa8c7d0e4a1e4b774adc6e1b1ed6d8e /src/engine/SCons/Taskmaster.py
parent908b74a3a3ecba5eccc6fd1f844505050d9dad2f (diff)
downloadSCons-6a98a941a75eab2e4c22fa3e19cb973046f613b6.zip
SCons-6a98a941a75eab2e4c22fa3e19cb973046f613b6.tar.gz
SCons-6a98a941a75eab2e4c22fa3e19cb973046f613b6.tar.bz2
Add -k support and more
Diffstat (limited to 'src/engine/SCons/Taskmaster.py')
-rw-r--r--src/engine/SCons/Taskmaster.py89
1 files changed, 68 insertions, 21 deletions
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py
index 3fd787e..3b4ee85 100644
--- a/src/engine/SCons/Taskmaster.py
+++ b/src/engine/SCons/Taskmaster.py
@@ -46,6 +46,9 @@ class Task:
def set_state(self, state):
return self.target.set_state(state)
+
+ def get_target(self):
+ return self.target
def current(node):
"""Default SCons build engine is-it-current function.
@@ -64,38 +67,55 @@ class Taskmaster:
the base class method, so this class can do it's thing.
"""
- def __init__(self, targets=[], tasker=Task, current=current):
+ def __init__(self,
+ targets=[],
+ tasker=Task,
+ current=current,
+ ignore_errors=0,
+ keep_going_on_error=0):
self.walkers = map(SCons.Node.Walker, targets)
self.tasker = tasker
self.current = current
self.targets = targets
+ self.ready = []
+ self.pending = 0
+ self.ignore_errors = ignore_errors
+ self.keep_going_on_error = keep_going_on_error
+ self._find_next_ready_node()
+
def next_task(self):
+ if self.ready:
+ n = self.ready.pop()
+ n.set_state(SCons.Node.executing)
+ if not self.ready:
+ self._find_next_ready_node()
+
+ return self.tasker(n)
+ else:
+ return None
+
+ def _find_next_ready_node(self):
+ """Find the next node that is ready to be built"""
while self.walkers:
n = self.walkers[0].next()
if n == None:
self.walkers.pop(0)
elif n.get_state() == SCons.Node.up_to_date:
self.up_to_date(n, self.walkers[0].is_done())
- elif n.get_state() == SCons.Node.failed:
- # XXX do the right thing here
- pass
- elif n.get_state() == SCons.Node.executing:
- # XXX do the right thing here
- pass
- elif n.get_state() == SCons.Node.executed:
- # skip this node because it has already been executed
- pass
- elif self.current(n):
- n.set_state(SCons.Node.up_to_date)
- self.up_to_date(n, self.walkers[0].is_done())
- else:
- n.set_state(SCons.Node.executing)
- return self.tasker(n)
- return None
-
+ elif n.get_state() == None:
+ if not n.children_are_executed():
+ n.set_state(SCons.Node.pending)
+ self.pending = self.pending + 1
+ elif self.current(n):
+ n.set_state(SCons.Node.up_to_date)
+ self.up_to_date(n, self.walkers[0].is_done())
+ else:
+ self.ready.append(n)
+ return
+
def is_blocked(self):
- return 0
+ return not self.ready and self.pending
def up_to_date(self, node):
pass
@@ -103,6 +123,33 @@ class Taskmaster:
def executed(self, task):
task.set_state(SCons.Node.executed)
+ # add all the pending parents that are now executable to the 'ready'
+ # queue:
+ n = task.get_target()
+ ready = filter(lambda x: (x.get_state() == SCons.Node.pending
+ and x.children_are_executed()),
+ n.get_parents())
+ self.ready.extend(ready)
+ self.pending = self.pending - len(ready)
+
def failed(self, task):
- self.walkers = []
- task.set_state(SCons.Node.failed)
+ if self.ignore_errors:
+ self.executed(task)
+ else:
+ if self.keep_going_on_error:
+ # mark all the depants of this node as failed:
+ def get_parents(node): return node.get_parents()
+ walker = SCons.Node.Walker(task.get_target(), get_parents)
+ while 1:
+ node = walker.next()
+ if node == None: break
+ if node.get_state() == SCons.Node.pending:
+ self.pending = self.pending - 1
+ node.set_state(SCons.Node.failed)
+ else:
+ # terminate the build:
+ self.walkers = []
+ self.pending = 0
+ self.ready = []
+
+ task.set_state(SCons.Node.failed)