summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2002-03-19 16:01:59 (GMT)
committerSteven Knight <knight@baldmt.com>2002-03-19 16:01:59 (GMT)
commit70d4bf67b7fefce28d76d451c959ba633720214e (patch)
tree17c6cc06738b1ab2d0c91828c3138a263ce007b0
parent1d0c4df93b2120fe494da4a2e1f40b20fe0245be (diff)
downloadSCons-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__.py18
-rw-r--r--src/engine/SCons/Sig/__init__.py2
-rw-r--r--src/engine/SCons/Taskmaster.py68
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