Check in the Tool() interface. (SK and Charles Crain)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 20 Jun 2002 00:17:18 +0000 (00:17 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 20 Jun 2002 00:17:18 +0000 (00:17 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@392 fdb21ef1-2011-0410-befe-b5e4ea1792b1

37 files changed:
doc/man/scons.1
rpm/scons.spec
src/CHANGES.txt
src/engine/MANIFEST.in
src/engine/SCons/Builder.py
src/engine/SCons/BuilderTests.py
src/engine/SCons/Defaults.py
src/engine/SCons/Environment.py
src/engine/SCons/EnvironmentTests.py
src/engine/SCons/Platform/__init__.py
src/engine/SCons/Platform/cygwin.py
src/engine/SCons/Platform/posix.py
src/engine/SCons/Platform/win32.py
src/engine/SCons/Script/SConscript.py
src/engine/SCons/Script/__init__.py
src/engine/SCons/Tool/ToolTests.py [new file with mode: 0644]
src/engine/SCons/Tool/__init__.py [new file with mode: 0644]
src/engine/SCons/Tool/ar.py [new file with mode: 0644]
src/engine/SCons/Tool/dvipdf.py [new file with mode: 0644]
src/engine/SCons/Tool/dvips.py [new file with mode: 0644]
src/engine/SCons/Tool/g++.py [new file with mode: 0644]
src/engine/SCons/Tool/g77.py [new file with mode: 0644]
src/engine/SCons/Tool/gcc.py [new file with mode: 0644]
src/engine/SCons/Tool/gnulink.py [new file with mode: 0644]
src/engine/SCons/Tool/latex.py [new file with mode: 0644]
src/engine/SCons/Tool/lex.py [new file with mode: 0644]
src/engine/SCons/Tool/lib.py [new file with mode: 0644]
src/engine/SCons/Tool/mslink.py [new file with mode: 0644]
src/engine/SCons/Tool/msvc.py [new file with mode: 0644]
src/engine/SCons/Tool/pdflatex.py [new file with mode: 0644]
src/engine/SCons/Tool/pdftex.py [new file with mode: 0644]
src/engine/SCons/Tool/tex.py [new file with mode: 0644]
src/engine/SCons/Tool/yacc.py [new file with mode: 0644]
src/engine/SCons/Util.py
src/engine/SCons/UtilTests.py
src/setup.py
test/SharedLibrary.py

index 79ca4b7faaf7adca56a5055819845cf58afc36f1..a81bae583376e56b3363213219e1d435529c041c 100644 (file)
@@ -686,6 +686,69 @@ def my_platform(env):
 env = Environment(platform = my_platform)
 .EE
 
+Additionally, a specific set of tools
+with which to initialize the environment
+may specified as an optional keyword argument:
+
+.ES
+env = Environment(tools = ['msvc', 'lex'])
+.EE
+
+The elements of the tools list may also
+be functions or callable objects,
+in which case the Environment() method
+will call the specified elements
+to update the new construction environment:
+
+.ES
+def my_tool(env):
+    env['XYZZY'] = 'xyzzy'
+
+env = Environment(tools = [my_tool])
+.EE
+
+SCons supports the following tool specifications
+out of the box on 
+.B cygwin
+and
+.B posix
+platforms:
+
+.ES
+ar
+dvipdf
+dvips
+g++
+g77
+gcc
+gnulink
+latex
+lex
+pdflatex
+pdftex
+tex
+yacc
+.EE
+
+and supports the following tool specifications out of the box on
+.B win32
+platforms:
+
+.ES
+dvipdf
+dvips
+g77
+latex
+lex
+lib
+mslink
+msvc
+pdflatex
+pdftex
+tex
+yacc
+.EE
+
 .SS Builder Methods
 
 Build rules are specified by calling a construction
@@ -1767,7 +1830,7 @@ foo = SConscript('subdir/SConscript', "env")
 
 .TP
 .RI SConscriptChdir( value )
-When a non-negative
+When a non-zero
 .I value
 is specified,
 this instructs
@@ -1841,6 +1904,17 @@ or by using the Split() function provided here,
 or by using a similar function such as the
 string.split() function in the Python library.
 
+.TP
+.RI Tool( string )
+Returns a callable object
+that can be used to initialize
+a construction environment using the
+tools keyword of the Environment() method.
+
+.ES
+env = Environment(tools = [ Tool('msvc') ])
+.EE
+
 .TP
 .RI WhereIs( program ", [" path  ", [" pathext ]])
 
index 0bfa0e057d09635bb6b937bd185dde762bb2695d..a2cb76da5469f769099f7b69f500ee529e97a929 100644 (file)
@@ -96,6 +96,40 @@ rm -rf $RPM_BUILD_ROOT
 /usr/lib/scons/SCons/Sig/__init__.pyc
 /usr/lib/scons/SCons/Taskmaster.py
 /usr/lib/scons/SCons/Taskmaster.pyc
+/usr/lib/scons/SCons/Tool/__init__.py
+/usr/lib/scons/SCons/Tool/__init__.pyc
+/usr/lib/scons/SCons/Tool/ar.py
+/usr/lib/scons/SCons/Tool/ar.pyc
+/usr/lib/scons/SCons/Tool/dvipdf.py
+/usr/lib/scons/SCons/Tool/dvipdf.pyc
+/usr/lib/scons/SCons/Tool/dvips.py
+/usr/lib/scons/SCons/Tool/dvips.pyc
+/usr/lib/scons/SCons/Tool/g++.py
+/usr/lib/scons/SCons/Tool/g++.pyc
+/usr/lib/scons/SCons/Tool/g77.py
+/usr/lib/scons/SCons/Tool/g77.pyc
+/usr/lib/scons/SCons/Tool/gcc.py
+/usr/lib/scons/SCons/Tool/gcc.pyc
+/usr/lib/scons/SCons/Tool/gnulink.py
+/usr/lib/scons/SCons/Tool/gnulink.pyc
+/usr/lib/scons/SCons/Tool/latex.py
+/usr/lib/scons/SCons/Tool/latex.pyc
+/usr/lib/scons/SCons/Tool/lex.py
+/usr/lib/scons/SCons/Tool/lex.pyc
+/usr/lib/scons/SCons/Tool/lib.py
+/usr/lib/scons/SCons/Tool/lib.pyc
+/usr/lib/scons/SCons/Tool/mslink.py
+/usr/lib/scons/SCons/Tool/mslink.pyc
+/usr/lib/scons/SCons/Tool/msvc.py
+/usr/lib/scons/SCons/Tool/msvc.pyc
+/usr/lib/scons/SCons/Tool/pdflatex.py
+/usr/lib/scons/SCons/Tool/pdflatex.pyc
+/usr/lib/scons/SCons/Tool/pdftex.py
+/usr/lib/scons/SCons/Tool/pdftex.pyc
+/usr/lib/scons/SCons/Tool/tex.py
+/usr/lib/scons/SCons/Tool/tex.pyc
+/usr/lib/scons/SCons/Tool/yacc.py
+/usr/lib/scons/SCons/Tool/yacc.pyc
 /usr/lib/scons/SCons/Util.py
 /usr/lib/scons/SCons/Util.pyc
 /usr/lib/scons/SCons/Warnings.py
index 63feea258fd02dd97da3b96254afbff0d2f2f3cd..ad9f56c04b1bd1e4160564218a20a10a51fe6670 100644 (file)
@@ -38,6 +38,12 @@ RELEASE 0.08 -
   - Removed support for the prefix, suffix and src_suffix arguments
     to Builder() to be callable functions.
 
+  From Charles Crain and Steven Knight:
+
+  - Add a "tools=" keyword argument to Environment instantiation,
+    and a separate Tools() method, for more flexible specification
+    of tool-specific environment changes.
+
   From Steven Knight:
 
   - Add a "platform=" keyword argument to Environment instantiation,
index dce529153fdb4281403ff860b524ab353d169f95..b67d63a76e2c41264966d26c73d52e14a71b0faf 100644 (file)
@@ -23,5 +23,22 @@ SCons/Sig/__init__.py
 SCons/Sig/MD5.py
 SCons/Sig/TimeStamp.py
 SCons/Taskmaster.py
+SCons/Tool/__init__.py
+SCons/Tool/ar.py
+SCons/Tool/dvipdf.py
+SCons/Tool/dvips.py
+SCons/Tool/g++.py
+SCons/Tool/g77.py
+SCons/Tool/gcc.py
+SCons/Tool/gnulink.py
+SCons/Tool/latex.py
+SCons/Tool/lex.py
+SCons/Tool/lib.py
+SCons/Tool/mslink.py
+SCons/Tool/msvc.py
+SCons/Tool/pdflatex.py
+SCons/Tool/pdftex.py
+SCons/Tool/tex.py
+SCons/Tool/yacc.py
 SCons/Util.py
 SCons/Warnings.py
index 94a89464f5e16511a0530f301943c5a7ec0c53ed..4dd6163504af31bf441416e0530d61cb96d20d62 100644 (file)
@@ -1,6 +1,20 @@
 """SCons.Builder
 
-XXX
+Builder object subsystem.
+
+A Builder object is a callable that encapsulates information about how
+to execute actions to create a Node (file) from other Nodes (files), and
+how to create those dependencies for tracking.
+
+The main entry point here is the Builder() factory method.  This
+provides a procedural interface that creates the right underlying
+Builder object based on the keyword arguments supplied and the types of
+the arguments.
+
+The goal is for this external interface to be simple enough that the
+vast majority of users can create new Builders as necessary to support
+building new types of files in their configurations, without having to
+dive any deeper into this subsystem.
 
 """
 
@@ -55,6 +69,11 @@ class DictCmdGenerator:
     def src_suffixes(self):
         return self.action_dict.keys()
 
+    def add_action(self, suffix, action):
+        """Add a suffix-action pair to the mapping.
+        """
+        self.action_dict[suffix] = action
+
     def __call__(self, source, target, env, **kw):
         ext = None
         for src in map(str, source):
@@ -71,9 +90,12 @@ class DictCmdGenerator:
             return self.action_dict[ext]
         except KeyError:
             raise UserError("Don't know how to build a file with suffix %s." % ext)
+    def __cmp__(self, other):
+        return cmp(self.action_dict, other.action_dict)
 
 def Builder(**kw):
     """A factory for builder objects."""
+    composite = None
     if kw.has_key('name'):
         SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
                             "The use of the 'name' parameter to Builder() is deprecated.")
@@ -83,9 +105,9 @@ def Builder(**kw):
         kw['action'] = SCons.Action.CommandGenerator(kw['generator'])
         del kw['generator']
     elif kw.has_key('action') and SCons.Util.is_Dict(kw['action']):
-        action_dict = kw['action']
-        kw['action'] = SCons.Action.CommandGenerator(DictCmdGenerator(action_dict))
-        kw['src_suffix'] = action_dict.keys()
+        composite = DictCmdGenerator(kw['action'])
+        kw['action'] = SCons.Action.CommandGenerator(composite)
+        kw['src_suffix'] = composite.src_suffixes()
 
     if kw.has_key('emitter') and \
        SCons.Util.is_String(kw['emitter']):
@@ -99,9 +121,14 @@ def Builder(**kw):
         kw['emitter'] = EmitterProxy(var)
         
     if kw.has_key('src_builder'):
-        return apply(MultiStepBuilder, (), kw)
+        ret = apply(MultiStepBuilder, (), kw)
     else:
-        return apply(BuilderBase, (), kw)
+        ret = apply(BuilderBase, (), kw)
+
+    if composite:
+        ret = CompositeBuilder(ret, composite)
+
+    return ret
 
 def _init_nodes(builder, env, args, tlist, slist):
     """Initialize lists of target and source nodes with all of
@@ -139,25 +166,7 @@ def _init_nodes(builder, env, args, tlist, slist):
         t.add_source(slist)
         if builder.scanner:
             t.target_scanner = builder.scanner
-        
-class _callable_adaptor:
-    """When crteating a Builder, you can pass a string OR
-    a callable in for prefix, suffix, or src_suffix.
-    src_suffix even takes a list!
-
-    If a string or list is passed, we use this class to
-    adapt it to a callable."""
-    def __init__(self, static):
-        self.static = static
-
-    def __call__(self, **kw):
-        return self.static
-
-    def __cmp__(self, other):
-        if isinstance(other, _callable_adaptor):
-            return cmp(self.static, other.static)
-        return -1
-
+            
 def _adjust_suffix(suff):
     if suff and not suff[0] in [ '.', '$' ]:
         return '.' + suff
@@ -176,7 +185,7 @@ class EmitterProxy:
     def __call__(self, target, source, env, **kw):
         emitter = self.var
 
-        # Recursively substitue the variable.
+        # Recursively substitute the variable.
         # We can't use env.subst() because it deals only
         # in strings.  Maybe we should change that?
         while SCons.Util.is_String(emitter) and \
@@ -190,6 +199,9 @@ class EmitterProxy:
         args.update(kw)
         return apply(emitter, (), args)
 
+    def __cmp__(self, other):
+        return cmp(self.var, other.var)
+
 class BuilderBase:
     """Base class for Builders, objects that create output
     nodes (files) from input nodes (files).
@@ -212,10 +224,7 @@ class BuilderBase:
         self.prefix = prefix
         self.suffix = suffix
 
-        if SCons.Util.is_String(src_suffix):
-            self.src_suffix = [ src_suffix ]
-        else:
-            self.src_suffix = src_suffix
+        self.set_src_suffix(src_suffix)
 
         self.target_factory = target_factory or node_factory
         self.source_factory = source_factory or node_factory
@@ -264,9 +273,9 @@ class BuilderBase:
                ret.append(f)
            return ret
 
-        pre = self.get_prefix(env, args)
-        suf = self.get_suffix(env, args)
-        src_suf = self.get_src_suffix(env, args)
+        pre = self.get_prefix(env)
+        suf = self.get_suffix(env)
+        src_suf = self.get_src_suffix(env)
         if self.emitter:
             # pass the targets and sources to the emitter as strings
             # rather than nodes since str(node) doesn't work 
@@ -299,7 +308,6 @@ class BuilderBase:
 
         return tlist
 
-
     def execute(self, **kw):
         """Execute a builder's action to create an output object.
         """
@@ -316,21 +324,28 @@ class BuilderBase:
         """
         return apply(self.action.get_contents, (), kw)
 
-    def src_suffixes(self, env, args):
+    def src_suffixes(self, env):
         return map(lambda x, e=env: e.subst(_adjust_suffix(x)),
                    self.src_suffix)
 
-    def get_src_suffix(self, env, args):
+    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
+
+    def get_src_suffix(self, env):
         """Get the first src_suffix in the list of src_suffixes."""
-        if not self.src_suffix:
+        ret = self.src_suffixes(env)
+        if not ret:
             return ''
-        else:
-            return self.src_suffix[0]
+        return ret[0]
 
-    def get_suffix(self, env, args):
+    def get_suffix(self, env):
         return env.subst(_adjust_suffix(self.suffix))
 
-    def get_prefix(self, env, args):
+    def get_prefix(self, env):
         return env.subst(self.prefix)
 
     def targets(self, node):
@@ -340,20 +355,19 @@ class BuilderBase:
         """
         return [ node ]
 
-class ListBuilder:
-    """This is technically not a Builder object, but a wrapper
-    around another Builder object.  This is designed to look
-    like a Builder object, though, for purposes of building an
-    array of targets from a single Action execution.
+class ListBuilder(SCons.Util.Proxy):
+    """A Proxy to support building an array of targets (for example,
+    foo.o and foo.h from foo.y) from a single Action execution.
     """
 
     def __init__(self, builder, env, tlist):
+        SCons.Util.Proxy.__init__(self, builder)
         self.builder = builder
+        self.scanner = builder.scanner
+        self.env = env
         self.tlist = tlist
-        self.name = "ListBuilder(%s)"%builder.get_name(env)
-
-    def get_name(self, env):
-        return self.name
+        self.multi = builder.multi
+        self.name = "ListBuilder(%s)"%builder.name
 
     def execute(self, **kw):
         if hasattr(self, 'status'):
@@ -375,10 +389,17 @@ class ListBuilder:
         return self.tlist
 
     def __cmp__(self, other):
-       return cmp(self.__dict__, other.__dict__)
+        return cmp(self.__dict__, other.__dict__)
 
-    def __getattr__(self, name):
-       return getattr(self.builder, name)
+    def get_name(self, env):
+        """Attempts to get the name of the Builder.
+
+        If the Builder's name attribute is None, then we will look at
+        the BUILDERS variable of env, expecting it to be a dictionary
+        containing this Builder, and we will return the key of the
+        dictionary."""
+
+        return "ListBuilder(%s)" % self.builder.get_name(env)
 
 class MultiStepBuilder(BuilderBase):
     """This is a builder subclass that can build targets in
@@ -421,7 +442,12 @@ class MultiStepBuilder(BuilderBase):
             sdict = {}
             self.sdict[r] = sdict
             for bld in self.src_builder:
-                for suf in bld.src_suffixes(env, kw):
+                if SCons.Util.is_String(bld):
+                    try:
+                        bld = env['BUILDERS'][bld]
+                    except KeyError:
+                        continue
+                for suf in bld.src_suffixes(env):
                     sdict[suf] = bld
                     
         for snode in slist:
@@ -440,7 +466,7 @@ class MultiStepBuilder(BuilderBase):
                 # Only supply the builder with sources it is capable
                 # of building.
                 tgt = filter(lambda x,
-                             suf=self.src_suffixes(env, kw):
+                             suf=self.src_suffixes(env):
                              os.path.splitext(SCons.Util.to_String(x))[1] in \
                              suf, tgt)
                 final_sources.extend(tgt)
@@ -452,9 +478,48 @@ class MultiStepBuilder(BuilderBase):
         return apply(BuilderBase.__call__,
                      (self, env), dictKwArgs)
 
-    def src_suffixes(self, env, args):
-        return BuilderBase.src_suffixes(self, env, args) + \
-               reduce(lambda x, y: x + y,
-                      map(lambda b, e=env, args=args: b.src_suffixes(e, args),
-                          self.src_builder),
-                      [])
+    def get_src_builders(self, env):
+        """Return all the src_builders for this Builder.
+
+        This is essentially a recursive descent of the src_builder "tree."
+        """
+        ret = []
+        for bld in self.src_builder:
+            if SCons.Util.is_String(bld):
+                # All Environments should have a BUILDERS
+                # variable, so no need to check for it.
+                try:
+                    bld = env['BUILDERS'][bld]
+                except KeyError:
+                    continue
+            ret.append(bld)
+        return ret
+
+    def src_suffixes(self, env):
+        """Return a list of the src_suffix attributes for all
+        src_builders of this Builder.
+        """
+        suffixes = BuilderBase.src_suffixes(self, env)
+        for builder in self.get_src_builders(env):
+            suffixes.extend(builder.src_suffixes(env))
+        return suffixes
+
+class CompositeBuilder(SCons.Util.Proxy):
+    """A Builder Proxy whose main purpose is to always have
+    a DictCmdGenerator as its action, and to provide access
+    to the DictCmdGenerator's add_action() method.
+    """
+
+    def __init__(self, builder, cmdgen):
+        SCons.Util.Proxy.__init__(self, builder)
+
+        # cmdgen should always be an instance of DictCmdGenerator.
+        self.cmdgen = cmdgen
+        self.builder = builder
+
+    def add_action(self, suffix, action):
+        self.cmdgen.add_action(suffix, action)
+        self.set_src_suffix(self.cmdgen.src_suffixes())
+        
+    def __cmp__(self, other):
+        return cmp(self.__dict__, other.__dict__)
index e1fc8fc887bdfaf1bac52aed040094535d83eee2..7ff06c2a71501b24687252b8b5903ab96d84169d 100644 (file)
@@ -76,6 +76,8 @@ class Environment:
         for k, v in kw.items():
             self.d[k] = v
     def subst(self, s):
+        if not SCons.Util.is_String(s):
+            return s
         try:
             if s[0] == '$':
                 return self.d.get(s[1:], '')
@@ -446,9 +448,9 @@ class BuilderTestCase(unittest.TestCase):
         Make sure that there is no '.' separator appended.
         """
         builder = SCons.Builder.Builder(name = "builder", prefix = 'lib.')
-        assert builder.get_prefix(env,{}) == 'lib.'
+        assert builder.get_prefix(env) == 'lib.'
         builder = SCons.Builder.Builder(name = "builder", prefix = 'lib')
-        assert builder.get_prefix(env,{}) == 'lib'
+        assert builder.get_prefix(env) == 'lib'
         tgt = builder(env, target = 'tgt1', source = 'src1')
         assert tgt.path == 'libtgt1', \
                 "Target has unexpected name: %s" % tgt.path
@@ -465,7 +467,7 @@ class BuilderTestCase(unittest.TestCase):
         env = Environment(XSUFFIX = '.x', YSUFFIX = '.y')
 
         b1 = SCons.Builder.Builder(name = "builder", src_suffix = '.c')
-        assert b1.src_suffixes(env,{}) == ['.c'], b1.src_suffixes(env,{})
+        assert b1.src_suffixes(env) == ['.c'], b1.src_suffixes(env)
 
         tgt = b1(env, target = 'tgt2', source = 'src2')
         assert tgt.sources[0].path == 'src2.c', \
@@ -479,19 +481,19 @@ class BuilderTestCase(unittest.TestCase):
         b2 = SCons.Builder.Builder(name = "b2",
                                    src_suffix = '.2',
                                    src_builder = b1)
-        assert b2.src_suffixes(env,{}) == ['.2', '.c'], b2.src_suffixes(env,{})
+        assert b2.src_suffixes(env) == ['.2', '.c'], b2.src_suffixes(env)
 
         b3 = SCons.Builder.Builder(name = "b3",
                                    action = {'.3a' : '', '.3b' : ''})
-        s = b3.src_suffixes(env,{})
+        s = b3.src_suffixes(env)
         s.sort()
         assert s == ['.3a', '.3b'], s
 
         b4 = SCons.Builder.Builder(name = "b4", src_suffix = '$XSUFFIX')
-        assert b4.src_suffixes(env,{}) == ['.x'], b4.src_suffixes(env,{})
+        assert b4.src_suffixes(env) == ['.x'], b4.src_suffixes(env)
 
-        b5 = SCons.Builder.Builder(name = "b5", action = {'$YSUFFIX' : ''})
-        assert b5.src_suffixes(env,{}) == ['.y'], b5.src_suffixes(env,{})
+        b5 = SCons.Builder.Builder(name = "b5", action = { '.y' : ''})
+        assert b5.src_suffixes(env) == ['.y'], b5.src_suffixes(env)
 
     def test_suffix(self):
         """Test Builder creation with a specified target suffix
@@ -500,9 +502,9 @@ class BuilderTestCase(unittest.TestCase):
         beginning if it isn't already present.
         """
         builder = SCons.Builder.Builder(name = "builder", suffix = '.o')
-        assert builder.get_suffix(env,{}) == '.o', builder.get_suffix(env,{})
+        assert builder.get_suffix(env) == '.o', builder.get_suffix(env)
         builder = SCons.Builder.Builder(name = "builder", suffix = 'o')
-        assert builder.get_suffix(env,{}) == '.o', builder.get_suffix(env,{})
+        assert builder.get_suffix(env) == '.o', builder.get_suffix(env)
         tgt = builder(env, target = 'tgt3', source = 'src3')
         assert tgt.path == 'tgt3.o', \
                 "Target has unexpected name: %s" % tgt.path
@@ -582,6 +584,12 @@ class BuilderTestCase(unittest.TestCase):
                str(tgt.sources[0].sources[0])
         assert str(tgt.sources[1]) == 'test2.foo', str(tgt.sources[1])
         assert str(tgt.sources[2]) == 'test3.txt', str(tgt.sources[2])
+
+        builder3 = SCons.Builder.MultiStepBuilder(name = "builder3",
+                                                  action = 'foo',
+                                                  src_builder = 'xyzzy',
+                                                  src_suffix = '.xyzzy')
+        assert builder3.get_src_builders(Environment()) == []
         
     def test_CompositeBuilder(self):
         """Testing CompositeBuilder class."""
@@ -592,13 +600,16 @@ class BuilderTestCase(unittest.TestCase):
                                         action={ '.foo' : func_action,
                                                  '.bar' : func_action })
         
-        assert isinstance(builder, SCons.Builder.BuilderBase)
+        assert isinstance(builder, SCons.Builder.CompositeBuilder)
         assert isinstance(builder.action, SCons.Action.CommandGeneratorAction)
         tgt = builder(env, target='test1', source='test1.foo')
         assert isinstance(tgt.builder, SCons.Builder.BuilderBase)
-        assert isinstance(tgt.builder.action.generator, SCons.Builder.DictCmdGenerator)
+        assert tgt.builder.action is builder.action
+        tgt = builder(env, target='test2', source='test1.bar')
+        assert isinstance(tgt.builder, SCons.Builder.BuilderBase)
+        assert tgt.builder.action is builder.action
         flag = 0
-        tgt = builder(env, target='test2', source=['test2.bar', 'test1.foo'])
+        tgt = builder(env, target='test3', source=['test2.bar', 'test1.foo'])
         try:
             tgt.build()
         except SCons.Errors.UserError:
@@ -614,7 +625,7 @@ class BuilderTestCase(unittest.TestCase):
                                         action = { '.foo' : 'foo',
                                                    '.bar' : 'bar' },
                                         src_builder = foo_bld)
-        assert isinstance(builder, SCons.Builder.MultiStepBuilder)
+        assert isinstance(builder, SCons.Builder.CompositeBuilder)
         assert isinstance(builder.action, SCons.Action.CommandGeneratorAction)
 
         tgt = builder(env, target='t1', source='t1a.ina t1b.ina')
@@ -629,12 +640,13 @@ class BuilderTestCase(unittest.TestCase):
                                         suffix = '.bar')
         assert isinstance(bar_bld, SCons.Builder.BuilderBase)
         builder = SCons.Builder.Builder(name = "builder",
-                                        action = { '.foo' : 'foo',
-                                                   '.bar' : 'bar' },
+                                        action = { '.foo' : 'foo'},
                                         src_builder = [foo_bld, bar_bld])
-        assert isinstance(builder, SCons.Builder.MultiStepBuilder)
+        assert isinstance(builder, SCons.Builder.CompositeBuilder)
         assert isinstance(builder.action, SCons.Action.CommandGeneratorAction)
 
+        builder.add_action('.bar', 'bar')
+
         tgt = builder(env, target='t3-foo', source='t3a.foo t3b.ina')
         assert isinstance(tgt.builder, SCons.Builder.MultiStepBuilder)
 
@@ -759,6 +771,10 @@ class BuilderTestCase(unittest.TestCase):
         assert 'baz' in map(str, tgt.sources), map(str, tgt.sources)
         assert 'bar' in map(str, tgt.sources), map(str, tgt.sources)
 
+        builder2a=SCons.Builder.Builder(name="builder2", action='foo',
+                                        emitter="$FOO")
+        assert builder2 == builder2a, repr(builder2.__dict__) + "\n" + repr(builder2a.__dict__)
+
 if __name__ == "__main__":
     suite = unittest.makeSuite(BuilderTestCase, 'test_')
     if not unittest.TextTestRunner().run(suite).wasSuccessful():
index e7a49b8656722ec5c67cbdf5f2222b7b64707d51..778517d3d92f157a9f107a96de445da36828c271 100644 (file)
@@ -44,14 +44,23 @@ import os.path
 
 import SCons.Action
 import SCons.Builder
-import SCons.Errors
 import SCons.Node.Alias
 import SCons.Node.FS
-import SCons.Platform
 import SCons.Scanner.C
 import SCons.Scanner.Fortran
 import SCons.Scanner.Prog
-import SCons.Util
+
+def alias_builder(env, target, source):
+    pass
+
+Alias = SCons.Builder.Builder(action = alias_builder,
+                              target_factory = SCons.Node.Alias.default_ans.Alias,
+                              source_factory = SCons.Node.FS.default_fs.Entry,
+                              multi = 1)
+
+CScan = SCons.Scanner.C.CScan()
+
+FortranScan = SCons.Scanner.Fortran.FortranScan()
 
 def yaccEmitter(target, source, env, **kw):
     # Yacc can be configured to emit a .h file as well
@@ -64,17 +73,17 @@ def yaccEmitter(target, source, env, **kw):
                       '.h')
     return (target, source)
 
-CFile = SCons.Builder.Builder(action = { '.l'    : '$LEXCOM',
-                                         '.y'    : '$YACCCOM',
-                                       },
-                              emitter = yaccEmitter,
-                              suffix = '$CFILESUFFIX')
+def CFile():
+    """Common function to generate a C file Builder."""
+    return SCons.Builder.Builder(action = {},
+                                 emitter = yaccEmitter,
+                                 suffix = '$CFILESUFFIX')
 
-CXXFile = SCons.Builder.Builder(action = { '.ll' : '$LEXCOM',
-                                           '.yy' : '$YACCCOM',
-                                         },
-                                emitter = yaccEmitter,
-                                suffix = '$CXXFILESUFFIX')
+def CXXFile():
+    """Common function to generate a C++ file Builder."""
+    return SCons.Builder.Builder(action = {},
+                                 emitter = yaccEmitter,
+                                 suffix = '$CXXFILESUFFIX')
 
 class SharedFlagChecker:
     """This is a callable class that is used as
@@ -112,536 +121,69 @@ ShF77Action = SCons.Action.Action([ SharedCheck, "$SHF77COM" ])
 F77PPAction = SCons.Action.Action([ StaticCheck, "$F77PPCOM" ])
 ShF77PPAction = SCons.Action.Action([ SharedCheck, "$SHF77PPCOM" ])
 
-if os.path.normcase('.c') == os.path.normcase('.C'):
-    # We're on a case-insensitive system, so .[CF] (upper case)
-    # files should be treated like .[cf] (lower case) files.
-    C_static = CAction
-    C_shared = ShCAction
-    F_static = F77Action
-    F_shared = ShF77Action
-else:
-    # We're on a case-sensitive system, so .C (upper case) files
-    # are C++, and .F (upper case) files get run through the C
-    # preprocessor.
-    C_static = CXXAction
-    C_shared = ShCXXAction
-    F_static = F77PPAction
-    F_shared = ShF77PPAction
-
-StaticObject = SCons.Builder.Builder(action = { ".C"   : C_static,
-                                                ".cc"  : CXXAction,
-                                                ".cpp" : CXXAction,
-                                                ".cxx" : CXXAction,
-                                                ".c++" : CXXAction,
-                                                ".C++" : CXXAction,
-                                                ".c"   : CAction,
-                                                ".f"   : F77Action,
-                                                ".for" : F77Action,
-                                                ".F"   : F_static,
-                                                ".FOR" : F77Action,
-                                                ".fpp" : F77PPAction,
-                                                ".FPP" : F77PPAction },
-                                     prefix = '$OBJPREFIX',
-                                     suffix = '$OBJSUFFIX',
-                                     src_builder = [CFile, CXXFile])
-
-SharedObject = SCons.Builder.Builder(action = { ".C"   : C_shared,
-                                                ".cc"  : ShCXXAction,
-                                                ".cpp" : ShCXXAction,
-                                                ".cxx" : ShCXXAction,
-                                                ".c++" : ShCXXAction,
-                                                ".C++" : ShCXXAction,
-                                                ".c"   : ShCAction,
-                                                ".f"   : ShF77Action,
-                                                ".for" : ShF77Action,
-                                                ".FOR" : ShF77Action,
-                                                ".F"   : F_shared,
-                                                ".fpp" : ShF77PPAction,
-                                                ".FPP" : ShF77PPAction },
-                                     prefix = '$OBJPREFIX',
-                                     suffix = '$OBJSUFFIX',
-                                     src_builder = [CFile, CXXFile])
-
-def win32TempFileMunge(env, cmd_list, for_signature): 
-    """Given a list of command line arguments, see if it is too
-    long to pass to the win32 command line interpreter.  If so,
-    create a temp file, then pass "@tempfile" as the sole argument
-    to the supplied command (which is the first element of cmd_list).
-    Otherwise, just return [cmd_list]."""
-    cmd = env.subst_list(cmd_list)[0]
-    if for_signature or \
-       (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= 2048:
-        return [cmd_list]
-    else:
-        import tempfile
-        # We do a normpath because mktemp() has what appears to be
-        # a bug in Win32 that will use a forward slash as a path
-        # delimiter.  Win32's link mistakes that for a command line
-        # switch and barfs.
-        tmp = os.path.normpath(tempfile.mktemp())
-        args = map(SCons.Util.quote_spaces, cmd[1:])
-        open(tmp, 'w').write(string.join(args, " ") + "\n")
-        return [ [cmd[0], '@' + tmp],
-                 ['del', tmp] ]
-    
-def win32LinkGenerator(env, target, source, for_signature, **kw):
-    args = [ '$LINK', '$LINKFLAGS', '/OUT:%s' % target[0],
-             '$(', '$_LIBDIRFLAGS', '$)', '$_LIBFLAGS' ]
-    args.extend(map(SCons.Util.to_String, source))
-    return win32TempFileMunge(env, args, for_signature)
 
-ProgScan = SCons.Scanner.Prog.ProgScan()
+def StaticObject():
+    """A function for generating the static object Builder."""
+    return SCons.Builder.Builder(action = {},
+                                 prefix = '$OBJPREFIX',
+                                 suffix = '$OBJSUFFIX',
+                                 src_builder = ['CFile', 'CXXFile'])
 
-Program = SCons.Builder.Builder(action=[ StaticCheck, '$LINKCOM' ],
-                                prefix='$PROGPREFIX',
-                                suffix='$PROGSUFFIX',
-                                src_suffix='$OBJSUFFIX',
-                                src_builder=StaticObject,
-                                scanner = ProgScan)
+def SharedObject():
+    """A function for generating the shared object Builder."""
+    return SCons.Builder.Builder(action = {},
+                                 prefix = '$OBJPREFIX',
+                                 suffix = '$OBJSUFFIX',
+                                 src_builder = ['CFile', 'CXXFile'])
 
-def win32LibGenerator(target, source, env, for_signature, no_import_lib=0):
-    listCmd = [ "$SHLINK", "$SHLINKFLAGS" ]
-
-    for tgt in target:
-        ext = os.path.splitext(str(tgt))[1]
-        if ext == env.subst("$LIBSUFFIX"):
-            # Put it on the command line as an import library.
-            if no_import_lib:
-                raise SCons.Errors.UserError, "%s: You cannot specify a .lib file as a target of a shared library build if no_import_library is nonzero." % tgt
-            listCmd.append("${WIN32IMPLIBPREFIX}%s" % tgt)
-        else:
-            listCmd.append("${WIN32DLLPREFIX}%s" % tgt)
-
-    listCmd.extend([ '$_LIBDIRFLAGS', '$_LIBFLAGS' ])
-    for src in source:
-        ext = os.path.splitext(str(src))[1]
-        if ext == env.subst("$WIN32DEFSUFFIX"):
-            # Treat this source as a .def file.
-            listCmd.append("${WIN32DEFPREFIX}%s" % src)
-        else:
-            # Just treat it as a generic source file.
-            listCmd.append(str(src))
-    return win32TempFileMunge(env, listCmd, for_signature)
-
-def win32LibEmitter(target, source, env, no_import_lib=0):
-    dll = None
-    for tgt in target:
-        ext = os.path.splitext(str(tgt))[1]
-        if ext == env.subst("$SHLIBSUFFIX"):
-            dll = tgt
-            break
-    if not dll:
-        raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
-        
-    if env.has_key("WIN32_INSERT_DEF") and \
-       env["WIN32_INSERT_DEF"] and \
-       not '.def' in map(lambda x: os.path.split(str(x))[1],
-                         source):
-
-        # append a def file to the list of sources
-        source.append("%s%s" % (os.path.splitext(str(dll))[0],
-                                env.subst("$WIN32DEFSUFFIX")))
-    if not no_import_lib and \
-       not env.subst("$LIBSUFFIX") in \
-       map(lambda x: os.path.split(str(x))[1], target):
-        # Append an import library to the list of targets.
-        target.append("%s%s%s" % (env.subst("$LIBPREFIX"),
-                                  os.path.splitext(str(dll))[0],
-                                  env.subst("$LIBSUFFIX")))
-    return (target, source)
+ProgScan = SCons.Scanner.Prog.ProgScan()
 
 StaticLibrary = SCons.Builder.Builder(action=[ StaticCheck, "$ARCOM" ],
                                       prefix = '$LIBPREFIX',
                                       suffix = '$LIBSUFFIX',
                                       src_suffix = '$OBJSUFFIX',
-                                      src_builder = StaticObject)
+                                      src_builder = 'Object')
 
 SharedLibrary = SCons.Builder.Builder(action=[ SharedCheck, "$SHLINKCOM" ],
-                                      emitter="$LIBEMITTER",
+                                      emitter="$SHLIBEMITTER",
                                       prefix = '$SHLIBPREFIX',
                                       suffix = '$SHLIBSUFFIX',
                                       scanner = ProgScan,
                                       src_suffix = '$OBJSUFFIX',
-                                      src_builder = SharedObject)
-
-LaTeXAction = SCons.Action.Action('$LATEXCOM')
-
-DVI = SCons.Builder.Builder(action = { '.tex'   : '$TEXCOM',
-                                       '.ltx'   : LaTeXAction,
-                                       '.latex' : LaTeXAction,
-                                     },
-                           # The suffix is not configurable via a
-                           # construction variable like $DVISUFFIX
-                           # because the output file name is
-                           # hard-coded within TeX.
-                            suffix = '.dvi')
-
-PDFLaTeXAction = SCons.Action.Action('$PDFLATEXCOM')
-
-PDF = SCons.Builder.Builder(action = { '.dvi'   : '$PDFCOM',
-                                       '.tex'   : '$PDFTEXCOM',
-                                       '.ltx'   : PDFLaTeXAction,
-                                       '.latex' : PDFLaTeXAction,
-                                     },
-                            prefix = '$PDFPREFIX',
-                            suffix = '$PDFSUFFIX')
-
-PostScript = SCons.Builder.Builder(action = '$PSCOM',
-                                   prefix = '$PSPREFIX',
-                                   suffix = '$PSSUFFIX',
-                                   src_suffix = '.dvi',
-                                   src_builder = DVI)
-
-CScan = SCons.Scanner.C.CScan()
-
-FortranScan = SCons.Scanner.Fortran.FortranScan()
+                                      src_builder = 'SharedObject')
+
+def DVI():
+    """Common function to generate a DVI file Builder."""
+    return SCons.Builder.Builder(action = {},
+                                 # The suffix is not configurable via a
+                                 # construction variable like $DVISUFFIX
+                                 # because the output file name is
+                                 # hard-coded within TeX.
+                                 suffix = '.dvi')
+
+def PDF():
+    """A function for generating the PDF Builder."""
+    return SCons.Builder.Builder(action = { },
+                                 prefix = '$PDFPREFIX',
+                                 suffix = '$PDFSUFFIX')
 
-def alias_builder(env, target, source):
-    pass
-
-Alias = SCons.Builder.Builder(action = alias_builder,
-                              target_factory = SCons.Node.Alias.default_ans.Alias,
-                              source_factory = SCons.Node.FS.default_fs.Entry,
-                              multi = 1)
+Program = SCons.Builder.Builder(action=[ StaticCheck, '$LINKCOM' ],
+                                prefix='$PROGPREFIX',
+                                suffix='$PROGSUFFIX',
+                                src_suffix='$OBJSUFFIX',
+                                src_builder='Object',
+                                scanner = ProgScan)
 
-def get_devstudio_versions ():
-    """
-    Get list of devstudio versions from the Windows registry.  Return a
-    list of strings containing version numbers; an exception will be raised
-    if we were unable to access the registry (eg. couldn't import
-    a registry-access module) or the appropriate registry keys weren't
-    found.
-    """
-
-    if not SCons.Util.can_read_reg:
-        raise SCons.Errors.InternalError, "No Windows registry module was found"
-
-    K = 'Software\\Microsoft\\Devstudio'
-    L = []
-    for base in (SCons.Util.HKEY_CLASSES_ROOT,
-                 SCons.Util.HKEY_LOCAL_MACHINE,
-                 SCons.Util.HKEY_CURRENT_USER,
-                 SCons.Util.HKEY_USERS):
-        try:
-            k = SCons.Util.RegOpenKeyEx(base,K)
-            i = 0
-            while 1:
-                try:
-                    p = SCons.Util.RegEnumKey(k,i)
-                    if p[0] in '123456789' and p not in L:
-                        L.append(p)
-                except SCons.Util.RegError:
-                    break
-                i = i + 1
-        except SCons.Util.RegError:
-            pass
-
-    if not L:
-        raise SCons.Errors.InternalError, "DevStudio was not found."
-
-    L.sort()
-    L.reverse()
-    return L
-
-def get_msvc_path (path, version, platform='x86'):
-    """
-    Get a list of devstudio directories (include, lib or path).  Return
-    a string delimited by ';'. An exception will be raised if unable to
-    access the registry or appropriate registry keys not found.
-    """
-
-    if not SCons.Util.can_read_reg:
-        raise SCons.Errors.InternalError, "No Windows registry module was found"
-
-    if path=='lib':
-        path= 'Library'
-    path = string.upper(path + ' Dirs')
-    K = ('Software\\Microsoft\\Devstudio\\%s\\' +
-         'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \
-        (version,platform)
-    for base in (SCons.Util.HKEY_CLASSES_ROOT,
-                 SCons.Util.HKEY_LOCAL_MACHINE,
-                 SCons.Util.HKEY_CURRENT_USER,
-                 SCons.Util.HKEY_USERS):
-        try:
-            k = SCons.Util.RegOpenKeyEx(base,K)
-            i = 0
-            while 1:
-                try:
-                    (p,v,t) = SCons.Util.RegEnumValue(k,i)
-                    if string.upper(p) == path:
-                        return v
-                    i = i + 1
-                except SCons.Util.RegError:
-                    break
-        except SCons.Util.RegError:
-            pass
-
-    # if we got here, then we didn't find the registry entries:
-    raise SCons.Errors.InternalError, "%s was not found in the registry."%path
-
-def get_msdev_dir(version):
-    """Returns the root directory of the MSDev installation from the
-    registry if it can be found, otherwise we guess."""
-    if SCons.Util.can_read_reg:
-        K = ('Software\\Microsoft\\Devstudio\\%s\\' +
-             'Products\\Microsoft Visual C++') % \
-             version
-        for base in (SCons.Util.HKEY_LOCAL_MACHINE,
-                     SCons.Util.HKEY_CURRENT_USER):
-            try:
-                k = SCons.Util.RegOpenKeyEx(base,K)
-                val, tok = SCons.Util.RegQueryValueEx(k, 'ProductDir')
-                return os.path.split(val)[0]
-            except SCons.Util.RegError:
-                pass
-
-def make_win32_env_from_paths(include, lib, path):
-    """
-    Build a dictionary of construction variables for a win32 platform.
-    include - include path
-    lib - library path
-    path - executable path
-    """
-    return {
-        'CC'         : 'cl',
-        'CCFLAGS'    : '/nologo',
-        'CCCOM'      : '$CC $CCFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET',
-        'SHCC'      : '$CC',
-        'SHCCFLAGS' : '$CCFLAGS',
-        'SHCCCOM'    : '$SHCC $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET',
-        'CFILESUFFIX' : '.c',
-        'CXX'        : '$CC',
-        'CXXFLAGS'   : '$CCFLAGS',
-        'CXXCOM'     : '$CXX $CXXFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET',
-        'SHCXX'      : '$CXX',
-        'SHCXXFLAGS' : '$CXXFLAGS',
-        'SHCXXCOM'   : '$SHCXX $SHCXXFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET',
-        'CXXFILESUFFIX' : '.cc',
-        'F77'        : 'g77',
-        'F77FLAGS'   : '',
-        'F77COM'     : '$F77 $F77FLAGS $_F77INCFLAGS /c $SOURCES /Fo$TARGET',
-        'F77PPCOM'   : '$F77 $F77FLAGS $CPPFLAGS $_F77INCFLAGS /c $SOURCES /Fo$TARGET',
-        'SHF77'      : '$F77',
-        'SHF77FLAGS' : '$F77FLAGS',
-        'SHF77COM'   : '$SHF77 $SHF77FLAGS $_F77INCFLAGS /c $SOURCES /Fo$TARGET',
-        'SHF77PPCOM' : '$SHF77 $SHF77FLAGS $CPPFLAGS $_F77INCFLAGS /c $SOURCES /Fo$TARGET',
-        'LINK'       : 'link',
-        'LINKFLAGS'  : '/nologo',
-        'LINKCOM'    : SCons.Action.CommandGenerator(win32LinkGenerator),
-        'SHLINK'     : '$LINK',
-        'SHLINKFLAGS': '$LINKFLAGS /dll',
-        'SHLINKCOM'  : SCons.Action.CommandGenerator(win32LibGenerator),
-        'AR'         : 'lib',
-        'ARFLAGS'    : '/nologo',
-        'ARCOM'      : '$AR $ARFLAGS /OUT:$TARGET $SOURCES',
-        'LEX'        : 'lex',
-        'LEXFLAGS'   : '',
-        'LEXCOM'     : '$LEX $LEXFLAGS -t $SOURCES > $TARGET',
-        'YACC'       : 'yacc',
-        'YACCFLAGS'  : '',
-        'YACCCOM'    : '$YACC $YACCFLAGS -o $TARGET $SOURCES',
-        'TEX'        : 'tex',
-        'TEXFLAGS'   : '',
-        'TEXCOM'     : '$TEX $TEXFLAGS $SOURCES',
-        'LATEX'      : 'latex',
-        'LATEXFLAGS' : '',
-        'LATEXCOM'   : '$LATEX $LATEXFLAGS $SOURCES',
-        'DVIPDF'     : 'dvipdf',
-        'DVIPDFFLAGS' : '',
-        'PDFCOM'     : '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET',
-        'PDFPREFIX'  : '',
-        'PDFSUFFIX'  : '.pdf',
-        'PDFTEX'     : 'pdftex',
-        'PDFTEXFLAGS' : '',
-        'PDFTEXCOM'  : '$PDFTEX $PDFTEXFLAGS $SOURCES $TARGET',
-        'PDFLATEX'   : 'pdflatex',
-        'PDFLATEXFLAGS' : '',
-        'PDFLATEXCOM' : '$PDFLATEX $PDFLATEXFLAGS $SOURCES $TARGET',
-        'DVIPS'      : 'dvips',
-        'DVIPSFLAGS' : '',
-        'PSCOM'      : '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES',
-        'PSPREFIX'   : '',
-        'PSSUFFIX'   : '.ps',
-        'BUILDERS'   : { 'Alias'          : Alias,
-                         'CFile'          : CFile,
-                         'CXXFile'        : CXXFile,
-                         'DVI'            : DVI,
-                         'Library'        : StaticLibrary,
-                         'StaticLibrary'  : StaticLibrary,
-                         'SharedLibrary'  : SharedLibrary,
-                         'Object'         : StaticObject,
-                         'StaticObject'   : StaticObject,
-                         'SharedObject'   : SharedObject,
-                         'PDF'            : PDF,
-                         'PostScript'     : PostScript,
-                         'Program'        : Program },
-        'SCANNERS'   : [CScan, FortranScan],
-        'LIBDIRPREFIX'          : '/LIBPATH:',
-        'LIBDIRSUFFIX'          : '',
-        'LIBLINKPREFIX'         : '',
-        'LIBLINKSUFFIX'         : '$LIBSUFFIX',
-        'LIBEMITTER'            : win32LibEmitter,
-        'INCPREFIX'             : '/I',
-        'INCSUFFIX'             : '',
-        'WIN32DEFPREFIX'        : '/def:',
-        'WIN32DEFSUFFIX'        : '.def',
-        'WIN32DLLPREFIX'        : '/out:',
-        'WIN32IMPLIBPREFIX'     : '/implib:',
-        'WIN32_INSERT_DEF'      : 0,
-        'ENV'        : {
-            'INCLUDE'  : include,
-            'LIB'      : lib,
-            'PATH'     : path,
-            },
-        }
-
-def make_win32_env(version):
-    """
-    Build a dictionary of construction variables for a win32 platform.
-    ver - the version string of DevStudio to use (e.g. "6.0")
-    """
-    return make_win32_env_from_paths(get_msvc_path("include", version),
-                                     get_msvc_path("lib", version),
-                                     get_msvc_path("path", version)
-                                     + ";" + os.environ['PATH'])
-
-
-if os.name == 'posix':
-    arcom = '$AR $ARFLAGS $TARGET $SOURCES'
-    ranlib = 'ranlib'
-    if SCons.Util.WhereIs(ranlib):
-        arcom = arcom + '\n$RANLIB $RANLIBFLAGS $TARGET'
-
-    ConstructionEnvironment = {
-        'CC'         : 'cc',
-        'CCFLAGS'    : '',
-        'CCCOM'      : '$CC $CCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES',
-        'SHCC'       : '$CC',
-        'SHCCFLAGS'  : '$CCFLAGS -fPIC',
-        'SHCCCOM'    : '$SHCC $SHCCFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES',
-        'CFILESUFFIX' : '.c',
-        'CXX'        : 'c++',
-        'CXXFLAGS'   : '$CCFLAGS',
-        'CXXCOM'     : '$CXX $CXXFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES',
-        'CXXFILESUFFIX' : '.cc',
-        'SHCXX'      : '$CXX',
-        'SHCXXFLAGS' : '$CXXFLAGS -fPIC',
-        'SHCXXCOM'   : '$SHCXX $SHCXXFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES',
-        'F77'        : 'g77',
-        'F77FLAGS'   : '',
-        'F77COM'     : '$F77 $F77FLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
-        'F77PPCOM'   : '$F77 $F77FLAGS $CPPFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
-        'SHF77FLAGS' : '$F77FLAGS -fPIC',
-        'SHF77COM'   : '$F77 $SHF77FLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
-        'SHF77PPCOM' : '$F77 $SHF77FLAGS $CPPFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
-        'SHF77'      : '$F77',
-        'SHF77FLAGS' : '$F77FLAGS -fPIC',
-        'SHF77COM'   : '$SHF77 $SHF77FLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
-        'SHF77PPCOM' : '$SHF77 $SHF77FLAGS $CPPFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
-        'LINK'       : '$CXX',
-        'LINKFLAGS'  : '',
-        'LINKCOM'    : '$LINK $LINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS',
-        'SHLINK'     : '$LINK',
-        'SHLINKFLAGS': '$LINKFLAGS -shared',
-        'SHLINKCOM'  : '$SHLINK $SHLINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS',
-        'AR'         : 'ar',
-        'ARFLAGS'    : 'r',
-        'RANLIB'     : ranlib,
-        'RANLIBFLAGS' : '',
-        'ARCOM'      : arcom,
-        'LEX'        : 'lex',
-        'LEXFLAGS'   : '',
-        'LEXCOM'     : '$LEX $LEXFLAGS -t $SOURCES > $TARGET',
-        'YACC'       : 'yacc',
-        'YACCFLAGS'  : '',
-        'YACCCOM'    : '$YACC $YACCFLAGS -o $TARGET $SOURCES',
-        'TEX'        : 'tex',
-        'TEXFLAGS'   : '',
-        'TEXCOM'     : '$TEX $TEXFLAGS $SOURCES',
-        'LATEX'      : 'latex',
-        'LATEXFLAGS' : '',
-        'LATEXCOM'   : '$LATEX $LATEXFLAGS $SOURCES',
-        'DVIPDF'     : 'dvipdf',
-        'PDFCOM'     : '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET',
-        'PDFPREFIX'  : '',
-        'PDFSUFFIX'  : '.pdf',
-        'PDFTEX'     : 'pdftex',
-        'PDFTEXFLAGS' : '',
-        'PDFTEXCOM'  : '$PDFTEX $PDFTEXFLAGS $SOURCES $TARGET',
-        'PDFLATEX'   : 'pdflatex',
-        'PDFLATEXFLAGS' : '',
-        'PDFLATEXCOM' : '$PDFLATEX $PDFLATEXFLAGS $SOURCES $TARGET',
-        'DVIPS'      : 'dvips',
-        'PSCOM'      : '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES',
-        'PSPREFIX'   : '',
-        'PSSUFFIX'   : '.ps',
-        'BUILDERS'   : { 'Alias'          : Alias,
-                         'CFile'          : CFile,
-                         'CXXFile'        : CXXFile,
-                         'DVI'            : DVI,
-                         'Library'        : StaticLibrary,
-                         'StaticLibrary'  : StaticLibrary,
-                         'SharedLibrary'  : SharedLibrary,
-                         'Object'         : StaticObject,
-                         'StaticObject'   : StaticObject,
-                         'SharedObject'   : SharedObject,
-                         'PDF'            : PDF,
-                         'PostScript'     : PostScript,
-                         'Program'        : Program },
-        'SCANNERS'   : [CScan, FortranScan],
-        'LIBDIRPREFIX'          : '-L',
-        'LIBDIRSUFFIX'          : '',
-        'LIBLINKPREFIX'         : '-l',
-        'LIBLINKSUFFIX'         : '',
-        'INCPREFIX'             : '-I',
-        'INCSUFFIX'             : '',
+ConstructionEnvironment = {
+    'BUILDERS'   : { 'SharedLibrary'  : SharedLibrary,
+                     'Library'        : StaticLibrary,
+                     'StaticLibrary'  : StaticLibrary,
+                     'Alias'          : Alias,    
+                     'Program'        : Program },
+    'SCANNERS'   : [CScan, FortranScan],
+    'PDFPREFIX'  : '',
+    'PDFSUFFIX'  : '.pdf',
+    'PSPREFIX'   : '',
+    'PSSUFFIX'   : '.ps',
+    'ENV'        : {},
     }
-
-elif os.name == 'nt':
-    versions = None
-    try:
-        versions = get_devstudio_versions()
-        ConstructionEnvironment = make_win32_env(versions[0]) #use highest version
-    except (SCons.Util.RegError, SCons.Errors.InternalError):
-        # Could not get the configured directories from the registry.
-        # However, the configured directories only appear if the user
-        # changes them from the default.  Therefore, we'll see if
-        # we can get the path to the MSDev base installation from
-        # the registry and deduce the default directories.
-        MVSdir = None
-        if versions:
-            MVSdir = get_msdev_dir(versions[0])
-        if MVSdir:
-            MVSVCdir = r'%s\VC98' % MVSdir
-            MVSCommondir = r'%s\Common' % MVSdir
-            try:
-                extra_path = os.pathsep + os.environ['PATH']
-            except KeyError:
-                extra_path = ''
-            ConstructionEnvironment = make_win32_env_from_paths(
-                r'%s\atl\include;%s\mfc\include;%s\include' % (MVSVCdir, MVSVCdir, MVSVCdir),
-                r'%s\mfc\lib;%s\lib' % (MVSVCdir, MVSVCdir),
-                (r'%s\MSDev98\Bin;%s\Bin' % (MVSCommondir, MVSVCdir)) + extra_path)
-        else:
-            # The DevStudio environment variables don't exist,
-            # so just use the variables from the source environment.
-            MVSdir = r'C:\Program Files\Microsoft Visual Studio'
-            MVSVCdir = r'%s\VC98' % MVSdir
-            MVSCommondir = r'%s\Common' % MVSdir
-            try:
-                include_path = os.environ['INCLUDE']
-            except KeyError:
-                include_path = ''
-            try:
-                lib_path = os.environ['LIB']
-            except KeyError:
-                lib_path = ''
-            try:
-                exe_path = os.environ['PATH']
-            except KeyError:
-                exe_path = ''
-            ConstructionEnvironment = make_win32_env_from_paths(
-                include_path,
-                lib_path,
-                exe_path)
index a95adf99ef3f354c3bc944d621d6d9cec00ade45..30e0a536b57ce07f05da91cc56c3b9f27cbf0556 100644 (file)
@@ -47,6 +47,8 @@ import SCons.Node.FS
 import SCons.Util
 import SCons.Warnings
 from UserDict import UserDict
+import SCons.Platform
+import SCons.Tool
 
 def installFunc(env, target, source):
     try:
@@ -117,12 +119,19 @@ class Environment:
     Environment.
     """
 
-    def __init__(self, platform=SCons.Platform.Platform(), **kw):
+    def __init__(self,
+                 platform=SCons.Platform.Platform(),
+                 tools=SCons.Platform.DefaultToolList(),
+                 **kw):
         self.fs = SCons.Node.FS.default_fs
         self._dict = our_deepcopy(SCons.Defaults.ConstructionEnvironment)
         if SCons.Util.is_String(platform):
             platform = SCons.Platform.Platform(platform)
         platform(self)
+        for tool in tools:
+            if SCons.Util.is_String(tool):
+                tool = SCons.Tool.Tool(tool)
+            tool(self, platform)
         apply(self.Replace, (), kw)
 
         #
@@ -231,14 +240,7 @@ class Environment:
                 for name, builder in bd.items():
                     setattr(self, name, BuilderWrapper(self, builder))
             else:
-                SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
-                                    "The use of the BUILDERS Environment variable as a list or Builder instance is deprecated.  BUILDERS should be a dictionary of name->Builder instead.")
-                
-                if not SCons.Util.is_List(self._dict['BUILDERS']):
-                    self._dict['BUILDERS'] = [self._dict['BUILDERS']]
-                for b in self._dict['BUILDERS']:
-                    setattr(self, b.name, BuilderWrapper(self, b))
-
+                raise UserError, "The use of the BUILDERS Environment variable as a list or Builder instance is deprecated.  BUILDERS should be a dictionary of name->Builder instead."
         for s in self._dict['SCANNERS']:
             setattr(self, s.name, s)
         
@@ -392,6 +394,14 @@ class Environment:
             interp.instance(dir, fs).generate(dict, self._dict)
         return dict
 
+    def get_builder(self, name):
+        """Fetch the builder with the specified name from the environment.
+        """
+        try:
+            return self._dict['BUILDERS'][name]
+        except KeyError:
+            return None
+
 class VarInterpolator:
     def __init__(self, dest, src, prefix, suffix):
         self.dest = dest
index 167c662af2bff7af82ddda1238596f65ed99d9ca..2e7003ac1ee3e08a13091c1c1bbdc3cd8b3f6969 100644 (file)
@@ -30,6 +30,27 @@ import unittest
 from SCons.Environment import *
 import SCons.Warnings
 
+def diff_env(env1, env2):
+    s1 = "env1 = {\n"
+    s2 = "env2 = {\n"
+    d = {}
+    for k in env1._dict.keys() + env2._dict.keys():
+       d[k] = None
+    keys = d.keys()
+    keys.sort()
+    for k in keys:
+        if env1.has_key(k):
+           if env2.has_key(k):
+               if env1[k] != env2[k]:
+                   s1 = s1 + "    " + repr(k) + " : " + repr(env1[k]) + "\n"
+                   s2 = s2 + "    " + repr(k) + " : " + repr(env2[k]) + "\n"
+           else:
+               s1 = s1 + "    " + repr(k) + " : " + repr(env1[k]) + "\n"
+        elif env2.has_key(k):
+           s2 = s2 + "    " + repr(k) + " : " + repr(env2[k]) + "\n"
+    s1 = s1 + "}\n"
+    s2 = s2 + "}\n"
+    return s1 + s2
 
 built_it = {}
 
@@ -74,23 +95,13 @@ class EnvironmentTestCase(unittest.TestCase):
        """
        global built_it
 
-       b1 = Builder(name = 'builder1')
-       b2 = Builder(name = 'builder2')
-
-        # BUILDERS as a list or instance, now deprecated...
-       built_it = {}
-       env1 = Environment(BUILDERS = b1)
-       env1.builder1.execute(target = 'out1')
-       assert built_it['out1']
-
-       built_it = {}
-       env2 = Environment(BUILDERS = [b1])
-       env1.builder1.execute(target = 'out1')
-       assert built_it['out1']
+       b1 = Builder()
+       b2 = Builder()
 
        built_it = {}
         env3 = Environment()
-        env3.Replace(BUILDERS = [b1, b2])
+        env3.Replace(BUILDERS = { 'builder1' : b1,
+                                  'builder2' : b2 })
        env3.builder1.execute(target = 'out1')
        env3.builder2.execute(target = 'out2')
        env3.builder1.execute(target = 'out3')
@@ -120,29 +131,6 @@ class EnvironmentTestCase(unittest.TestCase):
         assert built_it['out1']
         assert built_it['out2']
 
-        # Now test deprecated warning for BUILDERS as a list
-        # or instance.
-
-        SCons.Warnings.enableWarningClass(SCons.Warnings.DeprecatedWarning)
-        SCons.Warnings.warningAsException(1)
-        try:
-            try:
-                env=Environment(BUILDERS=b1)
-            except SCons.Warnings.DeprecatedWarning:
-                pass
-            else:
-                assert 0
-
-            try:
-                env=Environment(BUILDERS=[b1, b2])
-            except SCons.Warnings.DeprecatedWarning:
-                pass
-            else:
-                assert 0
-        finally:
-            SCons.Warnings.suppressWarningClass(SCons.Warnings.DeprecatedWarning)
-            SCons.Warnings.warningAsException(0)
-
     def test_Scanners(self):
         """Test Scanner execution through different environments
 
@@ -261,7 +249,7 @@ class EnvironmentTestCase(unittest.TestCase):
        """
        env1 = Environment(XXX = 'x', YYY = 'y')
        env2 = Environment(XXX = 'x', YYY = 'y')
-       assert env1 == env2
+       assert env1 == env2, diff_env(env1, env2)
 
     def test_Install(self):
        """Test Install and InstallAs methods"""
@@ -292,7 +280,7 @@ class EnvironmentTestCase(unittest.TestCase):
         env1 = Environment(AAA = 'a', BBB = 'b')
         env1.Replace(BBB = 'bbb', CCC = 'ccc')
         env2 = Environment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
-        assert env1 == env2
+        assert env1 == env2, diff_env(env1, env2)
 
     def test_Append(self):
         """Test appending to construction variables in an Environment
@@ -312,7 +300,7 @@ class EnvironmentTestCase(unittest.TestCase):
                            GGG = ['g', 'G'], HHH = UL(['h', 'H']),
                            III = UL(['i']), JJJ = UL(['j', 'J']),
                            KKK = UL(['k', 'K']), LLL = UL(['l', 'L']))
-        assert env1 == env2, env1._dict
+        assert env1 == env2, diff_env(env1, env2)
 
         env3 = Environment(X = {'x' : 7})
         try:
@@ -479,7 +467,15 @@ class EnvironmentTestCase(unittest.TestCase):
         env = Environment(platform = p)
         assert env['XYZZY'] == 777, env
 
-
+    def test_tools(self):
+        """Test specifying a tool callable when instantiating."""
+        def t1(env, platform):
+            env['TOOL1'] = 111
+        def t2(env, platform):
+            env['TOOL2'] = 222
+        env = Environment(tools = [t1, t2])
+        assert env['TOOL1'] == 111, env['TOOL1']
+        assert env['TOOL2'] == 222, env
 
 if __name__ == "__main__":
     suite = unittest.makeSuite(EnvironmentTestCase, 'test_')
index a519142460ba9e3f6ee0bb36a69112eea60745d0..42b2607205e65dfc67532c7fc055331b4d32e235 100644 (file)
@@ -61,15 +61,8 @@ def platform_default():
         return 'posix'
     return None
 
-class PlatformSpec:
-    def __init__(self, name):
-        self.name = name
-
-    def __str__(self):
-        return self.name
-    
-def Platform(name = platform_default()):
-    """Select a canned Platform specification.
+def platform_module(name = platform_default()):
+    """Return the imported module for the platform.
 
     This looks for a module name that matches the specified argument.
     If the name is unspecified, we fetch the appropriate default for
@@ -85,6 +78,25 @@ def Platform(name = platform_default()):
             raise SCons.Errors.UserError, "No platform named '%s'" % name
         if file:
             file.close()
+    return sys.modules[full_name]
+
+def DefaultToolList(name = platform_default()):
+    """Select a default tool list for the specified platform.
+    """
+    module = platform_module(name)
+    return module.tool_list()
+
+class PlatformSpec:
+    def __init__(self, name):
+        self.name = name
+
+    def __str__(self):
+        return self.name
+    
+def Platform(name = platform_default()):
+    """Select a canned Platform specification.
+    """
+    module = platform_module(name)
     spec = PlatformSpec(name)
-    spec.__call__ = sys.modules[full_name].generate
+    spec.__call__ = module.generate
     return spec
index 7faafd8157d033eadee7379c57b2b6e5f5ea583d..6a21ae9a1ec24ed11efb17d7427cb8587ff99201 100644 (file)
@@ -32,6 +32,10 @@ selection method.
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+def tool_list():
+    return ['ar', 'dvipdf', 'dvips', 'g++', 'g77', 'gcc', 'latex', 'lex',
+            'pdflatex', 'pdftex', 'tex', 'yacc', 'gnulink' ]
+
 def generate(env):
     if not env.has_key('ENV'):
         env['ENV']        = {}
index 4de68f66cd7f9fbafeda3cd07d9fd0492b47d71a..3d20263a9fa60513800840d1dd4bad30453719a0 100644 (file)
@@ -32,6 +32,10 @@ selection method.
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+def tool_list():
+    return ['ar', 'dvipdf', 'dvips', 'g++', 'g77', 'gcc', 'latex', 'lex',
+            'pdflatex', 'pdftex', 'tex', 'yacc', 'gnulink' ]
+
 def generate(env):
     if not env.has_key('ENV'):
         env['ENV']        = {}
index aa9a75f8ed2559025aeede8150c80e59f64afe7c..9bcea18e9a449316728ab9d18ae41c963b6da5ea 100644 (file)
@@ -32,6 +32,10 @@ selection method.
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+def tool_list():
+    return ['dvipdf', 'latex', 'dvips', 'g77', 'lex', 'lib', 'msvc',
+            'pdflatex', 'pdftex', 'tex', 'yacc', 'mslink' ]
+
 def generate(env):
     if not env.has_key('ENV'):
         env['ENV']        = {}
index 7fcdf7795c15e4b15c879d58b6ebce0f6da69917..7ae7f219aa247f34e0287a1c92e6ea4aa0849b07 100644 (file)
@@ -37,6 +37,7 @@ import SCons.Errors
 import SCons.Node
 import SCons.Node.FS
 import SCons.Platform
+import SCons.Tool
 import SCons.Util
 
 import os
@@ -273,5 +274,6 @@ def BuildDefaultGlobals():
     globals['SConscriptChdir']   = SConscriptChdir
     globals['SetCommandHandler'] = SCons.Action.SetCommandHandler
     globals['Split']             = SCons.Util.Split
+    globals['Tool']              = SCons.Tool.Tool
     globals['WhereIs']           = SCons.Util.WhereIs
     return globals
index 347119020e65c89fa0042869b7505df1a80981ed..c43f1ab309c76779a73c7d61030941dadc6890fc 100644 (file)
@@ -99,6 +99,7 @@ class BuildTask(SCons.Taskmaster.Task):
                 # We aren't being called out of a user frame, so
                 # don't try to walk the stack, just print the error.
                 sys.stderr.write("\nSCons error: %s\n" % e)
+                raise
            except:
                sys.stderr.write("scons: *** %s\n" % sys.exc_value)
                raise
@@ -982,6 +983,8 @@ def _main():
         SCons.Sig.write()
 
 def main():
+    global exit_status
+    
     try:
        _main()
     except SystemExit:
diff --git a/src/engine/SCons/Tool/ToolTests.py b/src/engine/SCons/Tool/ToolTests.py
new file mode 100644 (file)
index 0000000..a7e03e8
--- /dev/null
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import sys
+import unittest
+
+import SCons.Errors
+import SCons.Tool
+
+class ToolTestCase(unittest.TestCase):
+    def test_Tool(self):
+        """Test the Tool() function"""
+        t = SCons.Tool.Tool('g++')
+        env= { 'BUILDERS' : {}, 'ENV' : {} }
+        t(env, 'foo')
+        assert env['CXX'] == 'c++', env['CXX']
+        assert env['CXXFLAGS'] == '$CCFLAGS', env['CXXFLAGS']
+        assert env['INCPREFIX'] == '-I', env['INCPREFIX']
+
+        try:
+            SCons.Tool.Tool()
+        except TypeError:
+            pass
+        else:
+            raise
+
+        try:
+            p = SCons.Tool.Tool('_does_not_exist_')
+        except SCons.Errors.UserError:
+            pass
+        else:
+            raise
+
+
+if __name__ == "__main__":
+    suite = unittest.makeSuite(ToolTestCase, 'test_')
+    if not unittest.TextTestRunner().run(suite).wasSuccessful():
+        sys.exit(1)
diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py
new file mode 100644 (file)
index 0000000..08ab5c2
--- /dev/null
@@ -0,0 +1,125 @@
+"""SCons.Tool
+
+SCons tool selection.
+
+This looks for modules that define a callable object that can modify
+a construction environment as appropriate for a given tool (or tool
+chain).
+
+Note that because this subsysem just *selects* a callable that can
+modify a construction environment, it's possible for people to define
+their own "tool specification" in an arbitrary callable function.  No
+one needs to use or tie in to this subsystem in order to roll their own
+tool definition.
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+# 
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import imp
+import os
+import sys
+
+import SCons.Errors
+import SCons.Defaults
+
+class ToolSpec:
+    def __init__(self, name):
+        self.name = name
+
+    def __str__(self):
+        return self.name
+    
+def Tool(name, platform = None):
+    """Select a canned Tool specification.
+    """
+    full_name = 'SCons.Tool.' + name
+    if not sys.modules.has_key(full_name):
+        try:
+            file, path, desc = imp.find_module(name,
+                                        sys.modules['SCons.Tool'].__path__)
+            imp.load_module(full_name, file, path, desc)
+        except ImportError:
+            raise SCons.Errors.UserError, "No tool named '%s'" % name
+        if file:
+            file.close()
+    spec = ToolSpec(name)
+    spec.__call__ = sys.modules[full_name].generate
+    return spec
+
+def createObjBuilders(env):
+    """This is a utility function that creates the Object
+    and SharedObject Builders in an Environment if they
+    are not there already.
+
+    If they are there already, we return the existing ones.
+
+    This is a separate function because soooo many Tools
+    use this functionality.
+
+    The return is a 2-tuple of (StaticObject, SharedObject)
+    """
+
+    try:
+        static_obj = env['BUILDERS']['Object']
+    except KeyError:
+        static_obj = SCons.Defaults.StaticObject()
+        env['BUILDERS']['Object'] = static_obj
+        env['BUILDERS']['StaticObject'] = static_obj
+
+    try:
+        shared_obj = env['BUILDERS']['SharedObject']
+    except KeyError:
+        shared_obj = SCons.Defaults.SharedObject()
+        env['BUILDERS']['SharedObject'] = shared_obj
+
+    return (static_obj, shared_obj)
+
+def createCFileBuilders(env):
+    """This is a utility function that creates the CFile/CXXFile
+    Builders in an Environment if they
+    are not there already.
+
+    If they are there already, we return the existing ones.
+
+    This is a separate function because soooo many Tools
+    use this functionality.
+
+    The return is a 2-tuple of (CFile, CXXFile)
+    """
+
+    try:
+        c_file = env['BUILDERS']['CFile']
+    except KeyError:
+        c_file = SCons.Defaults.CFile()
+        env['BUILDERS']['CFile'] = c_file
+
+    try:
+        cxx_file = env['BUILDERS']['CXXFile']
+    except KeyError:
+        cxx_file = SCons.Defaults.CXXFile()
+        env['BUILDERS']['CXXFile'] = cxx_file
+
+    return (c_file, cxx_file)
diff --git a/src/engine/SCons/Tool/ar.py b/src/engine/SCons/Tool/ar.py
new file mode 100644 (file)
index 0000000..ab870b6
--- /dev/null
@@ -0,0 +1,59 @@
+"""SCons.Tool.ar
+
+Tool-specific initialization for ar (library archive).
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Defaults
+import SCons.Util
+
+def generate(env, platform):
+    """Add Builders and construction variables for ar to an Environment."""
+    bld = SCons.Defaults.StaticLibrary
+    env['BUILDERS']['Library'] = bld
+    env['BUILDERS']['StaticLibrary'] = bld
+    
+    arcom = '$AR $ARFLAGS $TARGET $SOURCES'
+    ranlib = 'ranlib'
+    if SCons.Util.WhereIs(ranlib):
+        arcom = arcom + '\n$RANLIB $RANLIBFLAGS $TARGET'
+
+    env['AR']          = 'ar'
+    env['ARFLAGS']     = 'r'
+    env['RANLIB']      = ranlib
+    env['RANLIBFLAGS'] = ''
+    env['ARCOM']       = arcom
+    env['SHLINK']      = '$LINK'
+    env['SHLINKFLAGS'] = '$LINKFLAGS -shared'
+    env['SHLINKCOM']   = '$SHLINK $SHLINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'
+
+
diff --git a/src/engine/SCons/Tool/dvipdf.py b/src/engine/SCons/Tool/dvipdf.py
new file mode 100644 (file)
index 0000000..230ce92
--- /dev/null
@@ -0,0 +1,49 @@
+"""SCons.Tool.dvipdf
+
+Tool-specific initialization for dvipdf.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Defaults
+
+def generate(env, platform):
+    """Add Builders and construction variables for dvipdf to an Environment."""
+    try:
+        bld = env['BUILDERS']['PDF']
+    except KeyError:
+        bld = SCons.Defaults.PDF()
+        env['BUILDERS']['PDF'] = bld
+    bld.add_action('.dvi', '$PDFCOM')
+
+    env['DVIPDF']      = 'dvipdf'
+    env['DVIPDFFLAGS'] = ''
+    env['PDFCOM']      = '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET'
diff --git a/src/engine/SCons/Tool/dvips.py b/src/engine/SCons/Tool/dvips.py
new file mode 100644 (file)
index 0000000..098cba7
--- /dev/null
@@ -0,0 +1,51 @@
+"""SCons.Tool.dvips
+
+Tool-specific initialization for dvips.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Action
+import SCons.Defaults
+
+PostScript = SCons.Builder.Builder(action = '$PSCOM',
+                                   prefix = '$PSPREFIX',
+                                   suffix = '$PSSUFFIX',
+                                   src_suffix = '.dvi',
+                                   src_builder = 'DVI')
+
+def generate(env, platform):
+    """Add Builders and construction variables for dvips to an Environment."""
+    env['BUILDERS']['PostScript'] = PostScript
+    
+    env['DVIPS']      = 'dvips'
+    env['DVIPSFLAGS'] = ''
+    env['PSCOM']      = '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES'
diff --git a/src/engine/SCons/Tool/g++.py b/src/engine/SCons/Tool/g++.py
new file mode 100644 (file)
index 0000000..a903b0a
--- /dev/null
@@ -0,0 +1,62 @@
+"""SCons.Tool.g++
+
+Tool-specific initialization for g++.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os.path
+
+import SCons.Defaults
+import SCons.Tool
+
+CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
+if os.path.normcase('.c') != os.path.normcase('.C'):
+    CXXSuffixes.append('.C')
+
+def generate(env, platform):
+    """Add Builders and construction variables for g++ to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in CXXSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CXXAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
+
+    env['CXX']        = 'c++'
+    env['CXXFLAGS']   = '$CCFLAGS'
+    env['CXXCOM']     = '$CXX $CXXFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
+    env['SHCXX']      = '$CXX'
+    env['SHCXXFLAGS'] = '$CXXFLAGS -fPIC'
+    env['SHCXXCOM']   = '$SHCXX $SHCXXFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
+    env['INCPREFIX']  = '-I'
+    env['INCSUFFIX']  = ''
+
+    env['CXXFILESUFFIX'] = '.cc'
diff --git a/src/engine/SCons/Tool/g77.py b/src/engine/SCons/Tool/g77.py
new file mode 100644 (file)
index 0000000..dbafcf2
--- /dev/null
@@ -0,0 +1,67 @@
+"""engine.SCons.Tool.g77
+
+Tool-specific initialization for g77.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os.path
+
+import SCons.Defaults
+import SCons.Tool
+
+F77Suffixes = ['.f', '.for', '.FOR']
+F77PPSuffixes = ['.fpp', '.FPP']
+if os.path.normcase('.f') == os.path.normcase('.F'):
+    F77Suffixes.append('.F')
+else:
+    F77PPSuffixes.append('.F')
+
+def generate(env, platform):
+    """Add Builders and construction variables for g77 to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in F77Suffixes:
+        static_obj.add_action(suffix, SCons.Defaults.F77Action)
+        shared_obj.add_action(suffix, SCons.Defaults.ShF77Action)
+
+    for suffix in F77PPSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.F77PPAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShF77PPAction)
+
+    env['F77']        = 'g77'
+    env['F77FLAGS']   = ''
+    env['F77COM']     = '$F77 $F77FLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES'
+    env['F77PPCOM']   = '$F77 $F77FLAGS $CPPFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES'
+    env['SHF77']      = '$F77'
+    env['SHF77FLAGS'] = '$F77FLAGS -fPIC'
+    env['SHF77COM']   = '$SHF77 $SHF77FLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES'
+    env['SHF77PPCOM'] = '$SHF77 $SHF77FLAGS $CPPFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES'
diff --git a/src/engine/SCons/Tool/gcc.py b/src/engine/SCons/Tool/gcc.py
new file mode 100644 (file)
index 0000000..c5a1e91
--- /dev/null
@@ -0,0 +1,63 @@
+"""SCons.Tool.gcc
+
+Tool-specific initialization for gcc.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os.path
+
+import SCons.Tool
+import SCons.Defaults
+
+CSuffixes = ['.c']
+if os.path.normcase('.c') == os.path.normcase('.C'):
+    CSuffixes.append('.C')
+
+def generate(env, platform):
+    """Add Builders and construction variables for gcc to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in CSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
+
+    env['CC']        = 'gcc'
+    env['CCFLAGS']   = ''
+    env['CCCOM']     = '$CC $CCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
+    env['SHCC']      = '$CC'
+    env['SHCCFLAGS'] = '$CCFLAGS -fPIC'
+    env['SHCCCOM']   = '$SHCC $SHCCFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
+
+    env['INCPREFIX']  = '-I'
+    env['INCSUFFIX']  = ''
+
+    env['CFILESUFFIX'] = '.c'
diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py
new file mode 100644 (file)
index 0000000..630d95a
--- /dev/null
@@ -0,0 +1,54 @@
+"""SCons.Tool.gnulink
+
+Tool-specific initialization for the gnu linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Defaults
+import SCons.Util
+
+def generate(env, platform):
+    """Add Builders and construction variables for ar to an Environment."""
+    env['BUILDERS']['SharedLibrary'] = SCons.Defaults.SharedLibrary
+    env['BUILDERS']['Program'] = SCons.Defaults.Program
+    
+    env['SHLINK']      = '$LINK'
+    env['SHLINKFLAGS'] = '$LINKFLAGS -shared'
+    env['SHLINKCOM']   = '$SHLINK $SHLINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'
+    env['SHLIBEMITTER']= None
+    env['LINK']        = 'c++'
+    env['LINKFLAGS']   = ''
+    env['LINKCOM']     = '$LINK $LINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'
+    env['LIBDIRPREFIX']='-L'
+    env['LIBDIRSUFFIX']=''
+    env['LIBLINKPREFIX']='-l'
+    env['LIBLINKSUFFIX']=''
diff --git a/src/engine/SCons/Tool/latex.py b/src/engine/SCons/Tool/latex.py
new file mode 100644 (file)
index 0000000..cb53ccf
--- /dev/null
@@ -0,0 +1,55 @@
+"""SCons.Tool.latex
+
+Tool-specific initialization for LaTeX.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Action
+import SCons.Defaults
+
+LaTeXAction = SCons.Action.Action('$LATEXCOM')
+
+def generate(env, platform):
+    """Add Builders and construction variables for LaTeX to an Environment."""
+
+    try:
+        bld = env['BUILDERS']['DVI']
+    except KeyError:
+        bld = SCons.Defaults.DVI()
+        env['BUILDERS']['DVI'] = bld
+        
+    bld.add_action('.ltx', LaTeXAction)
+    bld.add_action('.latex', LaTeXAction)
+
+    env['LATEX']      = 'latex'
+    env['LATEXFLAGS'] = ''
+    env['LATEXCOM']   = '$LATEX $LATEXFLAGS $SOURCES'
diff --git a/src/engine/SCons/Tool/lex.py b/src/engine/SCons/Tool/lex.py
new file mode 100644 (file)
index 0000000..c8851e2
--- /dev/null
@@ -0,0 +1,48 @@
+"""SCons.Tool.lex
+
+Tool-specific initialization for lex.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Defaults
+import SCons.Tool
+
+def generate(env, platform):
+    """Add Builders and construction variables for lex to an Environment."""
+    c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
+
+    c_file.add_action('.l', '$LEXCOM')
+    cxx_file.add_action('.ll', '$LEXCOM')
+
+    env['LEX']      = 'lex'
+    env['LEXFLAGS'] = ''
+    env['LEXCOM']   = '$LEX $LEXFLAGS -t $SOURCES > $TARGET'
diff --git a/src/engine/SCons/Tool/lib.py b/src/engine/SCons/Tool/lib.py
new file mode 100644 (file)
index 0000000..9683abf
--- /dev/null
@@ -0,0 +1,46 @@
+"""SCons.Tool.lib
+
+Tool-specific initialization for lib (MicroSoft library archiver).
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Defaults
+
+def generate(env, platform):
+    """Add Builders and construction variables for lib to an Environment."""
+    env['BUILDERS']['Library'] = SCons.Defaults.StaticLibrary
+    env['BUILDERS']['StaticLibrary'] = SCons.Defaults.StaticLibrary
+    
+    env['AR']          = 'lib'
+    env['ARFLAGS']     = '/nologo'
+    env['ARCOM']       = '$AR $ARFLAGS /OUT:$TARGET $SOURCES'
+    
diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py
new file mode 100644 (file)
index 0000000..2f05b46
--- /dev/null
@@ -0,0 +1,151 @@
+"""SCons.Tool.mslink
+
+Tool-specific initialization for the Microsoft linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os.path
+
+import SCons.Defaults
+import SCons.Errors
+import SCons.Action
+
+from SCons.Tool.msvc import get_msdev_paths
+
+def win32TempFileMunge(env, cmd_list, for_signature): 
+    """Given a list of command line arguments, see if it is too
+    long to pass to the win32 command line interpreter.  If so,
+    create a temp file, then pass "@tempfile" as the sole argument
+    to the supplied command (which is the first element of cmd_list).
+    Otherwise, just return [cmd_list]."""
+    cmd = env.subst_list(cmd_list)[0]
+    if for_signature or \
+       (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= 2048:
+        return [cmd_list]
+    else:
+        import tempfile
+        # We do a normpath because mktemp() has what appears to be
+        # a bug in Win32 that will use a forward slash as a path
+        # delimiter.  Win32's link mistakes that for a command line
+        # switch and barfs.
+        tmp = os.path.normpath(tempfile.mktemp())
+        args = map(SCons.Util.quote_spaces, cmd[1:])
+        open(tmp, 'w').write(string.join(args, " ") + "\n")
+        return [ [cmd[0], '@' + tmp],
+                 ['del', tmp] ]
+    
+def win32LinkGenerator(env, target, source, for_signature, **kw):
+    args = [ '$LINK', '$LINKFLAGS', '/OUT:%s' % target[0],
+             '$(', '$_LIBDIRFLAGS', '$)', '$_LIBFLAGS' ]
+    args.extend(map(SCons.Util.to_String, source))
+    return win32TempFileMunge(env, args, for_signature)
+
+def win32LibGenerator(target, source, env, for_signature, no_import_lib=0):
+    listCmd = [ "$SHLINK", "$SHLINKFLAGS" ]
+
+    for tgt in target:
+        ext = os.path.splitext(str(tgt))[1]
+        if ext == env.subst("$LIBSUFFIX"):
+            # Put it on the command line as an import library.
+            if no_import_lib:
+                raise SCons.Errors.UserError, "%s: You cannot specify a .lib file as a target of a shared library build if no_import_library is nonzero." % tgt
+            listCmd.append("${WIN32IMPLIBPREFIX}%s" % tgt)
+        else:
+            listCmd.append("${WIN32DLLPREFIX}%s" % tgt)
+
+    listCmd.extend([ '$_LIBDIRFLAGS', '$_LIBFLAGS' ])
+    for src in source:
+        ext = os.path.splitext(str(src))[1]
+        if ext == env.subst("$WIN32DEFSUFFIX"):
+            # Treat this source as a .def file.
+            listCmd.append("${WIN32DEFPREFIX}%s" % src)
+        else:
+            # Just treat it as a generic source file.
+            listCmd.append(str(src))
+    return win32TempFileMunge(env, listCmd, for_signature)
+
+def win32LibEmitter(target, source, env, no_import_lib=0):
+    dll = None
+    for tgt in target:
+        ext = os.path.splitext(str(tgt))[1]
+        if ext == env.subst("$SHLIBSUFFIX"):
+            dll = tgt
+            break
+    if not dll:
+        raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
+        
+    if env.has_key("WIN32_INSERT_DEF") and \
+       env["WIN32_INSERT_DEF"] and \
+       not '.def' in map(lambda x: os.path.split(str(x))[1],
+                         source):
+
+        # append a def file to the list of sources
+        source.append("%s%s" % (os.path.splitext(str(dll))[0],
+                                env.subst("$WIN32DEFSUFFIX")))
+    if not no_import_lib and \
+       not env.subst("$LIBSUFFIX") in \
+       map(lambda x: os.path.split(str(x))[1], target):
+        # Append an import library to the list of targets.
+        target.append("%s%s%s" % (env.subst("$LIBPREFIX"),
+                                  os.path.splitext(str(dll))[0],
+                                  env.subst("$LIBSUFFIX")))
+    return (target, source)
+
+ShLibAction = SCons.Action.CommandGenerator(win32LibGenerator)
+LinkAction = SCons.Action.CommandGenerator(win32LinkGenerator)
+
+def generate(env, platform):
+    """Add Builders and construction variables for ar to an Environment."""
+    env['BUILDERS']['SharedLibrary'] = SCons.Defaults.SharedLibrary
+    env['BUILDERS']['Program'] = SCons.Defaults.Program
+    
+    env['SHLINK']      = '$LINK'
+    env['SHLINKFLAGS'] = '$LINKFLAGS /dll'
+    env['SHLINKCOM']   = ShLibAction
+    env['SHLIBEMITTER']= win32LibEmitter
+    env['LINK']        = 'link'
+    env['LINKFLAGS']   = '/nologo'
+    env['LINKCOM']     = LinkAction
+    env['LIBDIRPREFIX']='/LIBPATH:'
+    env['LIBDIRSUFFIX']=''
+    env['LIBLINKPREFIX']=''
+    env['LIBLINKSUFFIX']='$LIBSUFFIX'
+
+    env['WIN32DEFPREFIX']        = '/def:'
+    env['WIN32DEFSUFFIX']        = '.def'
+    env['WIN32DLLPREFIX']        = '/out:'
+    env['WIN32IMPLIBPREFIX']     = '/implib:'
+    env['WIN32_INSERT_DEF']      = 0
+
+    include_path, lib_path, exe_path = get_msdev_paths()
+    env['ENV']['LIB']            = lib_path
+    env['ENV']['PATH']           = exe_path
diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py
new file mode 100644 (file)
index 0000000..54796e3
--- /dev/null
@@ -0,0 +1,223 @@
+"""engine.SCons.Tool.msvc
+
+Tool-specific initialization for Microsoft Visual C/C++.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os.path
+import string
+
+import SCons.Action
+import SCons.Tool
+import SCons.Errors
+
+CSuffixes = ['.c', '.C']
+CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
+
+def get_devstudio_versions():
+    """
+    Get list of devstudio versions from the Windows registry.  Return a
+    list of strings containing version numbers; an exception will be raised
+    if we were unable to access the registry (eg. couldn't import
+    a registry-access module) or the appropriate registry keys weren't
+    found.
+    """
+
+    if not SCons.Util.can_read_reg:
+        raise SCons.Errors.InternalError, "No Windows registry module was found"
+
+    K = 'Software\\Microsoft\\Devstudio'
+    L = []
+    for base in (SCons.Util.HKEY_CLASSES_ROOT,
+                 SCons.Util.HKEY_LOCAL_MACHINE,
+                 SCons.Util.HKEY_CURRENT_USER,
+                 SCons.Util.HKEY_USERS):
+        try:
+            k = SCons.Util.RegOpenKeyEx(base,K)
+            i = 0
+            while 1:
+                try:
+                    p = SCons.Util.RegEnumKey(k,i)
+                    if p[0] in '123456789' and p not in L:
+                        L.append(p)
+                except SCons.Util.RegError:
+                    break
+                i = i + 1
+        except SCons.Util.RegError:
+            pass
+
+    if not L:
+        raise SCons.Errors.InternalError, "DevStudio was not found."
+
+    L.sort()
+    L.reverse()
+    return L
+
+def get_msvc_path (path, version, platform='x86'):
+    """
+    Get a list of devstudio directories (include, lib or path).  Return
+    a string delimited by ';'. An exception will be raised if unable to
+    access the registry or appropriate registry keys not found.
+    """
+
+    if not SCons.Util.can_read_reg:
+        raise SCons.Errors.InternalError, "No Windows registry module was found"
+
+    if path=='lib':
+        path= 'Library'
+    path = string.upper(path + ' Dirs')
+    K = ('Software\\Microsoft\\Devstudio\\%s\\' +
+         'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \
+        (version,platform)
+    for base in (SCons.Util.HKEY_CLASSES_ROOT,
+                 SCons.Util.HKEY_LOCAL_MACHINE,
+                 SCons.Util.HKEY_CURRENT_USER,
+                 SCons.Util.HKEY_USERS):
+        try:
+            k = SCons.Util.RegOpenKeyEx(base,K)
+            i = 0
+            while 1:
+                try:
+                    (p,v,t) = SCons.Util.RegEnumValue(k,i)
+                    if string.upper(p) == path:
+                        return v
+                    i = i + 1
+                except SCons.Util.RegError:
+                    break
+        except SCons.Util.RegError:
+            pass
+
+    # if we got here, then we didn't find the registry entries:
+    raise SCons.Errors.InternalError, "%s was not found in the registry."%path
+
+def get_msdev_dir(version):
+    """Returns the root directory of the MSDev installation from the
+    registry if it can be found, otherwise we guess."""
+    if SCons.Util.can_read_reg:
+        K = ('Software\\Microsoft\\Devstudio\\%s\\' +
+             'Products\\Microsoft Visual C++') % \
+             version
+        for base in (SCons.Util.HKEY_LOCAL_MACHINE,
+                     SCons.Util.HKEY_CURRENT_USER):
+            try:
+                k = SCons.Util.RegOpenKeyEx(base,K)
+                val, tok = SCons.Util.RegQueryValueEx(k, 'ProductDir')
+                return os.path.split(val)[0]
+            except SCons.Util.RegError:
+                pass
+
+def get_msdev_paths(version=None):
+    """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
+    of those three environment variables that should be set
+    in order to execute the MSVC tools properly."""
+    exe_path = ''
+    lib_path = ''
+    include_path = ''
+    try:
+        if not version:
+            version = get_devstudio_versions()[0] #use highest version
+        include_path = get_msvc_path("include", version)
+        lib_path = get_msvc_path("lib", version)
+        exe_path = get_msvc_path("path", version) + ";" + os.environ['PATH']
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        # Could not get the configured directories from the registry.
+        # However, the configured directories only appear if the user
+        # changes them from the default.  Therefore, we'll see if
+        # we can get the path to the MSDev base installation from
+        # the registry and deduce the default directories.
+        MVSdir = None
+        if version:
+            MVSdir = get_msdev_dir(version)
+        if MVSdir:
+            MVSVCdir = r'%s\VC98' % MVSdir
+            MVSCommondir = r'%s\Common' % MVSdir
+            include_path = r'%s\atl\include;%s\mfc\include;%s\include' % (MVSVCdir, MVSVCdir, MVSVCdir)
+            lib_path = r'%s\mfc\lib;%s\lib' % (MVSVCdir, MVSVCdir)
+            try:
+                extra_path = os.pathsep + os.environ['PATH']
+            except KeyError:
+                extra_path = ''
+            exe_path = (r'%s\MSDev98\Bin;%s\Bin' % (MVSCommondir, MVSVCdir)) + extra_path
+        else:
+            # The DevStudio environment variables don't exist,
+            # so just use the variables from the source environment.
+            MVSdir = r'C:\Program Files\Microsoft Visual Studio'
+            MVSVCdir = r'%s\VC98' % MVSdir
+            MVSCommondir = r'%s\Common' % MVSdir
+            try:
+                include_path = os.environ['INCLUDE']
+            except KeyError:
+                include_path = ''
+            try:
+                lib_path = os.environ['LIB']
+            except KeyError:
+                lib_path = ''
+            try:
+                exe_path = os.environ['PATH']
+            except KeyError:
+                exe_path = ''
+    return (include_path, lib_path, exe_path)
+
+def generate(env, platform):
+    """Add Builders and construction variables for MSVC++ to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in CSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
+
+    for suffix in CXXSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CXXAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
+
+    env['CC']         = 'cl'
+    env['CCFLAGS']    = '/nologo'
+    env['CCCOM']      = '$CC $CCFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['SHCC']       = '$CC'
+    env['SHCCFLAGS']  = '$CCFLAGS'
+    env['SHCCCOM']    = '$SHCC $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['CXX']        = '$CC'
+    env['CXXFLAGS']   = '$CCFLAGS'
+    env['CXXCOM']     = '$CXX $CXXFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['SHCXX']      = '$CXX'
+    env['SHCXXFLAGS'] = '$CXXFLAGS'
+    env['SHCXXCOM']   = '$SHCXX $SHCXXFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['INCPREFIX']  = '/I'
+    env['INCSUFFIX']  = '' 
+
+    include_path, lib_path, exe_path = get_msdev_paths()
+    env['ENV']['INCLUDE'] = include_path
+    env['ENV']['PATH']    = exe_path
+    
+    env['CFILESUFFIX'] = '.c'
+    env['CXXFILESUFFIX'] = '.cc'
+    
diff --git a/src/engine/SCons/Tool/pdflatex.py b/src/engine/SCons/Tool/pdflatex.py
new file mode 100644 (file)
index 0000000..340622c
--- /dev/null
@@ -0,0 +1,54 @@
+"""SCons.Tool.pdflatex
+
+Tool-specific initialization for pdflatex.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Action
+import SCons.Defaults
+
+PDFLaTeXAction = SCons.Action.Action('$PDFLATEXCOM')
+
+def generate(env, platform):
+    """Add Builders and construction variables for pdflatex to an Environment."""
+    try:
+        bld = env['BUILDERS']['PDF']
+    except KeyError:
+        bld = SCons.Defaults.PDF()
+        env['BUILDERS']['PDF'] = bld
+
+    bld.add_action('.ltx', PDFLaTeXAction)
+    bld.add_action('.latex', PDFLaTeXAction)
+
+    env['PDFLATEX']      = 'pdflatex'
+    env['PDFLATEXFLAGS'] = ''
+    env['PDFLATEXCOM']   = '$PDFLATEX $PDFLATEXFLAGS $SOURCES $TARGET'
diff --git a/src/engine/SCons/Tool/pdftex.py b/src/engine/SCons/Tool/pdftex.py
new file mode 100644 (file)
index 0000000..1acc9ce
--- /dev/null
@@ -0,0 +1,50 @@
+"""SCons.Tool.pdftex
+
+Tool-specific initialization for pdftex.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Defaults
+
+def generate(env, platform):
+    """Add Builders and construction variables for pdftex to an Environment."""
+    try:
+        bld = env['BUILDERS']['PDF']
+    except KeyError:
+        bld = SCons.Defaults.PDF()
+        env['BUILDERS']['PDF'] = bld
+
+    bld.add_action('.tex', '$PDFTEXCOM')
+
+    env['PDFTEX']      = 'pdftex'
+    env['PDFTEXFLAGS'] = ''
+    env['PDFTEXCOM']   = '$PDFTEX $PDFTEXFLAGS $SOURCES $TARGET'
diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py
new file mode 100644 (file)
index 0000000..10413aa
--- /dev/null
@@ -0,0 +1,50 @@
+"""SCons.Tool.tex
+
+Tool-specific initialization for TeX.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Defaults
+
+def generate(env, platform):
+    """Add Builders and construction variables for TeX to an Environment."""
+    try:
+        bld = env['BUILDERS']['DVI']
+    except KeyError:
+        bld = SCons.Defaults.DVI()
+        env['BUILDERS']['DVI'] = bld
+        
+    bld.add_action('.tex', '$TEXCOM')
+
+    env['TEX']      = 'tex'
+    env['TEXFLAGS'] = ''
+    env['TEXCOM']   = '$TEX $TEXFLAGS $SOURCES'
diff --git a/src/engine/SCons/Tool/yacc.py b/src/engine/SCons/Tool/yacc.py
new file mode 100644 (file)
index 0000000..34abe77
--- /dev/null
@@ -0,0 +1,47 @@
+"""SCons.Tool.yacc
+
+Tool-specific initialization for yacc.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Tool
+
+def generate(env, platform):
+    """Add Builders and construction variables for yacc to an Environment."""
+    c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
+    
+    c_file.add_action('.y', '$YACCCOM')
+    cxx_file.add_action('.yy', '$YACCCOM')
+
+    env['YACC']      = 'yacc'
+    env['YACCFLAGS'] = ''
+    env['YACCCOM']   = '$YACC $YACCFLAGS -o $TARGET $SOURCES'
index d366d9ad62590d603363c2a19bba3c28a316dfb7..38489ef529ebe8b68217e421419f6262918ec8aa 100644 (file)
@@ -336,6 +336,15 @@ else:
     def is_String(e):
         return type(e) is types.StringType or isinstance(e, UserString)
 
+class Proxy:
+    """A simple generic Proxy class, forwarding all calls to
+    subject.  Inherit from this class to create a Proxy."""
+    def __init__(self, subject):
+        self.__subject = subject
+        
+    def __getattr__(self, name):
+        return getattr(self.__subject, name)
+
 # attempt to load the windows registry module:
 can_read_reg = 0
 try:
index 4f3195fee7cc117f61cde422f7d93d204e904a58..31dceb12860445a6f25d4b05acf09e796d94b5c0 100644 (file)
@@ -361,6 +361,32 @@ class UtilTestCase(unittest.TestCase):
         assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
         assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
 
+    def test_Proxy(self):
+        """Test generic Proxy class."""
+        class Subject:
+            def foo(self):
+                return 1
+            def bar(self):
+                return 2
+
+        s=Subject()
+        s.baz = 3
+
+        class ProxyTest(Proxy):
+            def bar(self):
+                return 4
+
+        p=ProxyTest(s)
+
+        assert p.foo() == 1, p.foo()
+        assert p.bar() == 4, p.bar()
+        assert p.baz == 3, p.baz
+
+        p.baz = 5
+        s.baz = 6
+
+        assert p.baz == 5, p.baz
+
 if __name__ == "__main__":
     suite = unittest.makeSuite(UtilTestCase, 'test_')
     if not unittest.TextTestRunner().run(suite).wasSuccessful():
index 8104e6d2d5d908b187ab54bbaed928dc8ea617f9..ceb4440e2fd972992ac1c1f3af36a0d7b0f53fba 100644 (file)
@@ -78,8 +78,9 @@ arguments = {
                           "SCons.Node",
                           "SCons.Platform",
                           "SCons.Scanner",
+                          "SCons.Script",
                           "SCons.Sig",
-                          "SCons.Script"],
+                          "SCons.Tool"],
     'package_dir'      : {'' : 'engine'},
     'scripts'          : ["script/scons"],
     'cmdclass'         : {'install_lib' : my_install_lib}
index 56738c7bebb003e2f870d2cc54dbf266cc8d5dec..6dcb7798ca517a5fb105d5a3e0899b066c1ea1bf 100644 (file)
@@ -48,7 +48,7 @@ Default(env.SharedLibrary(target = 'foo', source = obj))
 
 test.write('SConstructFoo2', """
 env=Environment()
-obj = env.SharedObject('foo', 'foo.c')
+obj = env.SharedObject('bar', 'foo.c')
 Default(env.Library(target = 'foo', source = obj))
 """)
 
@@ -193,7 +193,7 @@ SCons error: Source file: foo\..* is static and is not compatible with shared ta
 )
 
 test.run(arguments = '-f SConstructFoo2', status=2, stderr='''
-SCons error: Source file: foo\..* is shared and is not compatible with static target: .*
+SCons error: Source file: bar\..* is shared and is not compatible with static target: .*
 '''
 )