comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/distutils/command/config.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 # Added Fortran compiler support to config. Currently useful only for
2 # try_compile call. try_run works but is untested for most of Fortran
3 # compilers (they must define linker_exe first).
4 # Pearu Peterson
5 from __future__ import division, absolute_import, print_function
6
7 import os, signal
8 import warnings
9 import sys
10
11 from distutils.command.config import config as old_config
12 from distutils.command.config import LANG_EXT
13 from distutils import log
14 from distutils.file_util import copy_file
15 from distutils.ccompiler import CompileError, LinkError
16 import distutils
17 from numpy.distutils.exec_command import exec_command
18 from numpy.distutils.mingw32ccompiler import generate_manifest
19 from numpy.distutils.command.autodist import check_inline, check_compiler_gcc4
20 from numpy.distutils.compat import get_exception
21
22 LANG_EXT['f77'] = '.f'
23 LANG_EXT['f90'] = '.f90'
24
25 class config(old_config):
26 old_config.user_options += [
27 ('fcompiler=', None, "specify the Fortran compiler type"),
28 ]
29
30 def initialize_options(self):
31 self.fcompiler = None
32 old_config.initialize_options(self)
33
34 def try_run(self, body, headers=None, include_dirs=None,
35 libraries=None, library_dirs=None, lang="c"):
36 warnings.warn("\n+++++++++++++++++++++++++++++++++++++++++++++++++\n" \
37 "Usage of try_run is deprecated: please do not \n" \
38 "use it anymore, and avoid configuration checks \n" \
39 "involving running executable on the target machine.\n" \
40 "+++++++++++++++++++++++++++++++++++++++++++++++++\n",
41 DeprecationWarning)
42 return old_config.try_run(self, body, headers, include_dirs, libraries,
43 library_dirs, lang)
44
45 def _check_compiler (self):
46 old_config._check_compiler(self)
47 from numpy.distutils.fcompiler import FCompiler, new_fcompiler
48
49 if sys.platform == 'win32' and self.compiler.compiler_type == 'msvc':
50 # XXX: hack to circumvent a python 2.6 bug with msvc9compiler:
51 # initialize call query_vcvarsall, which throws an IOError, and
52 # causes an error along the way without much information. We try to
53 # catch it here, hoping it is early enough, and print an helpful
54 # message instead of Error: None.
55 if not self.compiler.initialized:
56 try:
57 self.compiler.initialize()
58 except IOError:
59 e = get_exception()
60 msg = """\
61 Could not initialize compiler instance: do you have Visual Studio
62 installed? If you are trying to build with MinGW, please use "python setup.py
63 build -c mingw32" instead. If you have Visual Studio installed, check it is
64 correctly installed, and the right version (VS 2008 for python 2.6, 2.7 and 3.2,
65 VS 2010 for >= 3.3).
66
67 Original exception was: %s, and the Compiler class was %s
68 ============================================================================""" \
69 % (e, self.compiler.__class__.__name__)
70 print ("""\
71 ============================================================================""")
72 raise distutils.errors.DistutilsPlatformError(msg)
73
74 # After MSVC is initialized, add an explicit /MANIFEST to linker
75 # flags. See issues gh-4245 and gh-4101 for details. Also
76 # relevant are issues 4431 and 16296 on the Python bug tracker.
77 from distutils import msvc9compiler
78 if msvc9compiler.get_build_version() >= 10:
79 for ldflags in [self.compiler.ldflags_shared,
80 self.compiler.ldflags_shared_debug]:
81 if '/MANIFEST' not in ldflags:
82 ldflags.append('/MANIFEST')
83
84 if not isinstance(self.fcompiler, FCompiler):
85 self.fcompiler = new_fcompiler(compiler=self.fcompiler,
86 dry_run=self.dry_run, force=1,
87 c_compiler=self.compiler)
88 if self.fcompiler is not None:
89 self.fcompiler.customize(self.distribution)
90 if self.fcompiler.get_version():
91 self.fcompiler.customize_cmd(self)
92 self.fcompiler.show_customization()
93
94 def _wrap_method(self, mth, lang, args):
95 from distutils.ccompiler import CompileError
96 from distutils.errors import DistutilsExecError
97 save_compiler = self.compiler
98 if lang in ['f77', 'f90']:
99 self.compiler = self.fcompiler
100 try:
101 ret = mth(*((self,)+args))
102 except (DistutilsExecError, CompileError):
103 msg = str(get_exception())
104 self.compiler = save_compiler
105 raise CompileError
106 self.compiler = save_compiler
107 return ret
108
109 def _compile (self, body, headers, include_dirs, lang):
110 return self._wrap_method(old_config._compile, lang,
111 (body, headers, include_dirs, lang))
112
113 def _link (self, body,
114 headers, include_dirs,
115 libraries, library_dirs, lang):
116 if self.compiler.compiler_type=='msvc':
117 libraries = (libraries or [])[:]
118 library_dirs = (library_dirs or [])[:]
119 if lang in ['f77', 'f90']:
120 lang = 'c' # always use system linker when using MSVC compiler
121 if self.fcompiler:
122 for d in self.fcompiler.library_dirs or []:
123 # correct path when compiling in Cygwin but with
124 # normal Win Python
125 if d.startswith('/usr/lib'):
126 s, o = exec_command(['cygpath', '-w', d],
127 use_tee=False)
128 if not s: d = o
129 library_dirs.append(d)
130 for libname in self.fcompiler.libraries or []:
131 if libname not in libraries:
132 libraries.append(libname)
133 for libname in libraries:
134 if libname.startswith('msvc'): continue
135 fileexists = False
136 for libdir in library_dirs or []:
137 libfile = os.path.join(libdir, '%s.lib' % (libname))
138 if os.path.isfile(libfile):
139 fileexists = True
140 break
141 if fileexists: continue
142 # make g77-compiled static libs available to MSVC
143 fileexists = False
144 for libdir in library_dirs:
145 libfile = os.path.join(libdir, 'lib%s.a' % (libname))
146 if os.path.isfile(libfile):
147 # copy libname.a file to name.lib so that MSVC linker
148 # can find it
149 libfile2 = os.path.join(libdir, '%s.lib' % (libname))
150 copy_file(libfile, libfile2)
151 self.temp_files.append(libfile2)
152 fileexists = True
153 break
154 if fileexists: continue
155 log.warn('could not find library %r in directories %s' \
156 % (libname, library_dirs))
157 elif self.compiler.compiler_type == 'mingw32':
158 generate_manifest(self)
159 return self._wrap_method(old_config._link, lang,
160 (body, headers, include_dirs,
161 libraries, library_dirs, lang))
162
163 def check_header(self, header, include_dirs=None, library_dirs=None, lang='c'):
164 self._check_compiler()
165 return self.try_compile(
166 "/* we need a dummy line to make distutils happy */",
167 [header], include_dirs)
168
169 def check_decl(self, symbol,
170 headers=None, include_dirs=None):
171 self._check_compiler()
172 body = """
173 int main()
174 {
175 #ifndef %s
176 (void) %s;
177 #endif
178 ;
179 return 0;
180 }""" % (symbol, symbol)
181
182 return self.try_compile(body, headers, include_dirs)
183
184 def check_macro_true(self, symbol,
185 headers=None, include_dirs=None):
186 self._check_compiler()
187 body = """
188 int main()
189 {
190 #if %s
191 #else
192 #error false or undefined macro
193 #endif
194 ;
195 return 0;
196 }""" % (symbol,)
197
198 return self.try_compile(body, headers, include_dirs)
199
200 def check_type(self, type_name, headers=None, include_dirs=None,
201 library_dirs=None):
202 """Check type availability. Return True if the type can be compiled,
203 False otherwise"""
204 self._check_compiler()
205
206 # First check the type can be compiled
207 body = r"""
208 int main() {
209 if ((%(name)s *) 0)
210 return 0;
211 if (sizeof (%(name)s))
212 return 0;
213 }
214 """ % {'name': type_name}
215
216 st = False
217 try:
218 try:
219 self._compile(body % {'type': type_name},
220 headers, include_dirs, 'c')
221 st = True
222 except distutils.errors.CompileError:
223 st = False
224 finally:
225 self._clean()
226
227 return st
228
229 def check_type_size(self, type_name, headers=None, include_dirs=None, library_dirs=None, expected=None):
230 """Check size of a given type."""
231 self._check_compiler()
232
233 # First check the type can be compiled
234 body = r"""
235 typedef %(type)s npy_check_sizeof_type;
236 int main ()
237 {
238 static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) >= 0)];
239 test_array [0] = 0
240
241 ;
242 return 0;
243 }
244 """
245 self._compile(body % {'type': type_name},
246 headers, include_dirs, 'c')
247 self._clean()
248
249 if expected:
250 body = r"""
251 typedef %(type)s npy_check_sizeof_type;
252 int main ()
253 {
254 static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) == %(size)s)];
255 test_array [0] = 0
256
257 ;
258 return 0;
259 }
260 """
261 for size in expected:
262 try:
263 self._compile(body % {'type': type_name, 'size': size},
264 headers, include_dirs, 'c')
265 self._clean()
266 return size
267 except CompileError:
268 pass
269
270 # this fails to *compile* if size > sizeof(type)
271 body = r"""
272 typedef %(type)s npy_check_sizeof_type;
273 int main ()
274 {
275 static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) <= %(size)s)];
276 test_array [0] = 0
277
278 ;
279 return 0;
280 }
281 """
282
283 # The principle is simple: we first find low and high bounds of size
284 # for the type, where low/high are looked up on a log scale. Then, we
285 # do a binary search to find the exact size between low and high
286 low = 0
287 mid = 0
288 while True:
289 try:
290 self._compile(body % {'type': type_name, 'size': mid},
291 headers, include_dirs, 'c')
292 self._clean()
293 break
294 except CompileError:
295 #log.info("failure to test for bound %d" % mid)
296 low = mid + 1
297 mid = 2 * mid + 1
298
299 high = mid
300 # Binary search:
301 while low != high:
302 mid = (high - low) // 2 + low
303 try:
304 self._compile(body % {'type': type_name, 'size': mid},
305 headers, include_dirs, 'c')
306 self._clean()
307 high = mid
308 except CompileError:
309 low = mid + 1
310 return low
311
312 def check_func(self, func,
313 headers=None, include_dirs=None,
314 libraries=None, library_dirs=None,
315 decl=False, call=False, call_args=None):
316 # clean up distutils's config a bit: add void to main(), and
317 # return a value.
318 self._check_compiler()
319 body = []
320 if decl:
321 if type(decl) == str:
322 body.append(decl)
323 else:
324 body.append("int %s (void);" % func)
325 # Handle MSVC intrinsics: force MS compiler to make a function call.
326 # Useful to test for some functions when built with optimization on, to
327 # avoid build error because the intrinsic and our 'fake' test
328 # declaration do not match.
329 body.append("#ifdef _MSC_VER")
330 body.append("#pragma function(%s)" % func)
331 body.append("#endif")
332 body.append("int main (void) {")
333 if call:
334 if call_args is None:
335 call_args = ''
336 body.append(" %s(%s);" % (func, call_args))
337 else:
338 body.append(" %s;" % func)
339 body.append(" return 0;")
340 body.append("}")
341 body = '\n'.join(body) + "\n"
342
343 return self.try_link(body, headers, include_dirs,
344 libraries, library_dirs)
345
346 def check_funcs_once(self, funcs,
347 headers=None, include_dirs=None,
348 libraries=None, library_dirs=None,
349 decl=False, call=False, call_args=None):
350 """Check a list of functions at once.
351
352 This is useful to speed up things, since all the functions in the funcs
353 list will be put in one compilation unit.
354
355 Arguments
356 ---------
357 funcs : seq
358 list of functions to test
359 include_dirs : seq
360 list of header paths
361 libraries : seq
362 list of libraries to link the code snippet to
363 libraru_dirs : seq
364 list of library paths
365 decl : dict
366 for every (key, value), the declaration in the value will be
367 used for function in key. If a function is not in the
368 dictionay, no declaration will be used.
369 call : dict
370 for every item (f, value), if the value is True, a call will be
371 done to the function f.
372 """
373 self._check_compiler()
374 body = []
375 if decl:
376 for f, v in decl.items():
377 if v:
378 body.append("int %s (void);" % f)
379
380 # Handle MS intrinsics. See check_func for more info.
381 body.append("#ifdef _MSC_VER")
382 for func in funcs:
383 body.append("#pragma function(%s)" % func)
384 body.append("#endif")
385
386 body.append("int main (void) {")
387 if call:
388 for f in funcs:
389 if f in call and call[f]:
390 if not (call_args and f in call_args and call_args[f]):
391 args = ''
392 else:
393 args = call_args[f]
394 body.append(" %s(%s);" % (f, args))
395 else:
396 body.append(" %s;" % f)
397 else:
398 for f in funcs:
399 body.append(" %s;" % f)
400 body.append(" return 0;")
401 body.append("}")
402 body = '\n'.join(body) + "\n"
403
404 return self.try_link(body, headers, include_dirs,
405 libraries, library_dirs)
406
407 def check_inline(self):
408 """Return the inline keyword recognized by the compiler, empty string
409 otherwise."""
410 return check_inline(self)
411
412 def check_compiler_gcc4(self):
413 """Return True if the C compiler is gcc >= 4."""
414 return check_compiler_gcc4(self)
415
416 def get_output(self, body, headers=None, include_dirs=None,
417 libraries=None, library_dirs=None,
418 lang="c", use_tee=None):
419 """Try to compile, link to an executable, and run a program
420 built from 'body' and 'headers'. Returns the exit status code
421 of the program and its output.
422 """
423 warnings.warn("\n+++++++++++++++++++++++++++++++++++++++++++++++++\n" \
424 "Usage of get_output is deprecated: please do not \n" \
425 "use it anymore, and avoid configuration checks \n" \
426 "involving running executable on the target machine.\n" \
427 "+++++++++++++++++++++++++++++++++++++++++++++++++\n",
428 DeprecationWarning)
429 from distutils.ccompiler import CompileError, LinkError
430 self._check_compiler()
431 exitcode, output = 255, ''
432 try:
433 grabber = GrabStdout()
434 try:
435 src, obj, exe = self._link(body, headers, include_dirs,
436 libraries, library_dirs, lang)
437 grabber.restore()
438 except:
439 output = grabber.data
440 grabber.restore()
441 raise
442 exe = os.path.join('.', exe)
443 exitstatus, output = exec_command(exe, execute_in='.',
444 use_tee=use_tee)
445 if hasattr(os, 'WEXITSTATUS'):
446 exitcode = os.WEXITSTATUS(exitstatus)
447 if os.WIFSIGNALED(exitstatus):
448 sig = os.WTERMSIG(exitstatus)
449 log.error('subprocess exited with signal %d' % (sig,))
450 if sig == signal.SIGINT:
451 # control-C
452 raise KeyboardInterrupt
453 else:
454 exitcode = exitstatus
455 log.info("success!")
456 except (CompileError, LinkError):
457 log.info("failure.")
458 self._clean()
459 return exitcode, output
460
461 class GrabStdout(object):
462
463 def __init__(self):
464 self.sys_stdout = sys.stdout
465 self.data = ''
466 sys.stdout = self
467
468 def write (self, data):
469 self.sys_stdout.write(data)
470 self.data += data
471
472 def flush (self):
473 self.sys_stdout.flush()
474
475 def restore(self):
476 sys.stdout = self.sys_stdout