"""Initialize lists of target and source nodes with all of
the proper Builder information.
"""
+ src_scanner = None
+ if slist:
+ src_key = slist[0].scanner_key() # the file suffix
+ src_scanner = env.get_scanner(src_key)
+ if src_scanner:
+ src_scanner = src_scanner.instance(env)
+
for t in tlist:
t.cwd = SCons.Node.FS.default_fs.getcwd() # XXX
t.builder_set(builder)
t.add_source(slist)
if builder.scanner:
t.scanner_set(builder.scanner.instance(env))
-
- for s in slist:
- s.env_set(env, 1)
- scanner = env.get_scanner(os.path.splitext(s.name)[1])
- if scanner:
- s.scanner_set(scanner.instance(env))
+ if src_scanner:
+ t.src_scanner_set(src_key, src_scanner)
self.env = env
def add_source(self, source):
self.sources.extend(source)
+ def scanner_key(self):
+ return self.name
builder = SCons.Builder.Builder(name="builder", action="foo", node_factory=Node)
n1 = Node("n1");
assert n1.env == env
assert n1.builder == builder
assert n1.sources == [n2]
- assert n2.env == env
+ assert not hasattr(n2, 'env')
target = builder(env, target = 'n3', source = 'n4')
assert target.name == 'n3'
instanced = 1
return self
scn = TestScanner()
- builder=SCons.Builder.Builder(name = "builder", scanner=scn)
+ builder = SCons.Builder.Builder(name = "builder", scanner=scn)
tgt = builder(env, target='foo', source='bar')
- assert scn in tgt.scanners, tgt.scanners
+ assert tgt.scanner == scn, tgt.scanner
assert instanced
instanced = None
src_builder = builder1,
scanner = scn)
tgt = builder2(env, target='baz', source='test.bar test2.foo test3.txt')
- assert scn in tgt.scanners, tgt.scanners
+ assert tgt.scanner == scn, tgt.scanner
assert instanced
def test_src_scanner(slf):
return self
env_scanner = TestScanner()
builder = SCons.Builder.Builder(name = "builder", action='action')
- tgt = builder(env, target='foo', source='bar')
- assert not tgt.scanners == [ env_scanner ]
- assert tgt.sources[0].scanners == [ env_scanner ]
+ tgt = builder(env, target='foo.x', source='bar')
+ assert tgt.scanner != env_scanner, tgt.scanner
+ assert tgt.src_scanners[''] == env_scanner, tgt.src_scanners
if __name__ == "__main__":
suite = unittest.makeSuite(BuilderTestCase, 'test_')
else:
return self.entries['..'].root()
- def children(self):
+ def children(self, scanner):
#XXX --random: randomize "dependencies?"
keys = filter(lambda k: k != '.' and k != '..', self.entries.keys())
kids = map(lambda x, s=self: s.entries[x], keys)
"""If all of our children were up-to-date, then this
directory was up-to-date, too."""
state = 0
- for kid in self.children():
+ for kid in self.children(None):
s = kid.get_state()
if s and (not state or s > state):
state = s
.sconsign entry."""
return self.dir.sconsign().get(self.name)
- def scan(self):
- if self.env:
- for scn in self.scanners:
- if not self.scanned.has_key(scn):
- deps = scn.scan(self, self.env)
- self.add_implicit(deps,scn)
- self.scanned[scn] = 1
+ def scan(self, scanner = None):
+ if not scanner:
+ scanner = self.scanner
+ if scanner and not self.scanned.has_key(scanner):
+ deps = scanner.scan(self, self.env)
+ self.add_implicit(deps, scanner)
+ self.scanned[scanner] = 1
def exists(self):
if self.duplicate and not self.created:
file_link(self.srcpath, self.path)
return Entry.exists(self)
+ def scanner_key(self):
+ return os.path.splitext(self.name)[1]
+
def __createDir(self):
# ensure that the directories for this node are
# created.
fs.Dir(string.join(['ddd', 'd1'], sep))
fs.Dir(string.join(['ddd', 'd1', 'f4'], sep))
fs.Dir(string.join(['ddd', 'd1', 'f5'], sep))
- kids = map(lambda x: x.path, dir.children())
+ kids = map(lambda x: x.path, dir.children(None))
kids.sort()
assert kids == [os.path.join('ddd', 'd1'),
os.path.join('ddd', 'f1'),
os.path.join('ddd', 'f2'),
os.path.join('ddd', 'f3')]
- kids = map(lambda x: x.path_, dir.children())
+ kids = map(lambda x: x.path_, dir.children(None))
kids.sort()
assert kids == [os.path.join('ddd', 'd1', ''),
os.path.join('ddd', 'f1'),
match(e13.path, "subdir/subdir/e13")
# Test scanning
- scn = Scanner()
- f1.scanners = [ scn ]
- f1.scan()
- assert f1.implicit[scn][0].path_ == os.path.join("d1", "f1")
- del f1.implicit[scn]
- f1.scan()
+ scn1 = Scanner()
+ f1.scan(scn1)
+ assert f1.implicit[scn1][0].path_ == os.path.join("d1", "f1")
+ del f1.implicit[scn1]
+ f1.scan(scn1)
assert len(f1.implicit) == 0, f1.implicit
- del f1.scanned[scn]
- f1.scan()
- assert f1.implicit[scn][0].path_ == os.path.join("d1", "f1")
+ del f1.scanned[scn1]
+ f1.scan(scn1)
+ assert f1.implicit[scn1][0].path_ == os.path.join("d1", "f1")
+
+ # Test multiple scanners
+ scn2 = Scanner()
+ f2 = fs.File("f2")
+ f2.scan(scn1)
+ f2.scan(scn2)
+ assert f2.implicit[scn1][0].path_ == 'subdir/f2', f2.implicit[scn1][0].path_
+ assert f2.implicit[scn2][0].path_ == 'subdir/f2', f2.implicit[scn2][0].path_
# Test building a file whose directory is not there yet...
f1 = fs.File(test.workpath("foo/bar/baz/ack"))
#XXX test get_prevsiginfo()
+ assert fs.File('foo.x').scanner_key() == '.x'
+ assert fs.File('foo.xyz').scanner_key() == '.xyz'
+
class find_fileTestCase(unittest.TestCase):
def runTest(self):
pass
ds=DummyScanner()
node = SCons.Node.Node()
- assert node.scanners == [], node.scanners
+ assert node.scanner == None, node.scanner
node.scanner_set(ds)
- assert node.scanners == [ ds ], node.scanners
- node.scan()
+ assert node.scanner == ds, node.scanner
+ node.scan(ds)
assert node.scanned[ds] == 1, node.scanned
+ def test_src_scanner_set(self):
+ """Test setting source-file Scanners"""
+ class DummyScanner:
+ pass
+ ds1=DummyScanner()
+ ds2=DummyScanner()
+ node = SCons.Node.Node()
+ assert node.src_scanners == {}, node.src_scanners
+ node.src_scanner_set('a', ds1)
+ assert node.src_scanners['a'] == ds1, node.src_scanners
+ node.src_scanner_set('b', ds2)
+ assert node.src_scanners['b'] == ds2, node.src_scanners
+
+ def test_src_scanner_set(self):
+ """Test setting source-file Scanners"""
+ class DummyScanner:
+ pass
+ ds1=DummyScanner()
+ ds2=DummyScanner()
+ node = SCons.Node.Node()
+ node.src_scanner_set('a', ds1)
+ node.src_scanner_set('b', ds2)
+ s = node.src_scanner_get(None)
+ assert s == None, s
+ s = node.src_scanner_get('a')
+ assert s == ds1, s
+ s = node.src_scanner_get('b')
+ assert s == ds2, s
+ s = node.src_scanner_get('c')
+ assert s == None, s
+
+ def test_scanner_key(self):
+ """Test that a scanner_key() method exists"""
+ assert SCons.Node.Node().scanner_key() == None
+
def test_children(self):
"""Test fetching the non-ignored "children" of a Node.
"""
node = SCons.Node.Node()
- one = SCons.Node.Node()
- two = SCons.Node.Node()
- three = SCons.Node.Node()
- four = SCons.Node.Node()
- five = SCons.Node.Node()
- six = SCons.Node.Node()
-
- node.add_source([one, two, three])
- node.add_dependency([four, five, six])
- node.add_ignore([two, five])
- kids = node.children()
- assert len(kids) == 4
- assert one in kids
- assert not two in kids
- assert three in kids
- assert four in kids
- assert not five in kids
- assert six in kids
+ n1 = SCons.Node.Node()
+ n2 = SCons.Node.Node()
+ n3 = SCons.Node.Node()
+ n4 = SCons.Node.Node()
+ n5 = SCons.Node.Node()
+ n6 = SCons.Node.Node()
+ n7 = SCons.Node.Node()
+ n8 = SCons.Node.Node()
+ n9 = SCons.Node.Node()
+ n10 = SCons.Node.Node()
+ n11 = SCons.Node.Node()
+ n12 = SCons.Node.Node()
+
+ node.add_source([n1, n2, n3])
+ node.add_dependency([n4, n5, n6])
+ node.add_implicit([n7, n8, n9], 'key1')
+ node.add_implicit([n10, n11, n12], 'key2')
+ node.add_ignore([n2, n5, n8, n11])
+
+ kids = node.children(None)
+ for kid in [n1, n3, n4, n6, n7, n9, n10, n12]:
+ assert kid in kids, kid
+ for kid in [n2, n5, n8, n11]:
+ assert not kid in kids, kid
+
+ kids = node.children('key1')
+ for kid in [n1, n3, n4, n6, n7, n9]:
+ assert kid in kids, kid
+ for kid in [n2, n5, n8, n10, n11, n12]:
+ assert not kid in kids, kid
+
+ kids = node.children('key2')
+ for kid in [n1, n3, n4, n6, n10, n12]:
+ assert kid in kids, kid
+ for kid in [n2, n5, n7, n8, n9, n11]:
+ assert not kid in kids, kid
def test_all_children(self):
"""Test fetching all the "children" of a Node.
"""
node = SCons.Node.Node()
- one = SCons.Node.Node()
- two = SCons.Node.Node()
- three = SCons.Node.Node()
- four = SCons.Node.Node()
- five = SCons.Node.Node()
- six = SCons.Node.Node()
-
- node.add_source([one, two, three])
- node.add_dependency([four, five, six])
- node.add_ignore([two, five])
- kids = node.all_children()
- assert len(kids) == 6
- assert one in kids
- assert two in kids
- assert three in kids
- assert four in kids
- assert five in kids
- assert six in kids
+ n1 = SCons.Node.Node()
+ n2 = SCons.Node.Node()
+ n3 = SCons.Node.Node()
+ n4 = SCons.Node.Node()
+ n5 = SCons.Node.Node()
+ n6 = SCons.Node.Node()
+ n7 = SCons.Node.Node()
+ n8 = SCons.Node.Node()
+ n9 = SCons.Node.Node()
+ n10 = SCons.Node.Node()
+ n11 = SCons.Node.Node()
+ n12 = SCons.Node.Node()
+
+ node.add_source([n1, n2, n3])
+ node.add_dependency([n4, n5, n6])
+ node.add_implicit([n7, n8, n9], 'key1')
+ node.add_implicit([n10, n11, n12], 'key2')
+ node.add_ignore([n2, n5, n8, n11])
+
+ kids = node.all_children(None)
+ for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12]:
+ assert kid in kids
+
+ kids = node.all_children('key1')
+ for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9]:
+ assert kid in kids
+ for kid in [n10, n11, n12]:
+ assert not kid in kids
+
+ kids = node.all_children('key2')
+ for kid in [n1, n2, n3, n4, n5, n6, n10, n11, n12]:
+ assert kid in kids
+ for kid in [n7, n8, n9]:
+ assert not kid in kids
def test_state(self):
"""Test setting and getting the state of a node
n4.add_source([n3])
n3.add_source([n1, n2])
- assert not n4.children_are_executed()
- assert not n3.children_are_executed()
- assert n2.children_are_executed()
- assert n1.children_are_executed()
+ assert not n4.children_are_executed(None)
+ assert not n3.children_are_executed(None)
+ assert n2.children_are_executed(None)
+ assert n1.children_are_executed(None)
n1.set_state(SCons.Node.executed)
- assert not n4.children_are_executed()
- assert not n3.children_are_executed()
- assert n2.children_are_executed()
- assert n1.children_are_executed()
+ assert not n4.children_are_executed(None)
+ assert not n3.children_are_executed(None)
+ assert n2.children_are_executed(None)
+ assert n1.children_are_executed(None)
n2.set_state(SCons.Node.executed)
- assert not n4.children_are_executed()
- assert n3.children_are_executed()
- assert n2.children_are_executed()
- assert n1.children_are_executed()
+ assert not n4.children_are_executed(None)
+ assert n3.children_are_executed(None)
+ assert n2.children_are_executed(None)
+ assert n1.children_are_executed(None)
n3.set_state(SCons.Node.executed)
- assert n4.children_are_executed()
- assert n3.children_are_executed()
- assert n2.children_are_executed()
- assert n1.children_are_executed()
+ assert n4.children_are_executed(None)
+ assert n3.children_are_executed(None)
+ assert n2.children_are_executed(None)
+ assert n1.children_are_executed(None)
def test_rescan(self):
- """Test that built nodes are rescanned."""
+ """Test that built node implicit dependencies are cleared
+ to be rescanned."""
class DummyScanner:
pass
class TestNode(SCons.Node.Node):
- def scan(self):
- for scn in self.scanners:
- if not self.scanned.has_key(scn):
- n=SCons.Node.Node()
- n.scanner_set(scn)
- self.add_implicit([ n ], scn)
- self.scanned[scn] = 1
+ def scan(self, scanner):
+ if not self.scanned.has_key(scanner):
+ n=SCons.Node.Node()
+ n.scanner_set(scanner)
+ self.add_implicit([ n ], scanner)
+ self.scanned[scanner] = 1
tn=TestNode()
tn.builder_set(Builder())
tn.env_set(Environment())
ds = DummyScanner()
- tn.scanner_set(ds)
- tn.scan()
+ tn.scan(ds)
map(lambda x: x.scan(), tn.depends)
assert tn.scanned[ds]
assert len(tn.implicit[ds]) == 1, tn.implicit
+ tn.scan(ds)
+ assert tn.scanned[ds]
+ assert len(tn.implicit[ds]) == 1, tn.implicit
tn.build()
+ assert not tn.scanned.has_key(ds)
+ assert len(tn.implicit[ds]) == 1, tn.implicit
+ tn.scan(ds)
+ assert tn.scanned[ds]
assert len(tn.implicit[ds]) == 2, tn.implicit
- for dep in tn.implicit[ds]:
- assert dep.scanned[ds] == 1
if __name__ == "__main__":
suite = unittest.makeSuite(NodeTestCase, 'test_')
self.ignore = [] # dependencies to ignore
self.parents = {}
self.wkids = None # Kids yet to walk, when it's an array
- self.builder = None
- self.scanners = []
- self.scanned = {}
- self.env = None
+ self.builder = None
+ self.scanner = None # explicit scanner from this node's Builder
+ self.scanned = {} # cached scanned values
+ self.src_scanners = {} # scanners for this node's source files
+ self.env = None
self.state = None
self.bsig = None
self.csig = None
self.found_includes = {}
- # If we succesfully build a node, then we need to rescan for
+ # If we successfully build a node, then we need to rescan for
# implicit dependencies, since it might have changed on us.
+ self.scanned = {}
- # XXX Modify this so we only rescan using the scanner(s) relevant
- # to this build.
- for scn in self.scanners:
- try:
- del self.scanned[scn]
- except KeyError:
- pass
-
- self.scan()
-
- for scn in self.scanners:
- try:
- for dep in self.implicit[scn]:
- w=Walker(dep)
- while not w.is_done():
- w.next().scan()
- except KeyError:
- pass
- return stat
+ return stat
def builder_set(self, builder):
self.builder = builder
return Adapter(self)
def scanner_set(self, scanner):
- if not scanner in self.scanners:
- self.scanners.append(scanner)
+ self.scanner = scanner
- def scan(self):
- for scn in self.scanners:
- self.scanned[scn] = 1
+ def src_scanner_set(self, key, scanner):
+ self.src_scanners[key] = scanner
+
+ def src_scanner_get(self, key):
+ return self.src_scanners.get(key, None)
+
+ def scan(self, scanner = None):
+ if not scanner:
+ scanner = self.scanner
+ self.scanned[scanner] = 1
+
+ def scanner_key(self):
+ return None
def env_set(self, env, safe=0):
if safe and self.env:
if self.wkids != None:
self.wkids.append(wkid)
- def children(self):
+ def children(self, scanner):
"""Return a list of the node's direct children, minus those
that are ignored by this node."""
- return filter(lambda x, i=self.ignore: x not in i, self.all_children())
+ return filter(lambda x, i=self.ignore: x not in i,
+ self.all_children(scanner))
- def all_children(self):
+ def all_children(self, scanner):
"""Return a list of all the node's direct children."""
#XXX Need to remove duplicates from this
- return self.sources \
- + self.depends \
- + reduce(lambda x, y: x + y, self.implicit.values(), [])
+ if not self.implicit.has_key(scanner):
+ self.scan(scanner)
+ if scanner:
+ implicit = self.implicit[scanner]
+ else:
+ implicit = reduce(lambda x, y: x + y, self.implicit.values(), [])
+ return self.sources + self.depends + implicit
def get_parents(self):
return self.parents.keys()
def current(self):
return None
- def children_are_executed(self):
+ def children_are_executed(self, scanner):
return reduce(lambda x,y: ((y.get_state() == executed
or y.get_state() == up_to_date)
and x),
- self.children(),
+ self.children(scanner),
1)
-def get_children(node, parent): return node.children()
+def get_children(node, parent): return node.children(None)
def ignore_cycle(node, stack): pass
def do_nothing(node, parent): pass
# utility functions
-def get_children(node): return node.all_children()
+def get_children(node): return node.all_children(None)
def _scons_syntax_error(e):
"""Handle syntax errors. Print out a message and show where the error
self.exists_cache = self.exists()
return self.exists_cache
- def children(self):
+ def children(self, scanner):
return filter(lambda x, i=self.ignore: x not in i,
self.sources + self.depends)
- def all_children(self):
+ def all_children(self, scanner):
return self.sources + self.depends
def current(self):
self.ignore = []
self.builder = None
self.use_signature = 1
- def children(self):
+ def children(self, scanner):
return filter(lambda x, i=self.ignore: x not in i, self.kids)
- def all_children(self):
+ def all_children(self, scanner):
return self.kids
def exists(self):
return 1
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())
+ n.all_children(None))
return []
walker = SCons.Node.Walker(node, walk_non_derived)
sigs = []
Note that it's generally a good idea for sub-classes to call
these methods explicitly to update state, etc., rather than
roll their own interaction with Taskmaster from scratch."""
- def __init__(self, tm, targets, top):
+ def __init__(self, tm, targets, top, scanner = None):
self.tm = tm
self.targets = targets
self.top = top
+ self.scanner = scanner
def execute(self):
if self.targets[0].get_state() != SCons.Node.up_to_date:
parents = {}
for p in reduce(lambda x, y: x + y.get_parents(), self.targets, []):
parents[p] = 1
- ready = filter(lambda x: (x.get_state() == SCons.Node.pending
- and x.children_are_executed()),
+ ready = filter(lambda x, s=self.scanner:
+ (x.get_state() == SCons.Node.pending
+ and x.children_are_executed(s)),
parents.keys())
tasks = {}
for t in map(lambda r: r.task, ready):
# (finished or currently executing). Find another one.
return []
# Scan the file before fetching its children().
- node.scan()
+ if parent:
+ scanner = parent.src_scanner_get(node.scanner_key())
+ else:
+ scanner = None
return filter(lambda x: x.get_state() != SCons.Node.up_to_date,
- node.children())
+ node.children(scanner))
def cycle_error(node, stack):
if node.builder:
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():
+ if parent:
+ scanner = parent.src_scanner_get(node.scanner_key())
+ else:
+ scanner = None
+ task = self.tasker(self, tlist, self.walkers[0].is_done(), scanner)
+ if not tlist[0].children_are_executed(scanner):
for t in tlist:
t.set_state(SCons.Node.pending)
t.task = task
self.name = name
self.kids = kids
self.scans = scans
+ self.scanned = {}
+ self.src_scanners = {}
self.builder = Node.build
self.bsig = None
self.csig = None
def prepare(self):
pass
- def children(self):
- return self.kids
+ def children(self, scanner):
+ if not self.scanned.get(scanner, None):
+ self.scan(scanner)
+ self.scanned[scanner] = 1
+ return self.kids
- def scan(self):
+ def scan(self, scanner):
global scan_called
scan_called = scan_called + 1
self.kids = self.kids + self.scans
for scan in self.scans:
scan.parents.append(self)
self.scans = []
+
+ def src_scanner_set(self, key, scanner):
+ self.src_scanners[key] = scanner
+
+ def src_scanner_get(self, key):
+ return self.src_scanners.get(key, None)
+
+ def scanner_key(self):
+ return self.name
def get_parents(self):
return self.parents
def store_sigs(self):
pass
- def children_are_executed(self):
+ def children_are_executed(self, scanner):
return reduce(lambda x,y: ((y.get_state() == SCons.Node.executed
or y.get_state() == SCons.Node.up_to_date)
and x),
- self.children(),
+ self.children(scanner),
1)
def __str__(self):
return self.name
n3 = Node("n3", [n1], [n2])
tm = SCons.Taskmaster.Taskmaster([n3])
t = tm.next_task()
- assert t.get_target() == n1
+ target = t.get_target()
+ assert target == n1, target
t.executed()
t = tm.next_task()
- assert t.get_target() == n2
+ target = t.get_target()
+ assert target == n2, target
t.executed()
t = tm.next_task()
- assert t.get_target() == n3
+ target = t.get_target()
+ assert target == n3, target
t.executed()
assert tm.next_task() == None
def test_add_ready(self):
"""Test adding a task to the ready queue"""
class MyTask:
- def __init__(self, tm, tlist, top):
+ def __init__(self, tm, tlist, top, scanner):
pass
def make_ready(self):
pass
n1 = Node("n1")
tm = SCons.Taskmaster.Taskmaster([n1], tasker = MyTask)
- task = MyTask(tm, [], 0)
+ task = MyTask(tm, [], 0, None)
tm.add_ready(task)
assert tm.ready == [ task ], tm.ready
BuildDir(var2, src)
BuildDir(var3, src, duplicate=0)
-env = Environment()
+env = Environment(CPPPATH='#src')
SConscript('build/var1/SConscript', "env")
SConscript('build/var2/SConscript', "env")