comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/distutils/fcompiler/gnu.py @ 87:2a2c65a20a8b

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