[Numpy-svn] r2919 - in trunk/numpy/distutils: . command fcompiler

numpy-svn at scipy.org numpy-svn at scipy.org
Fri Jul 28 16:02:11 EDT 2006


Author: cookedm
Date: 2006-07-28 15:02:07 -0500 (Fri, 28 Jul 2006)
New Revision: 2919

Modified:
   trunk/numpy/distutils/ccompiler.py
   trunk/numpy/distutils/command/build_ext.py
   trunk/numpy/distutils/fcompiler/gnu.py
   trunk/numpy/distutils/mingw32ccompiler.py
   trunk/numpy/distutils/misc_util.py
   trunk/numpy/distutils/system_info.py
Log:
Fix #114: Problems with building with MSVC and GCC under Cygwin


Modified: trunk/numpy/distutils/ccompiler.py
===================================================================
--- trunk/numpy/distutils/ccompiler.py	2006-07-28 16:27:18 UTC (rev 2918)
+++ trunk/numpy/distutils/ccompiler.py	2006-07-28 20:02:07 UTC (rev 2919)
@@ -18,7 +18,7 @@
 _old_init_posix = distutils.sysconfig._init_posix
 def _new_init_posix():
     _old_init_posix()
-    distutils.sysconfig._config_vars['OPT'] = '-Wall -g -O2'
+    distutils.sysconfig._config_vars['OPT'] = '-Wall -g -O0'
 #distutils.sysconfig._init_posix = _new_init_posix
 
 # Using customized CCompiler.spawn.

Modified: trunk/numpy/distutils/command/build_ext.py
===================================================================
--- trunk/numpy/distutils/command/build_ext.py	2006-07-28 16:27:18 UTC (rev 2918)
+++ trunk/numpy/distutils/command/build_ext.py	2006-07-28 20:02:07 UTC (rev 2919)
@@ -8,13 +8,17 @@
 
 from distutils.dep_util import newer_group
 from distutils.command.build_ext import build_ext as old_build_ext
+from distutils.errors import DistutilsFileError, DistutilsSetupError
+from distutils.file_util import copy_file
 
 from numpy.distutils import log
+from numpy.distutils.exec_command import exec_command
+from numpy.distutils.system_info import combine_paths
 from numpy.distutils.misc_util import filter_sources, has_f_sources, \
      has_cxx_sources, get_ext_source_files, all_strings, \
      get_numpy_include_dirs, is_sequence
-from distutils.errors import DistutilsFileError, DistutilsSetupError
 
+
 class build_ext (old_build_ext):
 
     description = "build C/C++/F extensions (compile/link to build directory)"
@@ -290,9 +294,8 @@
 
         # Always use system linker when using MSVC compiler.
         if self.compiler.compiler_type=='msvc' and use_fortran_linker:
-            c_libraries.extend(self.fcompiler.libraries)
-            c_library_dirs.extend(self.fcompiler.library_dirs)
-            use_fortran_linker = 0
+            self._libs_with_msvc_and_fortran(c_libraries, c_library_dirs)
+            use_fortran_linker = False
 
         if use_fortran_linker:
             if cxx_sources:
@@ -330,6 +333,32 @@
 
         return
 
+    def _libs_with_msvc_and_fortran(self, c_libraries, c_library_dirs):
+        # Always use system linker when using MSVC compiler.
+        f_lib_dirs = []
+        for dir in self.fcompiler.library_dirs:
+            # correct path when compiling in Cygwin but with normal Win
+            # Python
+            if dir.startswith('/usr/lib'):
+                s,o = exec_command(['cygpath', '-w', dir], use_tee=False)
+                if not s:
+                    dir = o
+            f_lib_dirs.append(dir)
+        c_library_dirs.extend(f_lib_dirs)
+
+        # make g77-compiled static libs available to MSVC
+        lib_added = False
+        for lib in self.fcompiler.libraries:
+            if not lib.startswtih('msvcr'):
+                c_libraries.append(lib)
+                p = combine_paths(f_lib_dirs, 'lib' + lib + '.a')
+                if p:
+                    dst_name = os.path.join(self.build_temp, lib + '.lib')
+                    copy_file(p[0], dst_name)
+                    if not lib_added:
+                        c_library_dirs.append(self.build_temp)
+                        lib_added = True
+
     def get_source_files (self):
         self.check_extensions_list(self.extensions)
         filenames = []

Modified: trunk/numpy/distutils/fcompiler/gnu.py
===================================================================
--- trunk/numpy/distutils/fcompiler/gnu.py	2006-07-28 16:27:18 UTC (rev 2918)
+++ trunk/numpy/distutils/fcompiler/gnu.py	2006-07-28 20:02:07 UTC (rev 2919)
@@ -8,7 +8,7 @@
 from numpy.distutils.ccompiler import simple_version_match
 from numpy.distutils.fcompiler import FCompiler
 from numpy.distutils.exec_command import exec_command, find_executable
-from numpy.distutils.misc_util import mingw32
+from numpy.distutils.misc_util import mingw32, msvc_runtime_library
 
 class GnuFCompiler(FCompiler):
 
@@ -38,10 +38,16 @@
     module_dir_switch = None
     module_include_switch = None
 
-    # Cygwin: f771: warning: -fPIC ignored for target (all code is position independent)
+    # Cygwin: f771: warning: -fPIC ignored for target (all code is
+    # position independent)
     if os.name != 'nt' and sys.platform!='cygwin':
         pic_flags = ['-fPIC']
 
+    # use -mno-cygwin for g77 when Python is not Cygwin-Python
+    if sys.platform == 'win32':
+        for key in ['version_cmd', 'compiler_f77', 'linker_so', 'linker_exe']:
+            executables[key].append('-mno-cygwin')
+
     g2c = 'g2c'
 
     #def get_linker_so(self):
@@ -52,7 +58,7 @@
     #    return FCompiler.get_linker_so(self)
 
     def get_flags_linker_so(self):
-        opt = []
+        opt = self.linker_so[1:]
         if sys.platform=='darwin':
             target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', None)
             if target is None:
@@ -79,17 +85,26 @@
         return opt
 
     def get_libgcc_dir(self):
-        status, output = exec_command('%s -print-libgcc-file-name' \
-                                      % (self.compiler_f77[0]),use_tee=0)
+        status, output = exec_command(self.compiler_f77 +
+                                      '-print-libgcc-file-name',
+                                      use_tee=0)
         if not status:
             return os.path.dirname(output)
-        return
+        return None
 
     def get_library_dirs(self):
         opt = []
         if sys.platform[:5] != 'linux':
             d = self.get_libgcc_dir()
             if d:
+                # if windows and not cygwin, libg2c lies in a different folder
+                if sys.platform == 'win32' and not d.startswith('/usr/lib'):
+                    d = os.path.normpath(d)
+                    if not os.path.exists(os.path.join(d, 'libg2c.a')):
+                        d2 = os.path.abspath(os.path.join(d,
+                                                          '../../../../lib'))
+                        if os.path.exists(os.path.join(d2, 'libg2c.a')):
+                            opt.append(d2)
                 opt.append(d)
         return opt
 
@@ -104,13 +119,14 @@
         else:
             g2c = self.g2c
 
-        if sys.platform=='win32':
-            # To avoid undefined reference __EH_FRAME_BEGIN__ linker error,
-            # don't use -lgcc option for mingw32 g77 linker.
-            if not mingw32():
-                opt.append('gcc')
         if g2c is not None:
             opt.append(g2c)
+        if sys.platform == 'win32':
+            # in case want to link F77 compiled code with MSVC
+            opt.append('gcc')
+            runtime_lib = msvc_runtime_library()
+            if runtime_lib:
+                opt.append(runtime_lib)
         if sys.platform == 'darwin':
             opt.append('cc_dynamic')
         return opt
@@ -242,6 +258,13 @@
         'ranlib'       : ["ranlib"],
         'linker_exe'   : [fc_exe,"-Wall"]
         }
+
+    # use -mno-cygwin flag for g77 when Python is not Cygwin-Python
+    if sys.platform == 'win32':
+        for key in ['version_cmd', 'compiler_f77', 'compiler_f90',
+                    'compiler_fix', 'linker_so', 'linker_exe']:
+            executables[key].append('-mno-cygwin')
+
     module_dir_switch = '-J'
     module_include_switch = '-I'
 

Modified: trunk/numpy/distutils/mingw32ccompiler.py
===================================================================
--- trunk/numpy/distutils/mingw32ccompiler.py	2006-07-28 16:27:18 UTC (rev 2918)
+++ trunk/numpy/distutils/mingw32ccompiler.py	2006-07-28 20:02:07 UTC (rev 2919)
@@ -27,6 +27,7 @@
 from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
 
 from distutils.unixccompiler import UnixCCompiler
+from numpy.distutils.misc_util import msvc_runtime_library
 
 # the same as cygwin plus some additional parameters
 class Mingw32CCompiler(distutils.cygwinccompiler.CygwinCCompiler):
@@ -93,9 +94,9 @@
                                  % (self.linker, entry_point))
         else:
             self.set_executables(compiler='gcc -mno-cygwin -O2 -Wall',
-                                 compiler_so='gcc -O2 -Wall -Wstrict-prototypes',
-                                 linker_exe='g++ ',
-                                 linker_so='g++ -shared')
+                                 compiler_so='gcc -mno-cygwin -O2 -Wall -Wstrict-prototypes',
+                                 linker_exe='g++ -mno-cygwin',
+                                 linker_so='g++ -mno-cygwin -shared')
         # added for python2.3 support
         # we can't pass it through set_executables because pre 2.2 would fail
         self.compiler_cxx = ['g++']
@@ -104,7 +105,7 @@
         # dlls need another dll (mingwm10.dll see Mingw32 docs)
         # (-mthreads: Support thread-safe exception handling on `Mingw32')
 
-        # no additional libraries needed -- maybe need msvcr71
+        # no additional libraries needed
         #self.dll_libraries=[]
         return
 
@@ -124,11 +125,13 @@
              extra_postargs=None,
              build_temp=None,
              target_lang=None):
-        if sys.version[:3] > '2.3':
-            if libraries:
-                libraries.append('msvcr71')
-            else:
-                libraries = ['msvcr71']
+        # Include the appropiate MSVC runtime library if Python was built
+        # with MSVC >= 7.0 (MinGW standard is msvcrt)
+        runtime_library = msvc_runtime_library()
+        if runtime_library:
+            if not libraries:
+                libraries = []
+            libraries.append(runtime_library)
         args = (self,
                 target_desc,
                 objects,

Modified: trunk/numpy/distutils/misc_util.py
===================================================================
--- trunk/numpy/distutils/misc_util.py	2006-07-28 16:27:18 UTC (rev 2918)
+++ trunk/numpy/distutils/misc_util.py	2006-07-28 20:02:07 UTC (rev 2919)
@@ -242,6 +242,19 @@
             return True
     return False
 
+def msvc_runtime_library():
+    "return name of MSVC runtime library if Python was built with MSVC >= 7"
+    msc_pos = sys.version.find('MSC v.')
+    if msc_pos != -1:
+        msc_ver = sys.version[msc_pos+6:msc_pos+10]
+        lib = {'1300' : 'msvcr70',    # MSVC 7.0
+               '1310' : 'msvcr71',    # MSVC 7.1
+               '1400' : 'msvcr80',    # MSVC 8
+              }.get(msc_ver, None)
+    else:
+        lib = None
+    return lib
+
 #########################
 
 #XXX need support for .C that is also C++

Modified: trunk/numpy/distutils/system_info.py
===================================================================
--- trunk/numpy/distutils/system_info.py	2006-07-28 16:27:18 UTC (rev 2918)
+++ trunk/numpy/distutils/system_info.py	2006-07-28 20:02:07 UTC (rev 2919)
@@ -492,6 +492,18 @@
     def get_libraries(self, key='libraries'):
         return self.get_libs(key,'')
 
+    def library_extensions(self):
+        static_exts = ['.a']
+        if sys.platform == 'win32':
+            static_exts.append('.lib')  # .lib is used by MSVC
+        if self.search_static_first:
+            exts = static_exts + [so_ext]
+        else:
+            exts = [so_ext] + static_exts
+        if sys.platform == 'cygwin':
+            exts.append('.dll.a')
+        return exts
+
     def check_libs(self,lib_dir,libs,opt_libs =[]):
         """If static or shared libraries are available then return
         their info dictionary.
@@ -499,12 +511,7 @@
         Checks for all libraries as shared libraries first, then
         static (or vice versa if self.search_static_first is True).
         """
-        if self.search_static_first:
-            exts = ['.a', so_ext]
-        else:
-            exts = [so_ext, '.a']
-        if sys.platform == 'cygwin':
-            exts.append('.dll.a')
+        exts = self.library_extensions()
         info = None
         for ext in exts:
             info = self._check_libs(lib_dir,libs,opt_libs,[ext])
@@ -520,12 +527,7 @@
 
         Checks each library for shared or static.
         """
-        if self.search_static_first:
-            exts = ['.a', so_ext]
-        else:
-            exts = [so_ext, '.a']
-        if sys.platform=='cygwin':
-            exts.append('.dll.a')
+        exts = self.library_extensions()
         info = self._check_libs(lib_dir,libs,opt_libs,exts)
         if not info:
             log.info('  libraries %s not found in %s', ','.join(libs), lib_dir)
@@ -534,17 +536,29 @@
     def _lib_list(self, lib_dir, libs, exts):
         assert is_string(lib_dir)
         liblist = []
+        # under windows first try without 'lib' prefix
+        if sys.platform == 'win32':
+            lib_prefixes = ['', 'lib']
+        else:
+            lib_prefixes = ['lib']
         # for each library name, see if we can find a file for it.
         for l in libs:
             for ext in exts:
-                p = self.combine_paths(lib_dir, 'lib'+l+ext)
+                for prefix in lib_prefixes:
+                    p = self.combine_paths(lib_dir, prefix+l+ext)
+                    if p:
+                        break
                 if p:
                     assert len(p)==1
+                    # ??? splitext on p[0] would do this for cygwin
+                    # doesn't seem correct
+                    if ext == '.dll.a':
+                        l += '.dll'
                     liblist.append(l)
                     break
         return liblist
 
-    def _check_libs(self,lib_dir,libs, opt_libs, exts):
+    def _check_libs(self, lib_dir, libs, opt_libs, exts):
         found_libs = self._lib_list(lib_dir, libs, exts)
         if len(found_libs) == len(libs):
             info = {'libraries' : found_libs, 'library_dirs' : [lib_dir]}
@@ -556,6 +570,9 @@
             return None
 
     def combine_paths(self,*args):
+        """Return a list of existing paths composed by all combinations
+        of items from the arguments.
+        """
         return combine_paths(*args,**{'verbosity':self.verbosity})
 
 
@@ -837,12 +854,12 @@
         lapack = None
         atlas_1 = None
         for d in lib_dirs:
-            atlas = self.check_libs(d,atlas_libs,[])
-            lapack_atlas = self.check_libs(d,['lapack_atlas'],[])
+            atlas = self.check_libs2(d,atlas_libs,[])
+            lapack_atlas = self.check_libs2(d,['lapack_atlas'],[])
             if atlas is not None:
-                lib_dirs2 = self.combine_paths(d,['atlas*','ATLAS*'])+[d]
+                lib_dirs2 = [d] + self.combine_paths(d,['atlas*','ATLAS*'])
                 for d2 in lib_dirs2:
-                    lapack = self.check_libs(d2,lapack_libs,[])
+                    lapack = self.check_libs2(d2,lapack_libs,[])
                     if lapack is not None:
                         break
                 else:
@@ -886,10 +903,16 @@
         lapack_dir = lapack['library_dirs'][0]
         lapack_name = lapack['libraries'][0]
         lapack_lib = None
-        for e in ['.a',so_ext]:
-            fn = os.path.join(lapack_dir,'lib'+lapack_name+e)
-            if os.path.exists(fn):
-                lapack_lib = fn
+        lib_prefixes = ['lib']
+        if sys.platform == 'win32':
+            lib_prefixes.append('')
+        for e in self.library_extensions():
+            for prefix in lib_prefixes:
+                fn = os.path.join(lapack_dir,prefix+lapack_name+e)
+                if os.path.exists(fn):
+                    lapack_lib = fn
+                    break
+            if lapack_lib:
                 break
         if lapack_lib is not None:
             sz = os.stat(lapack_lib)[6]
@@ -919,7 +942,7 @@
                                    self._lib_names + self._lib_atlas)
         atlas = None
         for d in lib_dirs:
-            atlas = self.check_libs(d,atlas_libs,[])
+            atlas = self.check_libs2(d,atlas_libs,[])
             if atlas is not None:
                 break
         if atlas is None:




More information about the Numpy-svn mailing list