Add MinGW support. (Anthony Roach)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 9 Jan 2003 05:29:53 +0000 (05:29 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 9 Jan 2003 05:29:53 +0000 (05:29 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@539 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
rpm/scons.spec
src/CHANGES.txt
src/engine/MANIFEST.in
src/engine/SCons/Environment.py
src/engine/SCons/EnvironmentTests.py
src/engine/SCons/Tool/__init__.py
src/engine/SCons/Tool/mingw.py [new file with mode: 0644]
src/engine/SCons/Tool/mslink.py
test/mingw.py [new file with mode: 0644]
test/msvc.py

index fb5af362162636a074672ccf6f0fd698c217e1aa..a2f265f65d73962838cfff58cde5c063e9658cbd 100644 (file)
@@ -777,6 +777,7 @@ gnulink
 latex
 lex
 masm
+mingw
 mslib
 mslink
 msvc
@@ -788,9 +789,11 @@ tex
 yacc
 .EE
 
-On posix and cygwin platforms the GNU tools (e.g. gcc) are preferred by SCons, 
-on win32 the Microsoft tools (e.g. msvc) are preferred by SCons, and in OS/2 the IBM
-tools (e.g. icc) are preferred by SCons.
+On posix and cygwin platforms
+the GNU tools (e.g. gcc) are preferred by SCons,
+on win32 the Microsoft tools (e.g. msvc)
+followed by MinGW are preferred by SCons,
+and in OS/2 the IBM tools (e.g. icc) are preferred by SCons.
 
 .SS Builder Methods
 
@@ -1022,10 +1025,13 @@ env.Program(target = 'foo', source = ['foo.o', 'bar.c', 'baz.f'])
 .EE
 
 .IP RES
-Builds a Microsoft Visual C++ resource file. This builder is only
-provided when Microsoft Visual C++ is being used as the compiler. The
+Builds a Microsoft Visual C++ resource file.
+This builder is only provided
+when Microsoft Visual C++ or MinGW is being used as the compiler. The
 .I .res
-suffix is added to the target name if no other suffix is given. The source
+(or 
+.I .o 
+for MinGW) suffix is added to the target name if no other suffix is given. The source
 file is scanned for implicit dependencies as though it were a C file. Example:
 
 .ES
@@ -2123,17 +2129,11 @@ if a .def file is not already listed as a build target.
 The default is 0 (do not build a .def file).
 
 .IP WIN32DEFPREFIX
-The prefix used to build WIN32 .def files.
+The prefix used for WIN32 .def file names.
 
 .IP WIN32DEFSUFFIX
 The suffix used for WIN32 .def file names.
 
-.IP WIN32DLLPREFIX
-The prefix used to build WIN32 shared libraries (.dll files).
-
-.IP WIN32IMPLIBPREFIX
-The prefix used to build WIN32 import libraries.
-
 .IP YACC
 The parser generator.
 
@@ -3352,6 +3352,24 @@ or by creating a wrapper shell
 script named
 .B scons .
 
+.SS MinGW
+
+The MinGW bin directory must be in your PATH environment variable or the
+PATH variable under the ENV construction variable for SCons
+to detect and use the MinGW tools. When running under the native Windows
+Python interpreter, SCons will prefer the MinGW tools over the Cygwin
+tools, if they are both installed, regardless of the order of the bin
+directories in the PATH variable. If you have both MSVC and MinGW
+installed and you want to use MinGW instead of MSVC,
+then you must explictly tell SCons to use MinGW by passing 
+
+.ES
+tools=['mingw']
+.EE
+
+to the Environment() function, because SCons will prefer the MSVC tools
+over the MinGW tools.
+
 .SH EXAMPLES
 
 To help you get started using SCons,
index 01bc67e459b799240b29507263893230d7b87984..bfa68a4a650c48121b9c61718926eada53755dd5 100644 (file)
@@ -140,6 +140,8 @@ rm -rf $RPM_BUILD_ROOT
 /usr/lib/scons/SCons/Tool/lex.pyc
 /usr/lib/scons/SCons/Tool/masm.py
 /usr/lib/scons/SCons/Tool/masm.pyc
+/usr/lib/scons/SCons/Tool/mingw.py
+/usr/lib/scons/SCons/Tool/mingw.pyc
 /usr/lib/scons/SCons/Tool/mslib.py
 /usr/lib/scons/SCons/Tool/mslib.pyc
 /usr/lib/scons/SCons/Tool/mslink.py
index c8610781a0e1703dc0d7c15c5f97b3d6503c4bde..4e1ffec0b446537c0d214686a526ad60b54b13e0 100644 (file)
@@ -66,6 +66,8 @@ RELEASE 0.10 - XXX
     all start with "scons: warning:").  Caught more cases with the "Do
     not know how to build" error message.
 
+  - Added support for the MinGW tool chain.
+
 
 
 RELEASE 0.09 - Thu,  5 Dec 2002 04:48:25 -0600
index 3481a2423d8166399dd9795c8639caf2d008791f..cf272744e1f2d2760acb7418321fcdf6bcdbef40 100644 (file)
@@ -45,6 +45,7 @@ SCons/Tool/ilink.py
 SCons/Tool/latex.py
 SCons/Tool/lex.py
 SCons/Tool/masm.py
+SCons/Tool/mingw.py
 SCons/Tool/mslib.py
 SCons/Tool/mslink.py
 SCons/Tool/msvc.py
index a5672aefefaf74b6db5b4b4effb73245081f6e48..5ebf64c63887d5ab85a624c8e35645e5e2ae0515 100644 (file)
@@ -421,6 +421,16 @@ class Environment:
     def Detect(self, progs):
         """Return the first available program in progs.
         """
+        if not SCons.Util.is_List(progs):
+            progs = [ progs ]
+        for prog in progs:
+            path = self.WhereIs(prog)
+            if path: return prog
+        return None
+
+    def WhereIs(self, prog):
+        """Find prog in the path.  
+        """
         path = None
         pathext = None
         if self.has_key('ENV'):
@@ -428,11 +438,8 @@ class Environment:
                 path = self['ENV']['PATH']
             if self['ENV'].has_key('PATHEXT'):
                 pathext = self['ENV']['PATHEXT']
-        if not SCons.Util.is_List(progs):
-            progs = [ progs ]
-        for prog in progs:
-            path = SCons.Util.WhereIs(prog, path, pathext)
-            if path: return prog
+        path = SCons.Util.WhereIs(prog, path, pathext)
+        if path: return path
         return None
 
     def Override(self, overrides):
@@ -464,4 +471,45 @@ class Environment:
     def items(self):
         "Emulates the items() method of dictionaries."""
         return self._dict.items()
+
+    def FindIxes(self, paths, prefix, suffix):
+        """
+        Search a list of paths for something that matches the prefix and suffix.
+
+        paths - the list of paths or nodes.
+        prefix - construction variable for the prefix.
+        suffix - construction variable for the suffix.
+        """
+
+        suffix = self.subst('$%s'%suffix)
+        prefix = self.subst('$%s'%prefix)
+
+        for path in paths:
+            dir,name = os.path.split(str(path))
+            if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix: 
+                return path
+
+    def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
+        """
+        Replace old_prefix with new_prefix and old_suffix with new_suffix.
+
+        env - Environment used to interpolate variables.
+        path - the path that will be modified.
+        old_prefix - construction variable for the old prefix.
+        old_suffix - construction variable for the old suffix.
+        new_prefix - construction variable for the new prefix.
+        new_suffix - construction variable for the new suffix.
+        """
+        old_prefix = self.subst('$%s'%old_prefix)
+        old_suffix = self.subst('$%s'%old_suffix)
+
+        new_prefix = self.subst('$%s'%new_prefix)
+        new_suffix = self.subst('$%s'%new_suffix)
+
+        dir,name = os.path.split(str(path))
+        if name[:len(old_prefix)] == old_prefix:
+            name = name[len(old_prefix):]
+        if name[-len(old_suffix):] == old_suffix:
+            name = name[:-len(old_suffix)]
+        return os.path.join(dir, new_prefix+name+new_suffix)
     
index 0ec3b4e67cf3a06a05d33353e2bba268fa942572..46aad4660c80e32ccc7abadd51a2387aa17a7c46 100644 (file)
@@ -696,6 +696,50 @@ class EnvironmentTestCase(unittest.TestCase):
         x = env.get('bbb', 'XXX')
         assert x == 'XXX', x
 
+    def test_FindIxes(self):
+        "Test FindIxes()"
+        env = Environment(LIBPREFIX='lib', 
+                          LIBSUFFIX='.a',
+                          SHLIBPREFIX='lib', 
+                          SHLIBSUFFIX='.so',
+                          PREFIX='pre',
+                          SUFFIX='post')
+
+        paths = [os.path.join('dir', 'libfoo.a'),
+                 os.path.join('dir', 'libfoo.so')]
+
+        assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
+        assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+        assert None == env.FindIxes(paths, 'PREFIX', 'POST')
+
+        paths = ['libfoo.a', 'prefoopost']
+
+        assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
+        assert None == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+        assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
+
+    def test_ReplaceIxes(self):
+        "Test ReplaceIxes()"
+        env = Environment(LIBPREFIX='lib', 
+                          LIBSUFFIX='.a',
+                          SHLIBPREFIX='lib', 
+                          SHLIBSUFFIX='.so',
+                          PREFIX='pre',
+                          SUFFIX='post')
+        
+        assert 'libfoo.a' == env.ReplaceIxes('libfoo.so', 
+                                             'SHLIBPREFIX', 'SHLIBSUFFIX',
+                                             'LIBPREFIX', 'LIBSUFFIX')
+        
+        assert os.path.join('dir', 'libfoo.a') == env.ReplaceIxes(os.path.join('dir', 'libfoo.so'),
+                                                                   'SHLIBPREFIX', 'SHLIBSUFFIX',
+                                                                   'LIBPREFIX', 'LIBSUFFIX')
+
+        assert 'libfoo.a' == env.ReplaceIxes('prefoopost', 
+                                             'PREFIX', 'SUFFIX',
+                                             'LIBPREFIX', 'LIBSUFFIX')
+
+        
 if __name__ == "__main__":
     suite = unittest.makeSuite(EnvironmentTestCase, 'test_')
     if not unittest.TextTestRunner().run(suite).wasSuccessful():
index 10b6608167d6ee61eda5beda9ac3d180f2ba1e0e..f5cea7ee2b58f1c3133b4d4dfaf366428b505c8d 100644 (file)
@@ -140,10 +140,14 @@ def FindAllTools(tools, env):
     return filter (ToolExists, tools)
              
 def tool_list(platform, env):
+
+    # XXX this logic about what tool to prefer on which platform
+    #     should be moved into either the platform files or
+    #     the tool files themselves.
     if str(platform) == 'win32':
         "prefer Microsoft tools on Windows"
         linkers = ['mslink', 'gnulink', 'ilink']
-        c_compilers = ['msvc', 'gcc', 'icc']
+        c_compilers = ['msvc', 'mingw', 'gcc', 'icc']
         assemblers = ['masm', 'nasm', 'gas']
         fortran_compilers = ['g77', 'ifl']
         ars = ['mslib', 'ar']
@@ -162,17 +166,29 @@ def tool_list(platform, env):
         fortran_compilers = ['g77', 'ifl']
         ars = ['ar', 'mslib']
 
-    linker = FindTool(linkers, env) or linkers[0]
     c_compiler = FindTool(c_compilers, env) or c_compilers[0]
-    assembler = FindTool(assemblers, env) or assemblers[0]
-    fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0]
-    ar = FindTool(ars, env) or ars[0]
-
-    # Don't use g++ if the C compiler has built-in C++ support:
-    if c_compiler and (c_compiler == 'msvc' or c_compiler == 'icc'):
+    # XXX this logic about what tool provides what should somehow be
+    #     moved into the tool files themselves.
+    if c_compiler and c_compiler == 'mingw':
+        # MinGW contains a linker, C compiler, C++ compiler, 
+        # Fortran compiler, archiver and assember:
+        linker = None
+        assembler = None
+        fortran_compiler = None
+        ar = None
         cxx_compiler = None
     else:
-        cxx_compiler = FindTool(['g++'], env)
+        linker = FindTool(linkers, env) or linkers[0]
+        assembler = FindTool(assemblers, env) or assemblers[0]
+        fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0]
+        ar = FindTool(ars, env) or ars[0]
+
+        # Don't use g++ if the C compiler has built-in C++ support:
+        if c_compiler and (c_compiler == 'msvc' or c_compiler == 'icc'):
+            cxx_compiler = None
+        else:
+            cxx_compiler = FindTool(['g++'], env)
         
     other_tools = FindAllTools(['dvipdf', 'dvips',
                                 'latex', 'lex',
diff --git a/src/engine/SCons/Tool/mingw.py b/src/engine/SCons/Tool/mingw.py
new file mode 100644 (file)
index 0000000..7221cd6
--- /dev/null
@@ -0,0 +1,131 @@
+"""SCons.Tool.gcc
+
+Tool-specific initialization for MinGW (http://www.mingw.org/)
+
+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 os
+import SCons.Tool
+import SCons.Util
+import string
+
+# This is what we search for to find mingw:
+key_program = 'mingw32-gcc'
+
+def find(env):
+    # First search in the SCons path and then the OS path:
+    return env.WhereIs(key_program) or SCons.Util.WhereIs(key_program)
+
+def shlib_generator(target, source, env, for_signature):
+    cmd = ['$SHLINK', '$SHLINKFLAGS'] 
+
+    dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+    if dll: cmd.extend(['-o', dll])
+
+    cmd.extend(['$SOURCES', '$_LIBDIRFLAGS', '$_LIBFLAGS'])
+
+    implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
+    if implib: cmd.append('-Wl,--out-implib,'+str(implib))
+
+    return [cmd]
+
+def shlib_emitter(target, source, env):
+    dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+    no_import_lib = env.get('no_import_lib', 0)
+
+    if not dll:
+        raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
+    
+    if not no_import_lib and \
+       not env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX'):
+
+        # Append an import library to the list of targets.
+        target.append(env.ReplaceIxes(dll,  
+                                      'SHLIBPREFIX', 'SHLIBSUFFIX',
+                                      'LIBPREFIX', 'LIBSUFFIX'))
+    
+    return (target, source)
+                         
+
+shlib_action = SCons.Action.CommandGenerator(shlib_generator)
+
+res_builder = SCons.Builder.Builder(action='$RCCOM', suffix='.o')
+
+def generate(env, platform):
+    
+    mingw = find(env)
+    if mingw:
+        dir = os.path.dirname(mingw)
+
+        # The mingw bin directory must be added to the path:
+        path = env['ENV'].get('PATH', [])
+        if not path: 
+            path = []
+        if SCons.Util.is_String(path):
+            path = string.split(path, os.pathsep)
+
+        env['ENV']['PATH'] = string.join([dir] + path, os.pathsep)
+        
+
+    # Most of mingw is the same as gcc and friends...
+    gnu_tools = ['gcc', 'g++', 'gnulink', 'ar', 'gas']
+    for tool in gnu_tools:
+        SCons.Tool.Tool(tool, platform)(env,platform)
+
+    #... but a few things differ:
+    env['CC'] = 'gcc'
+    env['SHCCFLAGS'] = '$CCFLAGS'
+    env['CXX'] = 'g++'
+    env['SHCXXFLAGS'] = '$CXXFLAGS'
+    env['SHLINKFLAGS'] = '$LINKFLAGS -shared'
+    env['SHLINKCOM']   = shlib_action
+    env['SHLIBEMITTER']= shlib_emitter
+    env['LINK'] = 'g++'
+    env['AS'] = 'as'
+
+    env['RC'] = 'windres'
+    env['RCFLAGS'] = ''
+    env['RCINCFLAGS'] = '$( ${_concat(RCINCPREFIX, CPPPATH, RCINCSUFFIX, locals(), globals(), RDirs)} $)'
+    env['RCINCPREFIX'] = '--include-dir '
+    env['RCINCSUFFIX'] = ''
+    env['RCCOM'] = '$RC $RCINCFLAGS $RCFLAGS -i $SOURCE -o $TARGET'
+    env.CScan.add_skey('.rc')
+    env['BUILDERS']['RES'] = res_builder
+    
+    # Some setting from the platform also have to be overridden:
+    env['OBJSUFFIX'] = '.o'
+    env['LIBPREFIX'] = 'lib'
+    env['LIBSUFFIX'] = '.a'
+
+def exists(env):
+    return find(env)
index 133e700b45c63cf4a738ff8f4b238a1ef97c4292..5b073b1e3a571edf5b62d8860f401190d41febeb 100644 (file)
@@ -57,27 +57,24 @@ def win32LinkGenerator(env, target, source, for_signature):
 
 def win32LibGenerator(target, source, env, for_signature):
     listCmd = [ "$SHLINK", "$SHLINKFLAGS" ]
-    no_import_lib = env.get('no_import_lib', 0)
 
     if env.has_key('PDB') and env['PDB']:
         listCmd.extend(['/PDB:%s'%target[0].File(env['PDB']), '/DEBUG'])
 
-    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)
+    dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+    if dll: listCmd.append("/out:%s"%dll)
 
+    implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
+    if implib: listCmd.append("/implib:%s"%implib)
+    
     listCmd.extend([ '$_LIBDIRFLAGS', '$_LIBFLAGS' ])
+
+    deffile = env.FindIxes(source, "WIN32DEFPREFIX", "WIN32DEFSUFFIX")
+    
     for src in source:
-        ext = os.path.splitext(str(src))[1]
-        if ext == env.subst("$WIN32DEFSUFFIX"):
+        if src == deffile:
             # Treat this source as a .def file.
-            listCmd.append("${WIN32DEFPREFIX}%s" % src)
+            listCmd.append("/def:%s" % src)
         else:
             # Just treat it as a generic source file.
             listCmd.append(str(src))
@@ -87,37 +84,31 @@ def win32LibGenerator(target, source, env, for_signature):
 def win32LibEmitter(target, source, env):
     msvc.validate_vars(env)
     
-    dll = None
+    dll = env.FindIxes(target, "SHLIBPREFIX", "SHLIBSUFFIX")
     no_import_lib = env.get('no_import_lib', 0)
     
-    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.splitext(str(x))[1],
-                         source):
+    if env.get("WIN32_INSERT_DEF", 0) and \
+       not env.FindIxes(source, "WIN32DEFPREFIX", "WIN32DEFSUFFIX"):
 
         # append a def file to the list of sources
-        source.append("%s%s" % (os.path.splitext(str(dll))[0],
-                                env.subst("$WIN32DEFSUFFIX")))
+        source.append(env.ReplaceIxes(dll, 
+                                      "SHLIBPREFIX", "SHLIBSUFFIX",
+                                      "WIN32DEFPREFIX", "WIN32DEFSUFFIX"))
 
     if env.has_key('PDB') and env['PDB']:
         env.SideEffect(env['PDB'], target)
         env.Precious(env['PDB'])
 
     if not no_import_lib and \
-       not env.subst("$LIBSUFFIX") in \
-       map(lambda x: os.path.splitext(str(x))[1], target):
+       not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"):
         # 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")))
+        target.append(env.ReplaceIxes(dll, 
+                                      "SHLIBPREFIX", "SHLIBSUFFIX",
+                                      "LIBPREFIX", "LIBSUFFIX"))
+
     return (target, source)
 
 def prog_emitter(target, source, env):
@@ -150,10 +141,8 @@ def generate(env, platform):
     env['LIBLINKPREFIX']=''
     env['LIBLINKSUFFIX']='$LIBSUFFIX'
 
-    env['WIN32DEFPREFIX']        = '/def:'
+    env['WIN32DEFPREFIX']        = ''
     env['WIN32DEFSUFFIX']        = '.def'
-    env['WIN32DLLPREFIX']        = '/out:'
-    env['WIN32IMPLIBPREFIX']     = '/implib:'
     env['WIN32_INSERT_DEF']      = 0
 
     include_path, lib_path, exe_path = get_msdev_paths()
diff --git a/test/mingw.py b/test/mingw.py
new file mode 100644 (file)
index 0000000..5d6e2c1
--- /dev/null
@@ -0,0 +1,190 @@
+"""
+This tests the MinGW C/C++ compiler support.
+"""
+
+#!/usr/bin/env python
+#
+# 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 TestSCons
+import sys
+import os.path
+import os
+import TestCmd
+import time
+import string
+
+test = TestSCons.TestSCons(match = TestCmd.match_re_dotall)
+
+# MinGW is win32 only:
+if sys.platform != 'win32':
+    test.pass_test()
+
+# This test requires MingW to be installed:
+test.write('SConstruct',"""
+from SCons.Tool.mingw import exists
+import sys
+env = Environment()
+if exists(env):
+    print 'mingw exists'
+sys.exit(0)
+""")
+
+test.run()
+if string.find(test.stdout(), 'mingw exists') == -1:
+    test.no_result()
+
+test.subdir('header')
+
+# Do the actual testing:
+test.write('SConstruct',"""
+env=Environment(tools=['mingw'])
+assert env['CC'] == 'gcc'
+env.StaticLibrary('static', 'static.cpp')
+env.SharedLibrary('shared', 'shared.cpp')
+env.SharedLibrary('cshared', 'cshared.c')
+env.Program('test', ['test.cpp', env.RES('resource.rc', CPPPATH=['header'])], LIBS=['static', 'shared', 'cshared'], LIBPATH=['.'])
+""")
+
+test.write('test.cpp', '''
+#include <stdio.h>
+#include <windows.h>
+#include "resource.h"
+
+void shared_func(void);
+void static_func(void);
+extern "C" void cshared_func(void);
+
+int main(void) 
+{ 
+    printf("%s\\n", "test.cpp");
+    shared_func();
+    static_func();
+    cshared_func();
+
+    char test[1024];
+    LoadString(GetModuleHandle(NULL), IDS_TEST, test, sizeof(test));
+    printf("%d %s\\n", IDS_TEST, test);
+
+    return 0;
+}
+''')
+
+test.write('resource.rc', '''
+#include "resource.h"
+#include <resource2.h>
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    IDS_TEST RESOURCE_RC
+END
+''')
+
+test.write('resource.h', '''
+#define IDS_TEST 2001
+''')
+
+test.write('static.cpp', '''
+#include <stdio.h>
+
+void static_func(void)
+{
+    printf("%s\\n", "static.cpp");
+}
+''')
+
+test.write('shared.cpp', '''
+#include <stdio.h>
+
+void shared_func(void)
+{
+    printf("%s\\n", "shared.cpp");
+}
+''')
+
+test.write('cshared.c', '''
+#include <stdio.h>
+
+void cshared_func(void)
+{
+    printf("%s\\n", "cshared.c");
+}
+''')
+
+test.write('header/resource2.h', '''
+#define RESOURCE_RC "resource.rc"
+''')
+
+# the mingw linker likes to print "Creating library file: libfoo.a" to stderr, but
+# we'd like for this test to pass once this bug is fixed, so match anything at all
+# that comes out of stderr:
+test.run(arguments='test.exe', stderr='.*')
+test.run(program=test.workpath('test.exe'), stdout='test.cpp\nshared.cpp\nstatic.cpp\ncshared.c\n2001 resource.rc\n')
+
+# ensure that modifying the header causes the resource to be rebuilt:
+test.write('resource.h', '''
+#define IDS_TEST 2002
+''')
+test.run(arguments='test.exe', stderr='.*')
+test.run(program=test.workpath('test.exe'), stdout='test.cpp\nshared.cpp\nstatic.cpp\ncshared.c\n2002 resource.rc\n')
+
+# Test with specifying the default tool to make sure msvc setting doen't ruin it
+# for mingw:
+test.write('SConstruct',"""
+env=Environment(tools=['default', 'mingw'])
+assert env['CC'] == 'gcc'
+env.SharedLibrary('shared', 'shared.cpp')
+env.Program('test', 'test.cpp', LIBS=['static', 'shared', 'cshared'], LIBPATH=['.'])
+""")
+
+test.write('test.cpp', '''
+#include <stdio.h>
+
+void shared_func(void);
+
+int main(void) 
+{ 
+    printf("%s\\n", "test.cpp2");
+    shared_func();
+    return 0;
+}
+''')
+
+test.write('shared.cpp', '''
+#include <stdio.h>
+
+void shared_func(void)
+{
+    printf("%s\\n", "shared.cpp2");
+}
+''')
+
+# the mingw linker likes to print "Creating library file: libfoo.a" to stderr, but
+# we'd like for this test to pass once this bug is fixed, so match anything at all
+# that comes out of stderr:
+test.run(arguments='test.exe', stderr='.*')
+test.run(program=test.workpath('test.exe'), stdout='test.cpp2\nshared.cpp2\n')
+
+test.pass_test()
index 7d771d3055561bae914e6b63252256722624699b..7b274fa1ff65c2f169fe2eeece9b38f3877cf690 100644 (file)
@@ -215,7 +215,7 @@ env.Program('test', 'test.cpp')
 """)
 
 test.run(status=2, stderr='''
-SCons error: The PCHSTOP construction must be defined if PCH is defined.
+scons: \*\*\* The PCHSTOP construction must be defined if PCH is defined.
 File "SConstruct", line 5, in \?
 ''')
 
@@ -228,7 +228,7 @@ env.Program('test', 'test.cpp')
 """)
 
 test.run(status=2, stderr='''
-SCons error: The PCHSTOP construction variable must be a string: .+
+scons: \*\*\* The PCHSTOP construction variable must be a string: .+
 File "SConstruct", line 6, in \?
 ''')