summaryrefslogtreecommitdiff
path: root/numpy/distutils/fcompiler/gnu.py
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/distutils/fcompiler/gnu.py')
-rw-r--r--numpy/distutils/fcompiler/gnu.py341
1 files changed, 341 insertions, 0 deletions
diff --git a/numpy/distutils/fcompiler/gnu.py b/numpy/distutils/fcompiler/gnu.py
new file mode 100644
index 000000000..64be7fbfe
--- /dev/null
+++ b/numpy/distutils/fcompiler/gnu.py
@@ -0,0 +1,341 @@
+import re
+import os
+import sys
+import warnings
+
+from numpy.distutils.cpuinfo import cpu
+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
+
+class GnuFCompiler(FCompiler):
+
+ compiler_type = 'gnu'
+
+ 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)
+ # GNU Fortran (GCC) 3.3.3 (Debian 20040401)
+ # 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)
+
+ executables = {
+ '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' : ["g77", "-g", "-Wall"],
+ 'archiver' : ["ar", "-cr"],
+ 'ranlib' : ["ranlib"],
+ 'linker_exe' : ["g77", "-g", "-Wall"]
+ }
+ module_dir_switch = None
+ module_include_switch = None
+
+ # 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'
+
+ 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.
+ # #if re.match(r'(darwin)', sys.platform):
+ # # return
+ # return FCompiler.get_linker_so(self)
+
+ def get_flags_linker_so(self):
+ opt = self.linker_so[1:]
+ if sys.platform=='darwin':
+ # MACOSX_DEPLOYMENT_TARGET must be at least 10.3. This is
+ # a reasonable default value even when building on 10.4 when using
+ # the official Python distribution and those derived from it (when
+ # not broken).
+ target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', None)
+ if target is None or target == '':
+ target = '10.3'
+ major, minor = target.split('.')
+ if int(minor) < 3:
+ minor = '3'
+ warnings.warn('Environment variable '
+ 'MACOSX_DEPLOYMENT_TARGET reset to %s.%s' % (major, minor))
+ os.environ['MACOSX_DEPLOYMENT_TARGET'] = '%s.%s' % (major,
+ minor)
+
+ opt.extend(['-undefined', 'dynamic_lookup', '-bundle'])
+ else:
+ opt.append("-shared")
+ if sys.platform[:5]=='sunos':
+ # SunOS often has dynamically loaded symbols defined in the
+ # static library libg2c.a The linker doesn't like this. To
+ # ignore the problem, use the -mimpure-text flag. It isn't
+ # the safest thing, but seems to work. 'man gcc' says:
+ # ".. Instead of using -mimpure-text, you should compile all
+ # source code with -fpic or -fPIC."
+ opt.append('-mimpure-text')
+ return opt
+
+ def get_libgcc_dir(self):
+ status, output = exec_command(self.compiler_f77 +
+ ['-print-libgcc-file-name'],
+ use_tee=0)
+ if not status:
+ return os.path.dirname(output)
+ 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
+
+ def get_libraries(self):
+ opt = []
+ d = self.get_libgcc_dir()
+ if d is not None:
+ g2c = self.g2c + '-pic'
+ f = self.static_lib_format % (g2c, self.static_lib_extension)
+ if not os.path.isfile(os.path.join(d,f)):
+ g2c = self.g2c
+ else:
+ g2c = self.g2c
+
+ 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
+
+ def get_flags_debug(self):
+ return ['-g']
+
+ def get_flags_opt(self):
+ if self.get_version()<='3.3.3':
+ # With this compiler version building Fortran BLAS/LAPACK
+ # with -O3 caused failures in lib.lapack heevr,syevr tests.
+ opt = ['-O2']
+ else:
+ opt = ['-O3']
+ opt.append('-funroll-loops')
+ return opt
+
+ def get_flags_arch(self):
+ opt = []
+ if sys.platform=='darwin':
+ if os.name != 'posix':
+ # this should presumably correspond to Apple
+ if cpu.is_ppc():
+ opt.append('-arch ppc')
+ elif cpu.is_i386():
+ opt.append('-arch i386')
+ for a in '601 602 603 603e 604 604e 620 630 740 7400 7450 750'\
+ '403 505 801 821 823 860'.split():
+ if getattr(cpu,'is_ppc%s'%a)():
+ opt.append('-mcpu='+a)
+ opt.append('-mtune='+a)
+ break
+ return opt
+
+ # default march options in case we find nothing better
+ if cpu.is_i686():
+ march_opt = '-march=i686'
+ elif cpu.is_i586():
+ march_opt = '-march=i586'
+ elif cpu.is_i486():
+ march_opt = '-march=i486'
+ elif cpu.is_i386():
+ march_opt = '-march=i386'
+ else:
+ march_opt = ''
+
+ gnu_ver = self.get_version()
+
+ if gnu_ver >= '0.5.26': # gcc 3.0
+ if cpu.is_AthlonK6():
+ march_opt = '-march=k6'
+ elif cpu.is_AthlonK7():
+ march_opt = '-march=athlon'
+
+ if gnu_ver >= '3.1.1':
+ if cpu.is_AthlonK6_2():
+ march_opt = '-march=k6-2'
+ elif cpu.is_AthlonK6_3():
+ march_opt = '-march=k6-3'
+ elif cpu.is_AthlonMP():
+ march_opt = '-march=athlon-mp'
+ # there's also: athlon-tbird, athlon-4, athlon-xp
+ elif cpu.is_Nocona():
+ march_opt = '-march=nocona'
+ elif cpu.is_Core2():
+ march_opt = '-march=nocona'
+ elif cpu.is_Xeon() and cpu.is_64bit():
+ march_opt = '-march=nocona'
+ elif cpu.is_Prescott():
+ march_opt = '-march=prescott'
+ elif cpu.is_PentiumIV():
+ march_opt = '-march=pentium4'
+ elif cpu.is_PentiumIII():
+ march_opt = '-march=pentium3'
+ elif cpu.is_PentiumM():
+ march_opt = '-march=pentium3'
+ elif cpu.is_PentiumII():
+ march_opt = '-march=pentium2'
+
+ if gnu_ver >= '3.4':
+ if cpu.is_Opteron():
+ march_opt = '-march=opteron'
+ elif cpu.is_Athlon64():
+ march_opt = '-march=athlon64'
+
+ 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 = ''
+
+ if march_opt:
+ opt.append(march_opt)
+
+ # other CPU flags
+ if gnu_ver >= '3.1.1':
+ if cpu.has_mmx(): opt.append('-mmmx')
+ if cpu.has_3dnow(): opt.append('-m3dnow')
+
+ if gnu_ver > '3.2.2':
+ if cpu.has_sse2(): opt.append('-msse2')
+ if cpu.has_sse(): opt.append('-msse')
+ if gnu_ver >= '3.4':
+ if cpu.has_sse3(): opt.append('-msse3')
+ if cpu.is_Intel():
+ opt.append('-fomit-frame-pointer')
+ if cpu.is_32bit():
+ opt.append('-malign-double')
+ return opt
+
+class Gnu95FCompiler(GnuFCompiler):
+
+ compiler_type = 'gnu95'
+
+ 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)
+
+ executables = {
+ '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' : ["gfortran", "-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'
+
+ 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':
+ opt.remove('cc_dynamic')
+ return opt
+
+if __name__ == '__main__':
+ from distutils import log
+ log.set_verbosity(2)
+ from numpy.distutils.fcompiler import new_fcompiler
+ #compiler = new_fcompiler(compiler='gnu')
+ compiler = GnuFCompiler()
+ compiler.customize()
+ print compiler.get_version()