Allow prefixes and suffixes to be selected from dictionaries keyd by source file...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sun, 10 Aug 2003 14:59:15 +0000 (14:59 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sun, 10 Aug 2003 14:59:15 +0000 (14:59 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@764 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/SCons/Builder.py
src/engine/SCons/BuilderTests.py

index 8df46cf5ffde4fc36a1755b71bd0867b3c54a89b..b9849c6e2e8cc39869613ca188ddf3ef5f5cafc2 100644 (file)
@@ -4946,14 +4946,14 @@ builder with the target.
 .IP prefix 
 The prefix that will be prepended to the target file name.
 This may be a simple string,  or a callable object that takes
-a construction environment as its argument
+two arguments, a construction environment and a list of sources,
 and returns a prefix.
 
 .ES
 b = Builder("build_it < $SOURCE > $TARGET"
             prefix = "file-")
 
-def gen_prefix(env):
+def gen_prefix(env, sources):
     return "file-" + env['PLATFORM'] + '-'
 b = Builder("build_it < $SOURCE > $TARGET"
             prefix = gen_prefix)
@@ -4962,7 +4962,7 @@ b = Builder("build_it < $SOURCE > $TARGET"
 .IP suffix
 The suffix that will be appended to the target file name.
 This may be a simple string, or a callable object that takes
-a construction environment as its argument
+two arguments, a construction environment and a list of sources,
 and returns a suffix.
 If the suffix is a string, then
 .B scons
@@ -4976,7 +4976,7 @@ to the beginning if one is desired.
 b = Builder("build_it < $SOURCE > $TARGET"
             suffix = "file-"
 
-def gen_suffix(env):
+def gen_suffix(env, sources):
     return "." + env['PLATFORM'] + "-file"
 b = Builder("build_it < $SOURCE > $TARGET"
             suffix = gen_suffix)
index 3df58e6eb2718918a75ac2b50852a2ef03033c7e..de2d75cc1f1ca614f1732789dc4d2ce956ddb7c2 100644 (file)
@@ -79,7 +79,8 @@ RELEASE 0.XX - XXX
     of the suffixes we use as C++ files.
 
   - Allow the "prefix" and "suffix" attributes of a Builder to be
-    callable objects that return generated strings.
+    callable objects that return generated strings, or dictionaries
+    that map a source file suffix to the right prefix/suffix.
 
   - Support a MAXLINELINELENGTH construction variable on Win32 systems
     to control when a temporary file is used for long command lines.
index be1608dd301ac21d0279857b2f849b4504c0f330..34f28bc65a03ed52ae2a90daa2e022544dabb319 100644 (file)
@@ -110,7 +110,29 @@ class DictCmdGenerator:
     def __cmp__(self, other):
         return cmp(self.action_dict, other.action_dict)
 
-class DictEmitter(UserDict.UserDict):
+class Selector(UserDict.UserDict):
+    """A callable dictionary that maps file suffixes to dictionary
+    values."""
+    def __call__(self, env, source):
+        ext = SCons.Util.splitext(str(source[0]))[1]
+        try:
+            return self[ext]
+        except KeyError:
+            # Try to perform Environment substitution on the keys of
+            # emitter_dict before giving up.
+            s_dict = {}
+            for (k,v) in self.items():
+                s_k = env.subst(k)
+                s_dict[s_k] = v
+            try:
+                return s_dict[ext]
+            except KeyError:
+                try:
+                    return self[None]
+                except KeyError:
+                    return None
+
+class DictEmitter(Selector):
     """A callable dictionary that maps file suffixes to emitters.
     When called, it finds the right emitter in its dictionary for the
     suffix of the first source file, and calls that emitter to get the
@@ -119,23 +141,9 @@ class DictEmitter(UserDict.UserDict):
     returned.
     """
     def __call__(self, target, source, env):
-        ext = SCons.Util.splitext(str(source[0]))[1]
-        if ext:
-            try:
-                emitter = self[ext]
-            except KeyError:
-                # Before raising the user error, try to perform Environment
-                # substitution on the keys of emitter_dict.
-                s_dict = {}
-                for (k,v) in self.items():
-                    s_k = env.subst(k)
-                    s_dict[s_k] = v
-                try:
-                    emitter = s_dict[ext]
-                except KeyError:
-                    emitter = None
-            if emitter:
-                target, source = emitter(target, source, env)
+        emitter = Selector.__call__(self, env, source)
+        if emitter:
+            target, source = emitter(target, source, env)
         return (target, source)
 
 def Builder(**kw):
@@ -284,7 +292,11 @@ class BuilderBase:
                         overrides = {}):
         self.action = SCons.Action.Action(action)
         self.multi = multi
+        if SCons.Util.is_Dict(prefix):
+            prefix = Selector(prefix)
         self.prefix = prefix
+        if SCons.Util.is_Dict(suffix):
+            suffix = Selector(suffix)
         self.suffix = suffix
         self.env = env
         self.overrides = overrides
@@ -344,13 +356,14 @@ class BuilderBase:
 
         env = env.Override(overrides)
 
-        pre = self.get_prefix(env)
-        suf = self.get_suffix(env)
         src_suf = self.get_src_suffix(env)
 
         source = adjustixes(source, None, src_suf)
         slist = SCons.Node.arg2nodes(source, self.source_factory)
 
+        pre = self.get_prefix(env, slist)
+        suf = self.get_suffix(env, slist)
+
         if target is None:
             try:
                 t_from_s = slist[0].target_from_source
@@ -410,16 +423,16 @@ class BuilderBase:
             return '.' + suff
         return suff
 
-    def get_prefix(self, env):
+    def get_prefix(self, env, sources=[]):
         prefix = self.prefix
         if callable(prefix):
-            prefix = prefix(env)
+            prefix = prefix(env, sources)
         return env.subst(prefix)
 
-    def get_suffix(self, env):
+    def get_suffix(self, env, sources=[]):
         suffix = self.suffix
         if callable(suffix):
-            suffix = suffix(env)
+            suffix = suffix(env, sources)
         else:
             suffix = self.adjust_suffix(suffix)
         return env.subst(suffix)
index f8d22edee90c8d5ad15b2ebf3705e21a778c04a5..8aafefaced2b10e6d56ac085b4fcdf24a91fd941 100644 (file)
@@ -362,7 +362,7 @@ class BuilderTestCase(unittest.TestCase):
         assert tgt.path == os.path.join('lib', 'libtgt5'), \
                 "Target has unexpected name: %s" % tgt.path
 
-        def gen_prefix(env):
+        def gen_prefix(env, sources):
             return "gen_prefix() says " + env['FOO']
         my_env = Environment(FOO = 'xyzzy')
         builder = SCons.Builder.Builder(prefix = gen_prefix)
@@ -370,6 +370,18 @@ class BuilderTestCase(unittest.TestCase):
         my_env['FOO'] = 'abracadabra'
         assert builder.get_prefix(my_env) == "gen_prefix() says abracadabra"
 
+        builder = SCons.Builder.Builder(prefix = {None  : 'default-',
+                                                  '.in' : 'out-',
+                                                  '.x'  : 'y-'})
+        tgt = builder(env, source = 'f1')
+        assert tgt.path == 'default-f1', tgt.path
+        tgt = builder(env, source = 'f2.c')
+        assert tgt.path == 'default-f2', tgt.path
+        tgt = builder(env, source = 'f3.in')
+        assert tgt.path == 'out-f3', tgt.path
+        tgt = builder(env, source = 'f4.x')
+        assert tgt.path == 'y-f4', tgt.path
+
     def test_src_suffix(self):
         """Test Builder creation with a specified source file suffix
         
@@ -424,7 +436,7 @@ class BuilderTestCase(unittest.TestCase):
         assert tgt.path == 'src5.o', \
                 "Target has unexpected name: %s" % tgt.path
 
-        def gen_suffix(env):
+        def gen_suffix(env, sources):
             return "gen_suffix() says " + env['BAR']
         my_env = Environment(BAR = 'hocus pocus')
         builder = SCons.Builder.Builder(suffix = gen_suffix)
@@ -432,6 +444,18 @@ class BuilderTestCase(unittest.TestCase):
         my_env['BAR'] = 'presto chango'
         assert builder.get_suffix(my_env) == "gen_suffix() says presto chango"
 
+        builder = SCons.Builder.Builder(suffix = {None  : '.default',
+                                                  '.in' : '.out',
+                                                  '.x'  : '.y'})
+        tgt = builder(env, source = 'f1')
+        assert tgt.path == 'f1.default', tgt.path
+        tgt = builder(env, source = 'f2.c')
+        assert tgt.path == 'f2.default', tgt.path
+        tgt = builder(env, source = 'f3.in')
+        assert tgt.path == 'f3.out', tgt.path
+        tgt = builder(env, source = 'f4.x')
+        assert tgt.path == 'f4.y', tgt.path
+
     def test_ListBuilder(self):
         """Testing ListBuilder class."""
         def function2(target, source, env, tlist = [outfile, outfile2], **kw):