annotate DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/distutils/fcompiler/gnu.py @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2a2c65a20a8b
children
rev   line source
Chris@87 1 from __future__ import division, absolute_import, print_function
Chris@87 2
Chris@87 3 import re
Chris@87 4 import os
Chris@87 5 import sys
Chris@87 6 import warnings
Chris@87 7 import platform
Chris@87 8 import tempfile
Chris@87 9 from subprocess import Popen, PIPE, STDOUT
Chris@87 10
Chris@87 11 from numpy.distutils.cpuinfo import cpu
Chris@87 12 from numpy.distutils.fcompiler import FCompiler
Chris@87 13 from numpy.distutils.exec_command import exec_command
Chris@87 14 from numpy.distutils.misc_util import msvc_runtime_library
Chris@87 15 from numpy.distutils.compat import get_exception
Chris@87 16
Chris@87 17 compilers = ['GnuFCompiler', 'Gnu95FCompiler']
Chris@87 18
Chris@87 19 TARGET_R = re.compile("Target: ([a-zA-Z0-9_\-]*)")
Chris@87 20
Chris@87 21 # XXX: handle cross compilation
Chris@87 22 def is_win64():
Chris@87 23 return sys.platform == "win32" and platform.architecture()[0] == "64bit"
Chris@87 24
Chris@87 25 if is_win64():
Chris@87 26 #_EXTRAFLAGS = ["-fno-leading-underscore"]
Chris@87 27 _EXTRAFLAGS = []
Chris@87 28 else:
Chris@87 29 _EXTRAFLAGS = []
Chris@87 30
Chris@87 31 class GnuFCompiler(FCompiler):
Chris@87 32 compiler_type = 'gnu'
Chris@87 33 compiler_aliases = ('g77',)
Chris@87 34 description = 'GNU Fortran 77 compiler'
Chris@87 35
Chris@87 36 def gnu_version_match(self, version_string):
Chris@87 37 """Handle the different versions of GNU fortran compilers"""
Chris@87 38 m = re.search(r'GNU Fortran', version_string)
Chris@87 39 if not m:
Chris@87 40 return None
Chris@87 41 m = re.search(r'GNU Fortran\s+95.*?([0-9-.]+)', version_string)
Chris@87 42 if m:
Chris@87 43 return ('gfortran', m.group(1))
Chris@87 44 m = re.search(r'GNU Fortran.*?\-?([0-9-.]+)', version_string)
Chris@87 45 if m:
Chris@87 46 v = m.group(1)
Chris@87 47 if v.startswith('0') or v.startswith('2') or v.startswith('3'):
Chris@87 48 # the '0' is for early g77's
Chris@87 49 return ('g77', v)
Chris@87 50 else:
Chris@87 51 # at some point in the 4.x series, the ' 95' was dropped
Chris@87 52 # from the version string
Chris@87 53 return ('gfortran', v)
Chris@87 54
Chris@87 55 def version_match(self, version_string):
Chris@87 56 v = self.gnu_version_match(version_string)
Chris@87 57 if not v or v[0] != 'g77':
Chris@87 58 return None
Chris@87 59 return v[1]
Chris@87 60
Chris@87 61 # 'g77 --version' results
Chris@87 62 # SunOS: GNU Fortran (GCC 3.2) 3.2 20020814 (release)
Chris@87 63 # Debian: GNU Fortran (GCC) 3.3.3 20040110 (prerelease) (Debian)
Chris@87 64 # GNU Fortran (GCC) 3.3.3 (Debian 20040401)
Chris@87 65 # GNU Fortran 0.5.25 20010319 (prerelease)
Chris@87 66 # 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)
Chris@87 67 # GNU Fortran (GCC) 3.4.2 (mingw-special)
Chris@87 68
Chris@87 69 possible_executables = ['g77', 'f77']
Chris@87 70 executables = {
Chris@87 71 'version_cmd' : [None, "--version"],
Chris@87 72 'compiler_f77' : [None, "-g", "-Wall", "-fno-second-underscore"],
Chris@87 73 'compiler_f90' : None, # Use --fcompiler=gnu95 for f90 codes
Chris@87 74 'compiler_fix' : None,
Chris@87 75 'linker_so' : [None, "-g", "-Wall"],
Chris@87 76 'archiver' : ["ar", "-cr"],
Chris@87 77 'ranlib' : ["ranlib"],
Chris@87 78 'linker_exe' : [None, "-g", "-Wall"]
Chris@87 79 }
Chris@87 80 module_dir_switch = None
Chris@87 81 module_include_switch = None
Chris@87 82
Chris@87 83 # Cygwin: f771: warning: -fPIC ignored for target (all code is
Chris@87 84 # position independent)
Chris@87 85 if os.name != 'nt' and sys.platform != 'cygwin':
Chris@87 86 pic_flags = ['-fPIC']
Chris@87 87
Chris@87 88 # use -mno-cygwin for g77 when Python is not Cygwin-Python
Chris@87 89 if sys.platform == 'win32':
Chris@87 90 for key in ['version_cmd', 'compiler_f77', 'linker_so', 'linker_exe']:
Chris@87 91 executables[key].append('-mno-cygwin')
Chris@87 92
Chris@87 93 g2c = 'g2c'
Chris@87 94
Chris@87 95 suggested_f90_compiler = 'gnu95'
Chris@87 96
Chris@87 97 #def get_linker_so(self):
Chris@87 98 # # win32 linking should be handled by standard linker
Chris@87 99 # # Darwin g77 cannot be used as a linker.
Chris@87 100 # #if re.match(r'(darwin)', sys.platform):
Chris@87 101 # # return
Chris@87 102 # return FCompiler.get_linker_so(self)
Chris@87 103
Chris@87 104 def get_flags_linker_so(self):
Chris@87 105 opt = self.linker_so[1:]
Chris@87 106 if sys.platform=='darwin':
Chris@87 107 target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', None)
Chris@87 108 # If MACOSX_DEPLOYMENT_TARGET is set, we simply trust the value
Chris@87 109 # and leave it alone. But, distutils will complain if the
Chris@87 110 # environment's value is different from the one in the Python
Chris@87 111 # Makefile used to build Python. We let disutils handle this
Chris@87 112 # error checking.
Chris@87 113 if not target:
Chris@87 114 # If MACOSX_DEPLOYMENT_TARGET is not set in the environment,
Chris@87 115 # we try to get it first from the Python Makefile and then we
Chris@87 116 # fall back to setting it to 10.3 to maximize the set of
Chris@87 117 # versions we can work with. This is a reasonable default
Chris@87 118 # even when using the official Python dist and those derived
Chris@87 119 # from it.
Chris@87 120 import distutils.sysconfig as sc
Chris@87 121 g = {}
Chris@87 122 filename = sc.get_makefile_filename()
Chris@87 123 sc.parse_makefile(filename, g)
Chris@87 124 target = g.get('MACOSX_DEPLOYMENT_TARGET', '10.3')
Chris@87 125 os.environ['MACOSX_DEPLOYMENT_TARGET'] = target
Chris@87 126 if target == '10.3':
Chris@87 127 s = 'Env. variable MACOSX_DEPLOYMENT_TARGET set to 10.3'
Chris@87 128 warnings.warn(s)
Chris@87 129
Chris@87 130 opt.extend(['-undefined', 'dynamic_lookup', '-bundle'])
Chris@87 131 else:
Chris@87 132 opt.append("-shared")
Chris@87 133 if sys.platform.startswith('sunos'):
Chris@87 134 # SunOS often has dynamically loaded symbols defined in the
Chris@87 135 # static library libg2c.a The linker doesn't like this. To
Chris@87 136 # ignore the problem, use the -mimpure-text flag. It isn't
Chris@87 137 # the safest thing, but seems to work. 'man gcc' says:
Chris@87 138 # ".. Instead of using -mimpure-text, you should compile all
Chris@87 139 # source code with -fpic or -fPIC."
Chris@87 140 opt.append('-mimpure-text')
Chris@87 141 return opt
Chris@87 142
Chris@87 143 def get_libgcc_dir(self):
Chris@87 144 status, output = exec_command(self.compiler_f77 +
Chris@87 145 ['-print-libgcc-file-name'],
Chris@87 146 use_tee=0)
Chris@87 147 if not status:
Chris@87 148 return os.path.dirname(output)
Chris@87 149 return None
Chris@87 150
Chris@87 151 def get_library_dirs(self):
Chris@87 152 opt = []
Chris@87 153 if sys.platform[:5] != 'linux':
Chris@87 154 d = self.get_libgcc_dir()
Chris@87 155 if d:
Chris@87 156 # if windows and not cygwin, libg2c lies in a different folder
Chris@87 157 if sys.platform == 'win32' and not d.startswith('/usr/lib'):
Chris@87 158 d = os.path.normpath(d)
Chris@87 159 if not os.path.exists(os.path.join(d, "lib%s.a" % self.g2c)):
Chris@87 160 d2 = os.path.abspath(os.path.join(d,
Chris@87 161 '../../../../lib'))
Chris@87 162 if os.path.exists(os.path.join(d2, "lib%s.a" % self.g2c)):
Chris@87 163 opt.append(d2)
Chris@87 164 opt.append(d)
Chris@87 165 return opt
Chris@87 166
Chris@87 167 def get_libraries(self):
Chris@87 168 opt = []
Chris@87 169 d = self.get_libgcc_dir()
Chris@87 170 if d is not None:
Chris@87 171 g2c = self.g2c + '-pic'
Chris@87 172 f = self.static_lib_format % (g2c, self.static_lib_extension)
Chris@87 173 if not os.path.isfile(os.path.join(d, f)):
Chris@87 174 g2c = self.g2c
Chris@87 175 else:
Chris@87 176 g2c = self.g2c
Chris@87 177
Chris@87 178 if g2c is not None:
Chris@87 179 opt.append(g2c)
Chris@87 180 c_compiler = self.c_compiler
Chris@87 181 if sys.platform == 'win32' and c_compiler and \
Chris@87 182 c_compiler.compiler_type=='msvc':
Chris@87 183 # the following code is not needed (read: breaks) when using MinGW
Chris@87 184 # in case want to link F77 compiled code with MSVC
Chris@87 185 opt.append('gcc')
Chris@87 186 runtime_lib = msvc_runtime_library()
Chris@87 187 if runtime_lib:
Chris@87 188 opt.append(runtime_lib)
Chris@87 189 if sys.platform == 'darwin':
Chris@87 190 opt.append('cc_dynamic')
Chris@87 191 return opt
Chris@87 192
Chris@87 193 def get_flags_debug(self):
Chris@87 194 return ['-g']
Chris@87 195
Chris@87 196 def get_flags_opt(self):
Chris@87 197 v = self.get_version()
Chris@87 198 if v and v<='3.3.3':
Chris@87 199 # With this compiler version building Fortran BLAS/LAPACK
Chris@87 200 # with -O3 caused failures in lib.lapack heevr,syevr tests.
Chris@87 201 opt = ['-O2']
Chris@87 202 else:
Chris@87 203 opt = ['-O3']
Chris@87 204 opt.append('-funroll-loops')
Chris@87 205 return opt
Chris@87 206
Chris@87 207 def _c_arch_flags(self):
Chris@87 208 """ Return detected arch flags from CFLAGS """
Chris@87 209 from distutils import sysconfig
Chris@87 210 try:
Chris@87 211 cflags = sysconfig.get_config_vars()['CFLAGS']
Chris@87 212 except KeyError:
Chris@87 213 return []
Chris@87 214 arch_re = re.compile(r"-arch\s+(\w+)")
Chris@87 215 arch_flags = []
Chris@87 216 for arch in arch_re.findall(cflags):
Chris@87 217 arch_flags += ['-arch', arch]
Chris@87 218 return arch_flags
Chris@87 219
Chris@87 220 def get_flags_arch(self):
Chris@87 221 return []
Chris@87 222
Chris@87 223 def runtime_library_dir_option(self, dir):
Chris@87 224 return '-Wl,-rpath="%s"' % dir
Chris@87 225
Chris@87 226 class Gnu95FCompiler(GnuFCompiler):
Chris@87 227 compiler_type = 'gnu95'
Chris@87 228 compiler_aliases = ('gfortran',)
Chris@87 229 description = 'GNU Fortran 95 compiler'
Chris@87 230
Chris@87 231 def version_match(self, version_string):
Chris@87 232 v = self.gnu_version_match(version_string)
Chris@87 233 if not v or v[0] != 'gfortran':
Chris@87 234 return None
Chris@87 235 v = v[1]
Chris@87 236 if v>='4.':
Chris@87 237 # gcc-4 series releases do not support -mno-cygwin option
Chris@87 238 pass
Chris@87 239 else:
Chris@87 240 # use -mno-cygwin flag for gfortran when Python is not Cygwin-Python
Chris@87 241 if sys.platform == 'win32':
Chris@87 242 for key in ['version_cmd', 'compiler_f77', 'compiler_f90',
Chris@87 243 'compiler_fix', 'linker_so', 'linker_exe']:
Chris@87 244 self.executables[key].append('-mno-cygwin')
Chris@87 245 return v
Chris@87 246
Chris@87 247 # 'gfortran --version' results:
Chris@87 248 # XXX is the below right?
Chris@87 249 # Debian: GNU Fortran 95 (GCC 4.0.3 20051023 (prerelease) (Debian 4.0.2-3))
Chris@87 250 # GNU Fortran 95 (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
Chris@87 251 # OS X: GNU Fortran 95 (GCC) 4.1.0
Chris@87 252 # GNU Fortran 95 (GCC) 4.2.0 20060218 (experimental)
Chris@87 253 # GNU Fortran (GCC) 4.3.0 20070316 (experimental)
Chris@87 254
Chris@87 255 possible_executables = ['gfortran', 'f95']
Chris@87 256 executables = {
Chris@87 257 'version_cmd' : ["<F90>", "--version"],
Chris@87 258 'compiler_f77' : [None, "-Wall", "-g", "-ffixed-form",
Chris@87 259 "-fno-second-underscore"] + _EXTRAFLAGS,
Chris@87 260 'compiler_f90' : [None, "-Wall", "-g",
Chris@87 261 "-fno-second-underscore"] + _EXTRAFLAGS,
Chris@87 262 'compiler_fix' : [None, "-Wall", "-g","-ffixed-form",
Chris@87 263 "-fno-second-underscore"] + _EXTRAFLAGS,
Chris@87 264 'linker_so' : ["<F90>", "-Wall", "-g"],
Chris@87 265 'archiver' : ["ar", "-cr"],
Chris@87 266 'ranlib' : ["ranlib"],
Chris@87 267 'linker_exe' : [None, "-Wall"]
Chris@87 268 }
Chris@87 269
Chris@87 270 module_dir_switch = '-J'
Chris@87 271 module_include_switch = '-I'
Chris@87 272
Chris@87 273 g2c = 'gfortran'
Chris@87 274
Chris@87 275 def _universal_flags(self, cmd):
Chris@87 276 """Return a list of -arch flags for every supported architecture."""
Chris@87 277 if not sys.platform == 'darwin':
Chris@87 278 return []
Chris@87 279 arch_flags = []
Chris@87 280 # get arches the C compiler gets.
Chris@87 281 c_archs = self._c_arch_flags()
Chris@87 282 if "i386" in c_archs:
Chris@87 283 c_archs[c_archs.index("i386")] = "i686"
Chris@87 284 # check the arches the Fortran compiler supports, and compare with
Chris@87 285 # arch flags from C compiler
Chris@87 286 for arch in ["ppc", "i686", "x86_64", "ppc64"]:
Chris@87 287 if _can_target(cmd, arch) and arch in c_archs:
Chris@87 288 arch_flags.extend(["-arch", arch])
Chris@87 289 return arch_flags
Chris@87 290
Chris@87 291 def get_flags(self):
Chris@87 292 flags = GnuFCompiler.get_flags(self)
Chris@87 293 arch_flags = self._universal_flags(self.compiler_f90)
Chris@87 294 if arch_flags:
Chris@87 295 flags[:0] = arch_flags
Chris@87 296 return flags
Chris@87 297
Chris@87 298 def get_flags_linker_so(self):
Chris@87 299 flags = GnuFCompiler.get_flags_linker_so(self)
Chris@87 300 arch_flags = self._universal_flags(self.linker_so)
Chris@87 301 if arch_flags:
Chris@87 302 flags[:0] = arch_flags
Chris@87 303 return flags
Chris@87 304
Chris@87 305 def get_library_dirs(self):
Chris@87 306 opt = GnuFCompiler.get_library_dirs(self)
Chris@87 307 if sys.platform == 'win32':
Chris@87 308 c_compiler = self.c_compiler
Chris@87 309 if c_compiler and c_compiler.compiler_type == "msvc":
Chris@87 310 target = self.get_target()
Chris@87 311 if target:
Chris@87 312 d = os.path.normpath(self.get_libgcc_dir())
Chris@87 313 root = os.path.join(d, os.pardir, os.pardir, os.pardir, os.pardir)
Chris@87 314 mingwdir = os.path.normpath(os.path.join(root, target, "lib"))
Chris@87 315 full = os.path.join(mingwdir, "libmingwex.a")
Chris@87 316 if os.path.exists(full):
Chris@87 317 opt.append(mingwdir)
Chris@87 318 return opt
Chris@87 319
Chris@87 320 def get_libraries(self):
Chris@87 321 opt = GnuFCompiler.get_libraries(self)
Chris@87 322 if sys.platform == 'darwin':
Chris@87 323 opt.remove('cc_dynamic')
Chris@87 324 if sys.platform == 'win32':
Chris@87 325 c_compiler = self.c_compiler
Chris@87 326 if c_compiler and c_compiler.compiler_type == "msvc":
Chris@87 327 if "gcc" in opt:
Chris@87 328 i = opt.index("gcc")
Chris@87 329 opt.insert(i+1, "mingwex")
Chris@87 330 opt.insert(i+1, "mingw32")
Chris@87 331 # XXX: fix this mess, does not work for mingw
Chris@87 332 if is_win64():
Chris@87 333 c_compiler = self.c_compiler
Chris@87 334 if c_compiler and c_compiler.compiler_type == "msvc":
Chris@87 335 return []
Chris@87 336 else:
Chris@87 337 raise NotImplementedError("Only MS compiler supported with gfortran on win64")
Chris@87 338 return opt
Chris@87 339
Chris@87 340 def get_target(self):
Chris@87 341 status, output = exec_command(self.compiler_f77 +
Chris@87 342 ['-v'],
Chris@87 343 use_tee=0)
Chris@87 344 if not status:
Chris@87 345 m = TARGET_R.search(output)
Chris@87 346 if m:
Chris@87 347 return m.group(1)
Chris@87 348 return ""
Chris@87 349
Chris@87 350 def get_flags_opt(self):
Chris@87 351 if is_win64():
Chris@87 352 return ['-O0']
Chris@87 353 else:
Chris@87 354 return GnuFCompiler.get_flags_opt(self)
Chris@87 355
Chris@87 356 def _can_target(cmd, arch):
Chris@87 357 """Return true is the command supports the -arch flag for the given
Chris@87 358 architecture."""
Chris@87 359 newcmd = cmd[:]
Chris@87 360 fid, filename = tempfile.mkstemp(suffix=".f")
Chris@87 361 try:
Chris@87 362 d = os.path.dirname(filename)
Chris@87 363 output = os.path.splitext(filename)[0] + ".o"
Chris@87 364 try:
Chris@87 365 newcmd.extend(["-arch", arch, "-c", filename])
Chris@87 366 p = Popen(newcmd, stderr=STDOUT, stdout=PIPE, cwd=d)
Chris@87 367 p.communicate()
Chris@87 368 return p.returncode == 0
Chris@87 369 finally:
Chris@87 370 if os.path.exists(output):
Chris@87 371 os.remove(output)
Chris@87 372 finally:
Chris@87 373 os.remove(filename)
Chris@87 374 return False
Chris@87 375
Chris@87 376 if __name__ == '__main__':
Chris@87 377 from distutils import log
Chris@87 378 log.set_verbosity(2)
Chris@87 379
Chris@87 380 compiler = GnuFCompiler()
Chris@87 381 compiler.customize()
Chris@87 382 print(compiler.get_version())
Chris@87 383
Chris@87 384 try:
Chris@87 385 compiler = Gnu95FCompiler()
Chris@87 386 compiler.customize()
Chris@87 387 print(compiler.get_version())
Chris@87 388 except Exception:
Chris@87 389 msg = get_exception()
Chris@87 390 print(msg)