diff options
author | Steven Knight <knight@baldmt.com> | 2002-03-19 16:01:59 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2002-03-19 16:01:59 (GMT) |
commit | 70d4bf67b7fefce28d76d451c959ba633720214e (patch) | |
tree | 17c6cc06738b1ab2d0c91828c3138a263ce007b0 | |
parent | 1d0c4df93b2120fe494da4a2e1f40b20fe0245be (diff) | |
download | SCons-70d4bf67b7fefce28d76d451c959ba633720214e.zip SCons-70d4bf67b7fefce28d76d451c959ba633720214e.tar.gz SCons-70d4bf67b7fefce28d76d451c959ba633720214e.tar.bz2 |
Enhance the Walker to call a third supplied function to actually work on a Node, and pass the parent Node to both the out-of-date-check function and the work function. Refactor Taskmaster to use the new Walker function.
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 18 | ||||
-rw-r--r-- | src/engine/SCons/Sig/__init__.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/Taskmaster.py | 68 |
3 files changed, 52 insertions, 36 deletions
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 4c54c53..ef12c6e 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -253,8 +253,9 @@ class Node: self.children(), 1) -def get_children(node): return node.children() +def get_children(node, parent): return node.children() def ignore_cycle(node, stack): pass +def do_nothing(node, parent): pass class Walker: """An iterator for walking a Node tree. @@ -270,10 +271,13 @@ class Walker: This class does not get caught in node cycles caused, for example, by C header file include loops. """ - def __init__(self, node, kids_func=get_children, cycle_func=ignore_cycle): + def __init__(self, node, kids_func=get_children, + cycle_func=ignore_cycle, + eval_func=do_nothing): self.kids_func = kids_func self.cycle_func = cycle_func - node.wkids = copy.copy(kids_func(node)) + self.eval_func = eval_func + node.wkids = copy.copy(kids_func(node, None)) self.stack = [node] self.history = {} # used to efficiently detect and avoid cycles self.history[node] = None @@ -293,12 +297,18 @@ class Walker: if self.history.has_key(node): self.cycle_func(node, self.stack) else: - node.wkids = copy.copy(self.kids_func(node)) + node.wkids = copy.copy(self.kids_func(node, self.stack[-1])) self.stack.append(node) self.history[node] = None else: node = self.stack.pop() del self.history[node] + if node: + if self.stack: + parent = self.stack[-1] + else: + parent = None + self.eval_func(node, parent) return node def is_done(self): diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index cedeb94..146c7c1 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -204,7 +204,7 @@ class Calculator: # derived files, because calling get_signature() on the # derived nodes will in turn call bsig() again and do that # for us. Hence: - def walk_non_derived(n, myself=node): + def walk_non_derived(n, parent, myself=node): if not n.builder or n is myself: return filter(lambda x, i=myself.ignore: x not in i, n.all_children()) diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index cdee378..0106f46 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -114,7 +114,7 @@ class Task: """ nodes = {} for t in self.targets: - def get_parents(node): return node.get_parents() + def get_parents(node, parent): return node.get_parents() walker = SCons.Node.Walker(t, get_parents) while 1: n = walker.next() @@ -165,7 +165,7 @@ class Taskmaster: def __init__(self, targets=[], tasker=Task, calc=Calc()): - def out_of_date(node): + def out_of_date(node, parent): if node.get_state(): # The state is set, so someone has already been here # (finished or currently executing). Find another one. @@ -182,8 +182,39 @@ class Taskmaster: desc = "Dependency cycle: " + string.join(map(str, nodes), " -> ") raise SCons.Errors.UserError, desc - #XXX In Python 2.2 we can get rid of f1 and f2: - self.walkers = map(lambda x, f1=out_of_date, f2=cycle_error: SCons.Node.Walker(x, f1, f2), + def eval_node(node, parent, self=self): + if node.get_state(): + # The state is set, so someone has already been here + # (finished or currently executing). Find another one. + return + if not node.builder: + # It's a source file, we don't need to build it, + # but mark it as "up to date" so targets won't + # wait for it. + node.set_state(SCons.Node.up_to_date) + # set the signature for non-derived files + # here so they don't get recalculated over + # and over again: + node.set_csig(self.calc.csig(node)) + return + try: + tlist = node.builder.targets(node) + except AttributeError: + tlist = [ node ] + task = self.tasker(self, tlist, self.walkers[0].is_done()) + if not tlist[0].children_are_executed(): + for t in tlist: + t.set_state(SCons.Node.pending) + t.task = task + self.pending = self.pending + 1 + return + task.make_ready() + + #XXX In Python 2.2 we can get rid of f1, f2 and f3: + self.walkers = map(lambda x, f1=out_of_date, + f2=cycle_error, + f3=eval_node: + SCons.Node.Walker(x, f1, f2, f3), targets) self.tasker = tasker self.calc = calc @@ -209,33 +240,8 @@ class Taskmaster: if n == None: self.walkers.pop(0) continue - if n.get_state(): - # The state is set, so someone has already been here - # (finished or currently executing). Find another one. - continue - if not n.builder: - # It's a source file, we don't need to build it, - # but mark it as "up to date" so targets won't - # wait for it. - n.set_state(SCons.Node.up_to_date) - # set the signature for non-derived files - # here so they don't get recalculated over - # and over again: - n.set_csig(self.calc.csig(n)) - continue - try: - tlist = n.builder.targets(n) - except AttributeError: - tlist = [ n ] - task = self.tasker(self, tlist, self.walkers[0].is_done()) - if not tlist[0].children_are_executed(): - for t in tlist: - t.set_state(SCons.Node.pending) - t.task = task - self.pending = self.pending + 1 - continue - task.make_ready() - return + if self.ready: + return def is_blocked(self): return not self.ready and self.pending |