[Numpy-svn] r3723 - in trunk/numpy/distutils: fcompiler tests

numpy-svn@scip... numpy-svn@scip...
Sun Apr 22 15:58:06 CDT 2007


Author: cookedm
Date: 2007-04-22 15:57:58 -0500 (Sun, 22 Apr 2007)
New Revision: 3723

Added:
   trunk/numpy/distutils/tests/test_fcompiler_gnu.py
Modified:
   trunk/numpy/distutils/fcompiler/__init__.py
   trunk/numpy/distutils/fcompiler/gnu.py
   trunk/numpy/distutils/fcompiler/intel.py
   trunk/numpy/distutils/fcompiler/vast.py
Log:
Better version handling for gnu and intel Fortran compilers

- gnu compilers check if the version is >= 4, in which case it's gfortran
- add a test file for gnu compiler check
- simplify version matching on intel compilers to be more flexible
- add FCompiler.find_executables so that subclasses can find executables
  at .customize() time, instead of when the class is created.



Modified: trunk/numpy/distutils/fcompiler/__init__.py
===================================================================
--- trunk/numpy/distutils/fcompiler/__init__.py	2007-04-22 04:29:42 UTC (rev 3722)
+++ trunk/numpy/distutils/fcompiler/__init__.py	2007-04-22 20:57:58 UTC (rev 3723)
@@ -28,7 +28,7 @@
 
     Methods that subclasses may redefine:
 
-        get_version_cmd(), get_linker_so(), get_version()
+        find_executables(), get_version_cmd(), get_linker_so(), get_version()
         get_flags(), get_flags_opt(), get_flags_arch(), get_flags_debug()
         get_flags_f77(), get_flags_opt_f77(), get_flags_arch_f77(),
         get_flags_debug_f77(), get_flags_f90(), get_flags_opt_f90(),
@@ -113,6 +113,11 @@
     ## They are private to FCompiler class and may return unexpected
     ## results if used elsewhere. So, you have been warned..
 
+    def find_executables(self):
+        """Modify self.executables to hold found executables, instead of
+        searching for them at class creation time."""
+        pass
+
     def get_version_cmd(self):
         """ Compiler command to print out version information. """
         f77 = self.executables['compiler_f77']
@@ -267,6 +272,7 @@
             noarch = conf.get('noarch',[None,noopt])[1]
         debug = conf.get('debug',[None,0])[1]
 
+        self.find_executables()
 
         f77 = self.__get_cmd('compiler_f77','F77',(conf,'f77exec'))
         f90 = self.__get_cmd('compiler_f90','F90',(conf,'f90exec'))

Modified: trunk/numpy/distutils/fcompiler/gnu.py
===================================================================
--- trunk/numpy/distutils/fcompiler/gnu.py	2007-04-22 04:29:42 UTC (rev 3722)
+++ trunk/numpy/distutils/fcompiler/gnu.py	2007-04-22 20:57:58 UTC (rev 3723)
@@ -4,7 +4,6 @@
 import warnings
 
 from numpy.distutils.cpuinfo import cpu
-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, msvc_runtime_library
@@ -12,8 +11,32 @@
 class GnuFCompiler(FCompiler):
 
     compiler_type = 'gnu'
-    version_match = simple_version_match(start=r'GNU Fortran (?!95)')
 
+    def gnu_version_match(self, version_string):
+        """Handle the different versions of GNU fortran compilers"""
+        m = re.match(r'GNU Fortran', version_string)
+        if not m:
+            return None
+        m = re.match(r'GNU Fortran\s+95.*?([0-9-.]+)', version_string)
+        if m:
+            return ('gfortran', m.group(1))
+        m = re.match(r'GNU Fortran.*?([0-9-.]+)', version_string)
+        if m:
+            v = m.group(1)
+            if v.startswith('0') or v.startswith('2') or v.startswith('3'):
+                # the '0' is for early g77's
+                return ('g77', v)
+            else:
+                # at some point in the 4.x series, the ' 95' was dropped
+                # from the version string
+                return ('gfortran', v)
+
+    def version_match(self, version_string):
+        v = self.gnu_version_match(version_string)
+        if not v or v[0] != 'g77':
+            return None
+        return v[1]
+
     # 'g77 --version' results
     # SunOS: GNU Fortran (GCC 3.2) 3.2 20020814 (release)
     # Debian: GNU Fortran (GCC) 3.3.3 20040110 (prerelease) (Debian)
@@ -21,18 +44,15 @@
     #         GNU Fortran 0.5.25 20010319 (prerelease)
     # Redhat: GNU Fortran (GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
 
-    for fc_exe in map(find_executable,['g77','f77']):
-        if os.path.isfile(fc_exe):
-            break
     executables = {
-        'version_cmd'  : [fc_exe,"--version"],
-        'compiler_f77' : [fc_exe, "-g", "-Wall","-fno-second-underscore"],
+        'version_cmd'  : ["g77", "--version"],
+        'compiler_f77' : ["g77", "-g", "-Wall","-fno-second-underscore"],
         'compiler_f90' : None, # Use --fcompiler=gnu95 for f90 codes
         'compiler_fix' : None,
-        'linker_so'    : [fc_exe, "-g", "-Wall"],
+        'linker_so'    : ["g77", "-g", "-Wall"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"],
-        'linker_exe'   : [fc_exe, "-g", "-Wall"]
+        'linker_exe'   : ["g77", "-g", "-Wall"]
         }
     module_dir_switch = None
     module_include_switch = None
@@ -51,6 +71,13 @@
 
     suggested_f90_compiler = 'gnu95'
 
+    def find_executables(self):
+        for fc_exe in [find_executable(c) for c in ['g77','f77']]:
+            if os.path.isfile(fc_exe):
+                break
+        for key in ['version_cmd', 'compiler_f77', 'linker_so', 'linker_exe']:
+            self.executables[key][0] = fc_exe
+
     #def get_linker_so(self):
     #    # win32 linking should be handled by standard linker
     #    # Darwin g77 cannot be used as a linker.
@@ -218,12 +245,11 @@
         if gnu_ver >= '3.4.4':
             if cpu.is_PentiumM():
                 march_opt = '-march=pentium-m'
-        
         # Future:
         # if gnu_ver >= '4.3':
         #    if cpu.is_Core2():
         #        march_opt = '-march=core2'
-        
+
         # Note: gcc 3.2 on win32 has breakage with -march specified
         if '3.1.1' <= gnu_ver <= '3.4' and sys.platform=='win32':
             march_opt = ''
@@ -250,26 +276,32 @@
 class Gnu95FCompiler(GnuFCompiler):
 
     compiler_type = 'gnu95'
-    version_match = simple_version_match(start='GNU Fortran (95|\(GCC\))')
 
+    def version_match(self, version_string):
+        v = self.gnu_version_match(version_string)
+        if not v or v[0] != 'gfortran':
+            return None
+        return v[1]
+
     # 'gfortran --version' results:
+    # XXX is the below right?
     # Debian: GNU Fortran 95 (GCC 4.0.3 20051023 (prerelease) (Debian 4.0.2-3))
+    #         GNU Fortran 95 (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
     # OS X: GNU Fortran 95 (GCC) 4.1.0
     #       GNU Fortran 95 (GCC) 4.2.0 20060218 (experimental)
     #       GNU Fortran (GCC) 4.3.0 20070316 (experimental)
 
-    for fc_exe in map(find_executable,['gfortran','f95']):
-        if os.path.isfile(fc_exe):
-            break
     executables = {
-        'version_cmd'  : [fc_exe,"--version"],
-        'compiler_f77' : [fc_exe,"-Wall","-ffixed-form","-fno-second-underscore"],
-        'compiler_f90' : [fc_exe,"-Wall","-fno-second-underscore"],
-        'compiler_fix' : [fc_exe,"-Wall","-ffixed-form","-fno-second-underscore"],
-        'linker_so'    : [fc_exe,"-Wall"],
+        'version_cmd'  : ["gfortran", "--version"],
+        'compiler_f77' : ["gfortran", "-Wall", "-ffixed-form",
+                          "-fno-second-underscore"],
+        'compiler_f90' : ["gfortran", "-Wall", "-fno-second-underscore"],
+        'compiler_fix' : ["gfortran", "-Wall", "-ffixed-form",
+                          "-fno-second-underscore"],
+        'linker_so'    : ["gfortran", "-Wall"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"],
-        'linker_exe'   : [fc_exe,"-Wall"]
+        'linker_exe'   : ["gfortran", "-Wall"]
         }
 
     # use -mno-cygwin flag for g77 when Python is not Cygwin-Python
@@ -283,6 +315,14 @@
 
     g2c = 'gfortran'
 
+    def find_executables(self):
+        for fc_exe in [find_executable(c) for c in ['gfortran','f95']]:
+            if os.path.isfile(fc_exe):
+                break
+        for key in ['version_cmd', 'compiler_f77', 'compiler_f90',
+                    'compiler_fix', 'linker_so', 'linker_exe']:
+            self.executables[key][0] = fc_exe
+
     def get_libraries(self):
         opt = GnuFCompiler.get_libraries(self)
         if sys.platform == 'darwin':

Modified: trunk/numpy/distutils/fcompiler/intel.py
===================================================================
--- trunk/numpy/distutils/fcompiler/intel.py	2007-04-22 04:29:42 UTC (rev 3722)
+++ trunk/numpy/distutils/fcompiler/intel.py	2007-04-22 20:57:58 UTC (rev 3723)
@@ -1,3 +1,6 @@
+# -*- encoding: iso-8859-1 -*-
+# above encoding b/c there's a non-ASCII character in the sample output
+# of intele
 # http://developer.intel.com/software/products/compilers/flin/
 
 import os
@@ -4,14 +7,18 @@
 import sys
 
 from numpy.distutils.cpuinfo import cpu
+from numpy.distutils.ccompiler import simple_version_match
 from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file
 from numpy.distutils.exec_command import find_executable
 
+def intel_version_match(type):
+    # Match against the important stuff in the version string
+    return simple_version_match(start=r'Intel.*?Fortran.*?%s.*?Version' % (type,))
+
 class IntelFCompiler(FCompiler):
 
     compiler_type = 'intel'
-    version_pattern = r'Intel\(R\) Fortran Compiler for 32-bit '\
-                      'applications, Version (?P<version>[^\s*]*)'
+    version_match = intel_version_match('32-bit')
 
     for fc_exe in map(find_executable,['ifort','ifc']):
         if os.path.isfile(fc_exe):
@@ -74,10 +81,9 @@
 
 class IntelItaniumFCompiler(IntelFCompiler):
     compiler_type = 'intele'
-    version_pattern = r'Intel\(R\) Fortran (90 Compiler Itanium\(TM\)|Itanium\(R\)) Compiler'\
-                      ' for (the Itanium\(TM\)|Itanium\(R\))-based applications(,|)'\
-                      '\s+Version (?P<version>[^\s*]*)'
 
+    version_match = intel_version_match('Itanium')
+
 #Intel(R) Fortran Itanium(R) Compiler for Itanium(R)-based applications
 #Version 9.1    Build 20060928 Package ID: l_fc_c_9.1.039
 #Copyright (C) 1985-2006 Intel Corporation.  All rights reserved.
@@ -101,8 +107,7 @@
 class IntelEM64TFCompiler(IntelFCompiler):
     compiler_type = 'intelem'
 
-    version_pattern = r'Intel\(R\) Fortran Compiler for Intel\(R\) EM64T-based '\
-                      'applications, Version (?P<version>[^\s*]*)'
+    version_match = intel_version_match('EM64T-based')
 
     for fc_exe in map(find_executable,['ifort','efort','efc']):
         if os.path.isfile(fc_exe):
@@ -125,11 +130,13 @@
             opt.extend(['-tpp7', '-xW'])
         return opt
 
+# Is there no difference in the version string between the above compilers
+# and the Visual compilers?
+
 class IntelVisualFCompiler(FCompiler):
 
     compiler_type = 'intelv'
-    version_pattern = r'Intel\(R\) Fortran Compiler for 32-bit applications, '\
-                      'Version (?P<version>[^\s*]*)'
+    version_match = intel_version_match('32-bit')
 
     ar_exe = 'lib.exe'
     fc_exe = 'ifl'
@@ -181,9 +188,7 @@
 class IntelItaniumVisualFCompiler(IntelVisualFCompiler):
 
     compiler_type = 'intelev'
-    version_pattern = r'Intel\(R\) Fortran (90 Compiler Itanium\(TM\)|Itanium\(R\)) Compiler'\
-                      ' for (the Itanium\(TM\)|Itanium\(R\))-based applications(,|)'\
-                      '\s+Version (?P<version>[^\s*]*)'
+    version_match = intel_version_match('Itanium')
 
     fc_exe = 'efl' # XXX this is a wild guess
     ar_exe = IntelVisualFCompiler.ar_exe

Modified: trunk/numpy/distutils/fcompiler/vast.py
===================================================================
--- trunk/numpy/distutils/fcompiler/vast.py	2007-04-22 04:29:42 UTC (rev 3722)
+++ trunk/numpy/distutils/fcompiler/vast.py	2007-04-22 20:57:58 UTC (rev 3723)
@@ -26,6 +26,9 @@
     module_dir_switch = None  #XXX Fix me
     module_include_switch = None #XXX Fix me
 
+    def find_executables(self):
+        pass
+
     def get_version_cmd(self):
         f90 = self.compiler_f90[0]
         d,b = os.path.split(f90)

Added: trunk/numpy/distutils/tests/test_fcompiler_gnu.py
===================================================================
--- trunk/numpy/distutils/tests/test_fcompiler_gnu.py	2007-04-22 04:29:42 UTC (rev 3722)
+++ trunk/numpy/distutils/tests/test_fcompiler_gnu.py	2007-04-22 20:57:58 UTC (rev 3723)
@@ -0,0 +1,52 @@
+from numpy.testing import *
+
+set_package_path()
+import numpy.distutils.fcompiler
+restore_path()
+
+g77_version_strings = [
+    ('GNU Fortran 0.5.25 20010319 (prerelease)', '0.5.25'),
+    ('GNU Fortran (GCC 3.2) 3.2 20020814 (release)', '3.2'),
+    ('GNU Fortran (GCC) 3.3.3 20040110 (prerelease) (Debian)', '3.3.3'),
+    ('GNU Fortran (GCC) 3.3.3 (Debian 20040401)', '3.3.3'),
+    ('GNU Fortran (GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) 3.2.2'
+       ' 20030222 (Red Hat Linux 3.2.2-5)', '3.2.2'),
+]
+
+gfortran_version_strings = [
+    ('GNU Fortran 95 (GCC 4.0.3 20051023 (prerelease) (Debian 4.0.2-3))',
+     '4.0.3'),
+    ('GNU Fortran 95 (GCC) 4.1.0', '4.1.0'),
+    ('GNU Fortran 95 (GCC) 4.2.0 20060218 (experimental)', '4.2.0'),
+    ('GNU Fortran (GCC) 4.3.0 20070316 (experimental)', '4.3.0'),
+]
+
+class test_g77_versions(NumpyTestCase):
+    def test_g77_version(self):
+        fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu')
+        for vs, version in g77_version_strings:
+            v = fc.version_match(vs)
+            assert v == version, (vs, v)
+
+    def test_not_g77(self):
+        fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu')
+        for vs, _ in gfortran_version_strings:
+            v = fc.version_match(vs)
+            assert v is None, (vs, v)
+
+class test_gortran_versions(NumpyTestCase):
+    def test_gfortran_version(self):
+        fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu95')
+        for vs, version in gfortran_version_strings:
+            v = fc.version_match(vs)
+            assert v == version, (vs, v)
+
+    def test_not_gfortran(self):
+        fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu95')
+        for vs, _ in g77_version_strings:
+            v = fc.version_match(vs)
+            assert v is None, (vs, v)
+
+
+if __name__ == '__main__':
+    NumpyTest.run()



More information about the Numpy-svn mailing list