More efficient Builder.src_suffixes() calculation and matching.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 2 Jun 2005 18:43:40 +0000 (18:43 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 2 Jun 2005 18:43:40 +0000 (18:43 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1305 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/Builder.py
src/engine/SCons/BuilderTests.py

index 6765364f9d2ef804ee99c54fd09a87923b0368d1..8abf25b5c27ac6affea035961842418f415914c5 100644 (file)
@@ -289,6 +289,8 @@ RELEASE 0.97 - XXX
     looks at the counts and profiles of the underlying function calls,
     not the Memoizer wrappers.
 
+  - Print various --debug= stats even if we exit early (e.g. using -h).
+
   From Wayne Lee:
 
   - Avoid "maximum recursion limit" errors when removing $(-$) pairs
index 57fbe3e1f29ccda69572d8baa23993c449b8d3d3..90839855448690976d9c0959ff6ae34c71fb4099 100644 (file)
@@ -383,7 +383,6 @@ class BuilderBase:
         self.prefix = prefix
         if SCons.Util.is_Dict(suffix):
             suffix = CallableSelector(suffix)
-        self.suffix = suffix
         self.env = env
         self.single_source = single_source
         if overrides.has_key('overrides'):
@@ -399,6 +398,7 @@ class BuilderBase:
             del overrides['scanner']
         self.overrides = overrides
 
+        self.set_suffix(suffix)
         self.set_src_suffix(src_suffix)
 
         self.target_factory = target_factory
@@ -614,24 +614,29 @@ class BuilderBase:
             prefix = prefix(env, sources)
         return env.subst(prefix)
 
+    def set_suffix(self, suffix):
+        if not callable(suffix):
+            suffix = self.adjust_suffix(suffix)
+        self.suffix = suffix
+
     def get_suffix(self, env, sources=[]):
         suffix = self.suffix
         if callable(suffix):
             suffix = suffix(env, sources)
-        else:
-            suffix = self.adjust_suffix(suffix)
         return env.subst(suffix)
 
     def src_suffixes(self, env):
-        return map(lambda x, s=self, e=env: e.subst(s.adjust_suffix(x)),
-                   self.src_suffix)
+        "__cacheable__"
+        return map(lambda x, s=self, e=env: e.subst(x), self.src_suffix)
 
     def set_src_suffix(self, src_suffix):
         if not src_suffix:
             src_suffix = []
         elif not SCons.Util.is_List(src_suffix):
             src_suffix = [ src_suffix ]
-        self.src_suffix = src_suffix
+        adjust = lambda suf, s=self: \
+                        callable(suf) and suf or s.adjust_suffix(suf)
+        self.src_suffix = map(adjust, src_suffix)
 
     def get_src_suffix(self, env):
         """Get the first src_suffix in the list of src_suffixes."""
@@ -745,19 +750,23 @@ class MultiStepBuilder(BuilderBase):
 
         src_suffixes = self.src_suffixes(env)
 
-        def match_src_suffix(node, src_suffixes=src_suffixes):
-            # This reaches directly into the Node.name attribute (instead
-            # of using an accessor function) for performance reasons.
-            return filter(lambda s, n=node.name:
-                                 n[-len(s):] == s,
-                          src_suffixes)
+        lengths_dict = {}
+        for l in map(len, src_suffixes):
+            lengths_dict[l] = None
+        lengths = lengths_dict.keys()
+
+        def match_src_suffix(node, src_suffixes=src_suffixes, lengths=lengths):
+            node_suffixes = map(lambda l, n=node: n.name[-l:], lengths)
+            for suf in src_suffixes:
+                if suf in node_suffixes:
+                    return suf
+            return None
 
         for snode in slist:
-            name = snode.name
-            match = match_src_suffix(snode)
-            if match:
+            match_suffix = match_src_suffix(snode)
+            if match_suffix:
                 try:
-                    bld = sdict[match[0]]
+                    bld = sdict[match_suffix]
                 except KeyError:
                     final_sources.append(snode)
                 else:
index 6ad57854f288ce8eb3057ca56d6da00860fa0ca7..3c98e278557d547425eafd40d4147c03db80edab 100644 (file)
@@ -536,6 +536,22 @@ class BuilderTestCase(unittest.TestCase):
         tgt = builder(my_env, target = None, source = 'f6.zzz')[0]
         assert tgt.path == 'emit-f6', tgt.path
 
+    def test_set_suffix(self):
+        """Test the set_suffix() method"""
+        b = SCons.Builder.Builder(action='')
+        env = Environment(XSUFFIX = '.x')
+
+        s = b.get_suffix(env)
+        assert s == '', s
+
+        b.set_suffix('.foo')
+        s = b.get_suffix(env)
+        assert s == '.foo', s
+
+        b.set_suffix('$XSUFFIX')
+        s = b.get_suffix(env)
+        assert s == '.x', s
+
     def test_src_suffix(self):
         """Test Builder creation with a specified source file suffix
         
@@ -1079,8 +1095,8 @@ class BuilderTestCase(unittest.TestCase):
         forms of component specifications."""
 
         builder = SCons.Builder.Builder()
-
         env = Environment(BUILDERS={'Bld':builder})
+
         r = builder.get_name(env)
         assert r == 'Bld', r
         r = builder.get_prefix(env)
@@ -1095,23 +1111,34 @@ class BuilderTestCase(unittest.TestCase):
         assert r == ['foo'], r
 
         # src_suffix can be a single string or a list of strings
+        # src_suffixes() caches its return value, so we use a new
+        # Builder each time we do any of these tests
 
-        builder.set_src_suffix('.foo')
-        r = builder.get_src_suffix(env)
+        bld = SCons.Builder.Builder()
+        env = Environment(BUILDERS={'Bld':bld})
+
+        bld.set_src_suffix('.foo')
+        r = bld.get_src_suffix(env)
         assert r == '.foo', r
-        r = builder.src_suffixes(env)
+        r = bld.src_suffixes(env)
         assert r == ['.foo'], r
 
-        builder.set_src_suffix(['.foo', '.bar'])
-        r = builder.get_src_suffix(env)
+        bld = SCons.Builder.Builder()
+        env = Environment(BUILDERS={'Bld':bld})
+
+        bld.set_src_suffix(['.foo', '.bar'])
+        r = bld.get_src_suffix(env)
         assert r == '.foo', r
-        r = builder.src_suffixes(env)
+        r = bld.src_suffixes(env)
         assert r == ['.foo', '.bar'], r
 
-        builder.set_src_suffix(['.bar', '.foo'])
-        r = builder.get_src_suffix(env)
+        bld = SCons.Builder.Builder()
+        env = Environment(BUILDERS={'Bld':bld})
+
+        bld.set_src_suffix(['.bar', '.foo'])
+        r = bld.get_src_suffix(env)
         assert r == '.bar', r
-        r = builder.src_suffixes(env)
+        r = bld.src_suffixes(env)
         assert r == ['.bar', '.foo'], r
 
         # adjust_suffix normalizes the suffix, adding a `.' if needed
@@ -1184,8 +1211,8 @@ class BuilderTestCase(unittest.TestCase):
         assert r == '.D', r
 
         builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={})
-
         env = Environment(BUILDERS={'Bld':builder})
+
         r = builder.get_name(env)
         assert r == 'Bld', r
         r = builder.get_prefix(env)
@@ -1201,7 +1228,10 @@ class BuilderTestCase(unittest.TestCase):
         # whose keys are the source suffix.  The add_action()
         # specifies a new source suffix/action binding.
 
+        builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={})
+        env = Environment(BUILDERS={'Bld':builder})
         builder.add_action('.src_sfx1', 'FOO')
+
         r = builder.get_name(env)
         assert r == 'Bld', r
         r = builder.get_prefix(env)
@@ -1215,6 +1245,9 @@ class BuilderTestCase(unittest.TestCase):
         r = builder.src_suffixes(env)
         assert r == ['.src_sfx1'], r
 
+        builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={})
+        env = Environment(BUILDERS={'Bld':builder})
+        builder.add_action('.src_sfx1', 'FOO')
         builder.add_action('.src_sfx2', 'BAR')
 
         r = builder.get_name(env)