Fix subtle problems in end cases with using multiple scanners on a Node.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 20 Mar 2002 16:45:30 +0000 (16:45 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 20 Mar 2002 16:45:30 +0000 (16:45 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@298 fdb21ef1-2011-0410-befe-b5e4ea1792b1

12 files changed:
src/engine/SCons/Builder.py
src/engine/SCons/BuilderTests.py
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
src/engine/SCons/Node/NodeTests.py
src/engine/SCons/Node/__init__.py
src/engine/SCons/Script/__init__.py
src/engine/SCons/Sig/SigTests.py
src/engine/SCons/Sig/__init__.py
src/engine/SCons/Taskmaster.py
src/engine/SCons/TaskmasterTests.py
test/BuildDir.py

index efef969c347e4c3122e9173cd0dc5608c5ffea7d..a62d91d62ee7739c47c68dddeee471dc9b802d10 100644 (file)
@@ -63,6 +63,13 @@ def _init_nodes(builder, env, tlist, slist):
     """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)
@@ -70,12 +77,8 @@ def _init_nodes(builder, env, tlist, slist):
         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)
 
 
 
index ab633179b453de6118141a61bfadf3d632813b05..f853bc261969ec5bf31838fb0525e64a187b436b 100644 (file)
@@ -103,6 +103,8 @@ class BuilderTestCase(unittest.TestCase):
                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");
@@ -111,7 +113,7 @@ class BuilderTestCase(unittest.TestCase):
        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'
@@ -662,9 +664,9 @@ class BuilderTestCase(unittest.TestCase):
                 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
@@ -677,7 +679,7 @@ class BuilderTestCase(unittest.TestCase):
                                          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):
@@ -690,9 +692,9 @@ class BuilderTestCase(unittest.TestCase):
                  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_')
index f7e1f44884d31313636aecd869b2678c72b8c5bf..362559c444f92f737098baf4ef35cc62975c4e8e 100644 (file)
@@ -417,7 +417,7 @@ class Dir(Entry):
         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)
@@ -446,7 +446,7 @@ class Dir(Entry):
         """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
@@ -523,13 +523,13 @@ class File(Entry):
         .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:
@@ -542,6 +542,9 @@ class File(Entry):
                 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.
index b132b1232ca302908777ff530dff9029fd21a093..e9e24eccab3e2f97f268f36e0017dd7132302f70 100644 (file)
@@ -257,13 +257,13 @@ class FSTestCase(unittest.TestCase):
             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'),
@@ -383,16 +383,23 @@ class FSTestCase(unittest.TestCase):
         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"))
@@ -468,6 +475,9 @@ class FSTestCase(unittest.TestCase):
 
         #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):
index 574e9cd14b47e7df7eb7a0c9ba9525e9bef631df..ec506aafda897be355bfe163f69813646e729dfd 100644 (file)
@@ -416,57 +416,126 @@ class NodeTestCase(unittest.TestCase):
             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
@@ -558,55 +627,59 @@ class NodeTestCase(unittest.TestCase):
         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_')
index ef12c6e2adecb54b2305e29ed1880476ef0c0e39..e8d45e182839b5b52be3e728546ce129345e5ba2 100644 (file)
@@ -62,10 +62,11 @@ class Node:
         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
@@ -96,28 +97,11 @@ class Node:
 
         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
@@ -144,12 +128,21 @@ class Node:
         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:
@@ -222,17 +215,22 @@ class Node:
         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()
@@ -246,14 +244,14 @@ class Node:
     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
 
index 5472e1091d2bb4293722bf9b73bec0a085814ffa..055dbbc53a1e4642f40f5ee615d9e3f441363e70 100644 (file)
@@ -149,7 +149,7 @@ exit_status = 0 # exit status, assume success by default
 
 # 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
index fba383e60d3d9cf796f322b56d128d13fccb28c1..71d48ce588e10ed825fd64579e44f20a3e476f8c 100644 (file)
@@ -81,11 +81,11 @@ class DummyNode:
             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):
@@ -296,9 +296,9 @@ class CalcTestCase(unittest.TestCase):
                 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
index 146c7c11bf4c3292d67601a2f74f9b4584311caa..7e93123e932d11fdfd87cffb5bcbc3dec2c57e7c 100644 (file)
@@ -207,7 +207,7 @@ class Calculator:
         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 = []
index 0106f46378b17594b6a64a56cb6e6560927faf81..404355eca1a7fdd15f15a904582a8236d6e6e210 100644 (file)
@@ -54,10 +54,11 @@ class Task:
     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:
@@ -89,8 +90,9 @@ class Task:
             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):
@@ -171,9 +173,12 @@ class Taskmaster:
                 # (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:
@@ -201,8 +206,12 @@ class Taskmaster:
                 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
index 32a111010dbce54824e0e06802455924677fa915..b6fa68568e917feffbef6d5faef3f2c3c3d5cefd 100644 (file)
@@ -39,6 +39,8 @@ class Node:
         self.name = name
         self.kids = kids
         self.scans = scans
+        self.scanned = {}
+        self.src_scanners = {}
         self.builder = Node.build
         self.bsig = None
         self.csig = None
@@ -55,16 +57,28 @@ class Node:
     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
@@ -84,11 +98,11 @@ class Node:
     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
@@ -234,13 +248,16 @@ class TaskmasterTestCase(unittest.TestCase):
         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
 
@@ -345,13 +362,13 @@ class TaskmasterTestCase(unittest.TestCase):
     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
 
index a71d4ddab636f642d42e2109614db70657f98f95..893731cbc0d9c837b123c070bffe1b896c6d54a5 100644 (file)
@@ -52,7 +52,7 @@ BuildDir('build/var1', src)
 BuildDir(var2, src)
 BuildDir(var3, src, duplicate=0)
 
-env = Environment()
+env = Environment(CPPPATH='#src')
 SConscript('build/var1/SConscript', "env")
 SConscript('build/var2/SConscript', "env")