Latest version from Rene Liebscher; major changes:
  - added big comment describing possible problems
  - look for and react to versions of gcc, ld, and dlltool; mainly
    this is done by the 'get_versions()' function and the CygwinCCompiler
    and Mingw32CCompiler constructors
  - move 'check_config_h()' to end of file and defer calling it until
    we need to (ie. in the CygwinCCompiler constructor)
  - lots of changes in 'link_shared_object()' -- mostly seems to be
    library and DLL stuff, but I don't follow it entirely
diff --git a/Lib/distutils/cygwinccompiler.py b/Lib/distutils/cygwinccompiler.py
index 650627f..3f9a5bd 100644
--- a/Lib/distutils/cygwinccompiler.py
+++ b/Lib/distutils/cygwinccompiler.py
@@ -6,53 +6,54 @@
 cygwin in no-cygwin mode).
 """
 
+# problems:
+#
+# * if you use a msvc compiled python version (1.5.2)
+#   1. you have to insert a __GNUC__ section in its config.h
+#   2. you have to generate a import library for its dll
+#      - create a def-file for python??.dll
+#      - create a import library using
+#             dlltool --dllname python15.dll --def python15.def \
+#                       --output-lib libpython15.a
+#
+#   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
+#
+# * We use put export_symbols in a def-file, and don't use 
+#   --export-all-symbols because it doesn't worked reliable in some
+#   tested configurations. And because other windows compilers also
+#   need their symbols specified this no serious problem.
+#
+# tested configurations:
+#   
+# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works 
+#   (after patching python's config.h and for C++ some other include files)
+#   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
+# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works 
+#   (ld doesn't support -shared, so we use dllwrap)   
+# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now
+#   - its dllwrap doesn't work, there is a bug in binutils 2.10.90
+#     see also .....
+#   - using gcc -mdll instead dllwrap doesn't work without -static because 
+#     it tries to link against dlls instead their import libraries. (If
+#     it finds the dll first.)
+#     By specifying -static we force ld to link against the import libraries, 
+#     this is windows standard and there are normally not the necessary symbols 
+#     in the dlls.
+
 # created 2000/05/05, Rene Liebscher
 
 __revision__ = "$Id$"
 
-import os,sys,string
-from distutils import sysconfig
+import os,sys
 from distutils.unixccompiler import UnixCCompiler
-
-# Because these compilers aren't configured in Python's config.h file by
-# default we should at least warn the user if he is using a unmodified
-# version.
-
-def check_config_h():
-    """Checks if the GCC compiler is mentioned in config.h.  If it is not,
-    compiling probably doesn't work, so print a warning to stderr.
-    """
-
-    # XXX the result of the check should be returned!
-
-    from distutils import sysconfig
-    import string,sys
-    try:
-        # It would probably better to read single lines to search.
-        # But we do this only once, and it is fast enough 
-        f=open(sysconfig.get_config_h_filename())
-        s=f.read()
-        f.close()
-        try:
-            # is somewhere a #ifdef __GNUC__ or something similar
-            string.index(s,"__GNUC__") 
-        except ValueError:
-            sys.stderr.write ("warning: "+
-                "Python's config.h doesn't seem to support your compiler.\n")
-    except IOError:
-        # if we can't read this file, we cannot say it is wrong
-        # the compiler will complain later about this file as missing
-        pass
-
-
-# This is called when the module is imported, so we make this check only once
-# XXX why not make it only when the compiler is needed?
-check_config_h()
-
+from distutils.file_util import write_file
 
 class CygwinCCompiler (UnixCCompiler):
 
     compiler_type = 'cygwin'
+    gcc_version = None
+    dllwrap_version = None
+    ld_version = None
    
     def __init__ (self,
                   verbose=0,
@@ -61,22 +62,45 @@
 
         UnixCCompiler.__init__ (self, verbose, dry_run, force)
 
+        if check_config_h()<=0:
+            self.warn(
+                "Python's config.h doesn't seem to support your compiler. "
+                "Compiling may fail because of undefined preprocessor macros.")
+        
+        (self.gcc_version, self.ld_version, self.dllwrap_version) = \
+            get_versions()
+        sys.stderr.write(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
+                         (self.gcc_version, 
+                          self.ld_version, 
+                          self.dllwrap_version) )
+
+        # ld_version >= "2.10.90" should also be able to use 
+        # gcc -mdll instead of dllwrap
+        # Older dllwraps had own version numbers, newer ones use the 
+        # same as the rest of binutils ( also ld )
+        # dllwrap 2.10.90 is buggy
+        if self.ld_version >= "2.10.90": 
+            self.linker = "gcc"
+        else:
+            self.linker = "dllwrap"
+
         # Hard-code GCC because that's what this is all about.
         # XXX optimization, warnings etc. should be customizable.
-        self.set_executables(compiler='gcc -O -Wall',
-                             compiler_so='gcc -O -Wall',
-                             linker_exe='gcc',
-                             linker_so='dllwrap --target=i386-cygwin32')
+        self.set_executables(compiler='gcc -mcygwin -O -Wall',
+                             compiler_so='gcc -mcygwin -mdll -O -Wall',
+                             linker_exe='gcc -mcygwin',
+                             linker_so=('%s -mcygwin -mdll -static' %
+                                        self.linker))
 
         # cygwin and mingw32 need different sets of libraries 
-        self.dll_libraries=[
-               # cygwin shouldn't need msvcrt, 
-               # but without the dll's will crash
-               # ( gcc version 2.91.57 )
-               # perhaps something about initialization
-               # mingw32 needs it in all cases
-                            "msvcrt"
-                            ]
+        if self.gcc_version == "2.91.57":
+            # cygwin shouldn't need msvcrt, but without the dlls will crash
+            # (gcc version 2.91.57) -- perhaps something about initialization
+            self.dll_libraries=["msvcrt"]
+            self.warn( 
+                "Consider upgrading to a newer version of gcc")
+        else:
+            self.dll_libraries=[]
         
     # __init__ ()
 
@@ -93,64 +117,67 @@
                             extra_postargs=None,
                             build_temp=None):
         
-        if libraries == None:
-            libraries = []
+        # use separate copies, so can modify the lists
+        extra_preargs = list(extra_preargs or [])
+        libraries = list(libraries or [])
         
-        # Additional libraries: the python library is always needed on
-        # Windows we need the python version without the dot, eg. '15'
-
-        pythonlib = ("python%d%d" %
-                     (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
-        libraries.append(pythonlib)
+        # Additional libraries
         libraries.extend(self.dll_libraries)
-
-        # name of extension
-
-        # XXX WRONG WRONG WRONG
-        # this is NOT the place to make guesses about Python namespaces;
-        # that MUST be done in build_ext.py
-
-        if not debug:
-            ext_name = os.path.basename(output_filename)[:-len(".pyd")]
-        else:
-            ext_name = os.path.basename(output_filename)[:-len("_d.pyd")]
-
-        def_file = os.path.join(build_temp, ext_name + ".def")
-        #exp_file = os.path.join(build_temp, ext_name + ".exp")
-        #lib_file = os.path.join(build_temp, 'lib' + ext_name + ".a")
         
-        # Make .def file
-        # (It would probably better to check if we really need this, 
-        # but for this we had to insert some unchanged parts of 
-        # UnixCCompiler, and this is not what we want.) 
-        f = open(def_file,"w")
-        f.write("EXPORTS\n") # intro
-        if export_symbols == None: 
-            # export a function "init" + ext_name
-            f.write("init" + ext_name + "\n")    
+        # we want to put some files in the same directory as the 
+        # object files are, build_temp doesn't help much
+
+        # where are the object files
+        temp_dir = os.path.dirname(objects[0])
+
+        # name of dll to give the helper files (def, lib, exp) the same name
+        (dll_name, dll_extension) = os.path.splitext(
+            os.path.basename(output_filename))
+
+        # generate the filenames for these files
+        def_file = None # this will be done later, if necessary
+        exp_file = os.path.join(temp_dir, dll_name + ".exp")
+        lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
+
+        #extra_preargs.append("--verbose")
+        if self.linker == "dllwrap":
+            extra_preargs.extend([#"--output-exp",exp_file,
+                                  "--output-lib",lib_file,
+                                 ])
         else:
-            # if there are more symbols to export write them into f
+            # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
+            extra_preargs.extend([#"-Wl,--out-implib,%s" % lib_file,
+                                 ])
+       
+        #  check what we got in export_symbols
+        if export_symbols is not None:
+            # Make .def file
+            # (It would probably better to check if we really need this, 
+            # but for this we had to insert some unchanged parts of 
+            # UnixCCompiler, and this is not what we want.) 
+            def_file = os.path.join(temp_dir, dll_name + ".def")
+            contents = [
+                "LIBRARY %s" % os.path.basename(output_filename),
+                "EXPORTS"]
             for sym in export_symbols:
-                f.write(sym+"\n")                    
-        f.close()
-        
-        if extra_preargs == None:
-                extra_preargs = []
-        
-        extra_preargs = extra_preargs + [
-                        #"--verbose",
-                        #"--output-exp",exp_file,
-                        #"--output-lib",lib_file,
-                        "--def",def_file
-                        ]
-        
+                contents.append(sym)
+            self.execute(write_file, (def_file, contents),
+                         "writing %s" % def_file)
+
+        if def_file:
+            if self.linker == "dllwrap":
+                # for dllwrap we have to use a special option
+                extra_preargs.append("--def")
+            # for gcc/ld it is specified as any other object file    
+            extra_preargs.append(def_file)
+                                                 
         # who wants symbols and a many times larger output file
         # should explicitly switch the debug mode on 
-        # otherwise we let dllwrap strip the output file
+        # otherwise we let dllwrap/ld strip the output file
         # (On my machine unstripped_file = stripped_file + 254KB
         #   10KB < stripped_file < ??100KB ) 
         if not debug: 
-            extra_preargs = extra_preargs + ["-s"] 
+            extra_preargs.append("-s") 
         
         UnixCCompiler.link_shared_object(self,
                             objects,
@@ -159,7 +186,7 @@
                             libraries,
                             library_dirs,
                             runtime_library_dirs,
-                            None, # export_symbols, we do this with our def-file
+                            None, # export_symbols, we do this in our def-file
                             debug,
                             extra_preargs,
                             extra_postargs,
@@ -181,19 +208,115 @@
                   force=0):
 
         CygwinCCompiler.__init__ (self, verbose, dry_run, force)
+        
+        # A real mingw32 doesn't need to specify a different entry point,
+        # but cygwin 2.91.57 in no-cygwin-mode needs it.
+        if self.gcc_version <= "2.91.57":
+            entry_point = '--entry _DllMain@12'
+        else:
+            entry_point = ''
 
         self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
-                             compiler_so='gcc -mno-cygwin -O -Wall',
+                             compiler_so='gcc -mno-cygwin -mdll -O -Wall',
                              linker_exe='gcc -mno-cygwin',
-                             linker_so='dllwrap' 
-                                    + ' --target=i386-mingw32'
-                                    + ' --entry _DllMain@12')
-        # mingw32 doesn't really need 'target' and cygwin too (it seems, 
-        # it is enough to specify a different entry point)                
-
-        # no additional libraries need 
-        # (only msvcrt, which is already added by CygwinCCompiler)
-
+                             linker_so='%s -mno-cygwin -mdll -static %s' 
+                                        % (self.linker, entry_point))
+        # Maybe we should also append -mthreads, but then the finished
+        # dlls need another dll (mingwm10.dll see Mingw32 docs)
+        # (-mthreads: Support thread-safe exception handling on `Mingw32')       
+        
+        # no additional libraries needed 
+        self.dll_libraries=[]
+        
     # __init__ ()
-                
+
 # class Mingw32CCompiler
+
+# Because these compilers aren't configured in Python's config.h file by
+# default, we should at least warn the user if he is using a unmodified
+# version.
+
+def check_config_h():
+    """Checks if the GCC compiler is mentioned in config.h.  If it is not,
+       compiling probably doesn't work.
+    """
+    # return values
+    #  2: OK, python was compiled with GCC
+    #  1: OK, python's config.h mentions __GCC__
+    #  0: uncertain, because we couldn't check it
+    # -1: probably not OK, because we didn't found it in config.h
+    # You could check check_config_h()>0 => OK
+
+    from distutils import sysconfig
+    import string,sys
+    # if sys.version contains GCC then python was compiled with
+    # GCC, and the config.h file should be OK
+    if -1 == string.find(sys.version,"GCC"):
+        pass # go to the next test
+    else:
+        return 2
+    
+    try:
+        # It would probably better to read single lines to search.
+        # But we do this only once, and it is fast enough 
+        f=open(sysconfig.get_config_h_filename())
+        s=f.read()
+        f.close()
+        
+        # is somewhere a #ifdef __GNUC__ or something similar
+        if -1 == string.find(s,"__GNUC__"):
+            return -1  
+        else:
+            return 1
+    except IOError:
+        # if we can't read this file, we cannot say it is wrong
+        # the compiler will complain later about this file as missing
+        pass
+    return 0
+
+def get_versions():
+    """ Try to find out the versions of gcc, ld and dllwrap.
+        If not possible it returns None for it.
+    """
+    from distutils.version import StrictVersion
+    from distutils.spawn import find_executable
+    import re
+        
+    gcc_exe = find_executable('gcc')
+    if gcc_exe:
+        out = os.popen(gcc_exe + ' -dumpversion','r')
+        out_string = out.read()
+        out.close()
+        result = re.search('(\d+\.\d+\.\d+)',out_string)
+        if result:
+            gcc_version = StrictVersion(result.group(1))
+        else:
+            gcc_version = None
+    else:
+        gcc_version = None
+    ld_exe = find_executable('ld')
+    if ld_exe:
+        out = os.popen(ld_exe + ' -v','r')
+        out_string = out.read()
+        out.close()
+        result = re.search('(\d+\.\d+\.\d+)',out_string)
+        if result:
+            ld_version = StrictVersion(result.group(1))
+        else:
+            ld_version = None
+    else:
+        ld_version = None
+    dllwrap_exe = find_executable('dllwrap')
+    if dllwrap_exe:
+        out = os.popen(dllwrap_exe + ' --version','r')
+        out_string = out.read()
+        out.close()
+        result = re.search(' (\d+\.\d+\.\d+)',out_string)
+        if result:
+            dllwrap_version = StrictVersion(result.group(1))
+        else:
+            dllwrap_version = None
+    else:
+        dllwrap_version = None
+    return (gcc_version, ld_version, dllwrap_version)
+