Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/distutils/command/build_ext.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 """ Modified version of build_ext that handles fortran source files. | |
2 | |
3 """ | |
4 from __future__ import division, absolute_import, print_function | |
5 | |
6 import os | |
7 import sys | |
8 from glob import glob | |
9 | |
10 from distutils.dep_util import newer_group | |
11 from distutils.command.build_ext import build_ext as old_build_ext | |
12 from distutils.errors import DistutilsFileError, DistutilsSetupError,\ | |
13 DistutilsError | |
14 from distutils.file_util import copy_file | |
15 | |
16 from numpy.distutils import log | |
17 from numpy.distutils.exec_command import exec_command | |
18 from numpy.distutils.system_info import combine_paths | |
19 from numpy.distutils.misc_util import filter_sources, has_f_sources, \ | |
20 has_cxx_sources, get_ext_source_files, \ | |
21 get_numpy_include_dirs, is_sequence, get_build_architecture, \ | |
22 msvc_version | |
23 from numpy.distutils.command.config_compiler import show_fortran_compilers | |
24 | |
25 try: | |
26 set | |
27 except NameError: | |
28 from sets import Set as set | |
29 | |
30 class build_ext (old_build_ext): | |
31 | |
32 description = "build C/C++/F extensions (compile/link to build directory)" | |
33 | |
34 user_options = old_build_ext.user_options + [ | |
35 ('fcompiler=', None, | |
36 "specify the Fortran compiler type"), | |
37 ] | |
38 | |
39 help_options = old_build_ext.help_options + [ | |
40 ('help-fcompiler', None, "list available Fortran compilers", | |
41 show_fortran_compilers), | |
42 ] | |
43 | |
44 def initialize_options(self): | |
45 old_build_ext.initialize_options(self) | |
46 self.fcompiler = None | |
47 | |
48 def finalize_options(self): | |
49 incl_dirs = self.include_dirs | |
50 old_build_ext.finalize_options(self) | |
51 if incl_dirs is not None: | |
52 self.include_dirs.extend(self.distribution.include_dirs or []) | |
53 | |
54 def run(self): | |
55 if not self.extensions: | |
56 return | |
57 | |
58 # Make sure that extension sources are complete. | |
59 self.run_command('build_src') | |
60 | |
61 if self.distribution.has_c_libraries(): | |
62 if self.inplace: | |
63 if self.distribution.have_run.get('build_clib'): | |
64 log.warn('build_clib already run, it is too late to ' \ | |
65 'ensure in-place build of build_clib') | |
66 build_clib = self.distribution.get_command_obj('build_clib') | |
67 else: | |
68 build_clib = self.distribution.get_command_obj('build_clib') | |
69 build_clib.inplace = 1 | |
70 build_clib.ensure_finalized() | |
71 build_clib.run() | |
72 self.distribution.have_run['build_clib'] = 1 | |
73 | |
74 else: | |
75 self.run_command('build_clib') | |
76 build_clib = self.get_finalized_command('build_clib') | |
77 self.library_dirs.append(build_clib.build_clib) | |
78 else: | |
79 build_clib = None | |
80 | |
81 # Not including C libraries to the list of | |
82 # extension libraries automatically to prevent | |
83 # bogus linking commands. Extensions must | |
84 # explicitly specify the C libraries that they use. | |
85 | |
86 from distutils.ccompiler import new_compiler | |
87 from numpy.distutils.fcompiler import new_fcompiler | |
88 | |
89 compiler_type = self.compiler | |
90 # Initialize C compiler: | |
91 self.compiler = new_compiler(compiler=compiler_type, | |
92 verbose=self.verbose, | |
93 dry_run=self.dry_run, | |
94 force=self.force) | |
95 self.compiler.customize(self.distribution) | |
96 self.compiler.customize_cmd(self) | |
97 self.compiler.show_customization() | |
98 | |
99 # Create mapping of libraries built by build_clib: | |
100 clibs = {} | |
101 if build_clib is not None: | |
102 for libname, build_info in build_clib.libraries or []: | |
103 if libname in clibs and clibs[libname] != build_info: | |
104 log.warn('library %r defined more than once,'\ | |
105 ' overwriting build_info\n%s... \nwith\n%s...' \ | |
106 % (libname, repr(clibs[libname])[:300], repr(build_info)[:300])) | |
107 clibs[libname] = build_info | |
108 # .. and distribution libraries: | |
109 for libname, build_info in self.distribution.libraries or []: | |
110 if libname in clibs: | |
111 # build_clib libraries have a precedence before distribution ones | |
112 continue | |
113 clibs[libname] = build_info | |
114 | |
115 # Determine if C++/Fortran 77/Fortran 90 compilers are needed. | |
116 # Update extension libraries, library_dirs, and macros. | |
117 all_languages = set() | |
118 for ext in self.extensions: | |
119 ext_languages = set() | |
120 c_libs = [] | |
121 c_lib_dirs = [] | |
122 macros = [] | |
123 for libname in ext.libraries: | |
124 if libname in clibs: | |
125 binfo = clibs[libname] | |
126 c_libs += binfo.get('libraries', []) | |
127 c_lib_dirs += binfo.get('library_dirs', []) | |
128 for m in binfo.get('macros', []): | |
129 if m not in macros: | |
130 macros.append(m) | |
131 | |
132 for l in clibs.get(libname, {}).get('source_languages', []): | |
133 ext_languages.add(l) | |
134 if c_libs: | |
135 new_c_libs = ext.libraries + c_libs | |
136 log.info('updating extension %r libraries from %r to %r' | |
137 % (ext.name, ext.libraries, new_c_libs)) | |
138 ext.libraries = new_c_libs | |
139 ext.library_dirs = ext.library_dirs + c_lib_dirs | |
140 if macros: | |
141 log.info('extending extension %r defined_macros with %r' | |
142 % (ext.name, macros)) | |
143 ext.define_macros = ext.define_macros + macros | |
144 | |
145 # determine extension languages | |
146 if has_f_sources(ext.sources): | |
147 ext_languages.add('f77') | |
148 if has_cxx_sources(ext.sources): | |
149 ext_languages.add('c++') | |
150 l = ext.language or self.compiler.detect_language(ext.sources) | |
151 if l: | |
152 ext_languages.add(l) | |
153 # reset language attribute for choosing proper linker | |
154 if 'c++' in ext_languages: | |
155 ext_language = 'c++' | |
156 elif 'f90' in ext_languages: | |
157 ext_language = 'f90' | |
158 elif 'f77' in ext_languages: | |
159 ext_language = 'f77' | |
160 else: | |
161 ext_language = 'c' # default | |
162 if l and l != ext_language and ext.language: | |
163 log.warn('resetting extension %r language from %r to %r.' % | |
164 (ext.name, l, ext_language)) | |
165 ext.language = ext_language | |
166 # global language | |
167 all_languages.update(ext_languages) | |
168 | |
169 need_f90_compiler = 'f90' in all_languages | |
170 need_f77_compiler = 'f77' in all_languages | |
171 need_cxx_compiler = 'c++' in all_languages | |
172 | |
173 # Initialize C++ compiler: | |
174 if need_cxx_compiler: | |
175 self._cxx_compiler = new_compiler(compiler=compiler_type, | |
176 verbose=self.verbose, | |
177 dry_run=self.dry_run, | |
178 force=self.force) | |
179 compiler = self._cxx_compiler | |
180 compiler.customize(self.distribution, need_cxx=need_cxx_compiler) | |
181 compiler.customize_cmd(self) | |
182 compiler.show_customization() | |
183 self._cxx_compiler = compiler.cxx_compiler() | |
184 else: | |
185 self._cxx_compiler = None | |
186 | |
187 # Initialize Fortran 77 compiler: | |
188 if need_f77_compiler: | |
189 ctype = self.fcompiler | |
190 self._f77_compiler = new_fcompiler(compiler=self.fcompiler, | |
191 verbose=self.verbose, | |
192 dry_run=self.dry_run, | |
193 force=self.force, | |
194 requiref90=False, | |
195 c_compiler=self.compiler) | |
196 fcompiler = self._f77_compiler | |
197 if fcompiler: | |
198 ctype = fcompiler.compiler_type | |
199 fcompiler.customize(self.distribution) | |
200 if fcompiler and fcompiler.get_version(): | |
201 fcompiler.customize_cmd(self) | |
202 fcompiler.show_customization() | |
203 else: | |
204 self.warn('f77_compiler=%s is not available.' % | |
205 (ctype)) | |
206 self._f77_compiler = None | |
207 else: | |
208 self._f77_compiler = None | |
209 | |
210 # Initialize Fortran 90 compiler: | |
211 if need_f90_compiler: | |
212 ctype = self.fcompiler | |
213 self._f90_compiler = new_fcompiler(compiler=self.fcompiler, | |
214 verbose=self.verbose, | |
215 dry_run=self.dry_run, | |
216 force=self.force, | |
217 requiref90=True, | |
218 c_compiler = self.compiler) | |
219 fcompiler = self._f90_compiler | |
220 if fcompiler: | |
221 ctype = fcompiler.compiler_type | |
222 fcompiler.customize(self.distribution) | |
223 if fcompiler and fcompiler.get_version(): | |
224 fcompiler.customize_cmd(self) | |
225 fcompiler.show_customization() | |
226 else: | |
227 self.warn('f90_compiler=%s is not available.' % | |
228 (ctype)) | |
229 self._f90_compiler = None | |
230 else: | |
231 self._f90_compiler = None | |
232 | |
233 # Build extensions | |
234 self.build_extensions() | |
235 | |
236 | |
237 def swig_sources(self, sources): | |
238 # Do nothing. Swig sources have beed handled in build_src command. | |
239 return sources | |
240 | |
241 def build_extension(self, ext): | |
242 sources = ext.sources | |
243 if sources is None or not is_sequence(sources): | |
244 raise DistutilsSetupError( | |
245 ("in 'ext_modules' option (extension '%s'), " + | |
246 "'sources' must be present and must be " + | |
247 "a list of source filenames") % ext.name) | |
248 sources = list(sources) | |
249 | |
250 if not sources: | |
251 return | |
252 | |
253 fullname = self.get_ext_fullname(ext.name) | |
254 if self.inplace: | |
255 modpath = fullname.split('.') | |
256 package = '.'.join(modpath[0:-1]) | |
257 base = modpath[-1] | |
258 build_py = self.get_finalized_command('build_py') | |
259 package_dir = build_py.get_package_dir(package) | |
260 ext_filename = os.path.join(package_dir, | |
261 self.get_ext_filename(base)) | |
262 else: | |
263 ext_filename = os.path.join(self.build_lib, | |
264 self.get_ext_filename(fullname)) | |
265 depends = sources + ext.depends | |
266 | |
267 if not (self.force or newer_group(depends, ext_filename, 'newer')): | |
268 log.debug("skipping '%s' extension (up-to-date)", ext.name) | |
269 return | |
270 else: | |
271 log.info("building '%s' extension", ext.name) | |
272 | |
273 extra_args = ext.extra_compile_args or [] | |
274 macros = ext.define_macros[:] | |
275 for undef in ext.undef_macros: | |
276 macros.append((undef,)) | |
277 | |
278 c_sources, cxx_sources, f_sources, fmodule_sources = \ | |
279 filter_sources(ext.sources) | |
280 | |
281 | |
282 | |
283 if self.compiler.compiler_type=='msvc': | |
284 if cxx_sources: | |
285 # Needed to compile kiva.agg._agg extension. | |
286 extra_args.append('/Zm1000') | |
287 # this hack works around the msvc compiler attributes | |
288 # problem, msvc uses its own convention :( | |
289 c_sources += cxx_sources | |
290 cxx_sources = [] | |
291 | |
292 # Set Fortran/C++ compilers for compilation and linking. | |
293 if ext.language=='f90': | |
294 fcompiler = self._f90_compiler | |
295 elif ext.language=='f77': | |
296 fcompiler = self._f77_compiler | |
297 else: # in case ext.language is c++, for instance | |
298 fcompiler = self._f90_compiler or self._f77_compiler | |
299 if fcompiler is not None: | |
300 fcompiler.extra_f77_compile_args = (ext.extra_f77_compile_args or []) if hasattr(ext, 'extra_f77_compile_args') else [] | |
301 fcompiler.extra_f90_compile_args = (ext.extra_f90_compile_args or []) if hasattr(ext, 'extra_f90_compile_args') else [] | |
302 cxx_compiler = self._cxx_compiler | |
303 | |
304 # check for the availability of required compilers | |
305 if cxx_sources and cxx_compiler is None: | |
306 raise DistutilsError("extension %r has C++ sources" \ | |
307 "but no C++ compiler found" % (ext.name)) | |
308 if (f_sources or fmodule_sources) and fcompiler is None: | |
309 raise DistutilsError("extension %r has Fortran sources " \ | |
310 "but no Fortran compiler found" % (ext.name)) | |
311 if ext.language in ['f77', 'f90'] and fcompiler is None: | |
312 self.warn("extension %r has Fortran libraries " \ | |
313 "but no Fortran linker found, using default linker" % (ext.name)) | |
314 if ext.language=='c++' and cxx_compiler is None: | |
315 self.warn("extension %r has C++ libraries " \ | |
316 "but no C++ linker found, using default linker" % (ext.name)) | |
317 | |
318 kws = {'depends':ext.depends} | |
319 output_dir = self.build_temp | |
320 | |
321 include_dirs = ext.include_dirs + get_numpy_include_dirs() | |
322 | |
323 c_objects = [] | |
324 if c_sources: | |
325 log.info("compiling C sources") | |
326 c_objects = self.compiler.compile(c_sources, | |
327 output_dir=output_dir, | |
328 macros=macros, | |
329 include_dirs=include_dirs, | |
330 debug=self.debug, | |
331 extra_postargs=extra_args, | |
332 **kws) | |
333 | |
334 if cxx_sources: | |
335 log.info("compiling C++ sources") | |
336 c_objects += cxx_compiler.compile(cxx_sources, | |
337 output_dir=output_dir, | |
338 macros=macros, | |
339 include_dirs=include_dirs, | |
340 debug=self.debug, | |
341 extra_postargs=extra_args, | |
342 **kws) | |
343 | |
344 extra_postargs = [] | |
345 f_objects = [] | |
346 if fmodule_sources: | |
347 log.info("compiling Fortran 90 module sources") | |
348 module_dirs = ext.module_dirs[:] | |
349 module_build_dir = os.path.join( | |
350 self.build_temp, os.path.dirname( | |
351 self.get_ext_filename(fullname))) | |
352 | |
353 self.mkpath(module_build_dir) | |
354 if fcompiler.module_dir_switch is None: | |
355 existing_modules = glob('*.mod') | |
356 extra_postargs += fcompiler.module_options( | |
357 module_dirs, module_build_dir) | |
358 f_objects += fcompiler.compile(fmodule_sources, | |
359 output_dir=self.build_temp, | |
360 macros=macros, | |
361 include_dirs=include_dirs, | |
362 debug=self.debug, | |
363 extra_postargs=extra_postargs, | |
364 depends=ext.depends) | |
365 | |
366 if fcompiler.module_dir_switch is None: | |
367 for f in glob('*.mod'): | |
368 if f in existing_modules: | |
369 continue | |
370 t = os.path.join(module_build_dir, f) | |
371 if os.path.abspath(f)==os.path.abspath(t): | |
372 continue | |
373 if os.path.isfile(t): | |
374 os.remove(t) | |
375 try: | |
376 self.move_file(f, module_build_dir) | |
377 except DistutilsFileError: | |
378 log.warn('failed to move %r to %r' % | |
379 (f, module_build_dir)) | |
380 if f_sources: | |
381 log.info("compiling Fortran sources") | |
382 f_objects += fcompiler.compile(f_sources, | |
383 output_dir=self.build_temp, | |
384 macros=macros, | |
385 include_dirs=include_dirs, | |
386 debug=self.debug, | |
387 extra_postargs=extra_postargs, | |
388 depends=ext.depends) | |
389 | |
390 objects = c_objects + f_objects | |
391 | |
392 if ext.extra_objects: | |
393 objects.extend(ext.extra_objects) | |
394 extra_args = ext.extra_link_args or [] | |
395 libraries = self.get_libraries(ext)[:] | |
396 library_dirs = ext.library_dirs[:] | |
397 | |
398 linker = self.compiler.link_shared_object | |
399 # Always use system linker when using MSVC compiler. | |
400 if self.compiler.compiler_type=='msvc': | |
401 # expand libraries with fcompiler libraries as we are | |
402 # not using fcompiler linker | |
403 self._libs_with_msvc_and_fortran(fcompiler, libraries, library_dirs) | |
404 | |
405 elif ext.language in ['f77', 'f90'] and fcompiler is not None: | |
406 linker = fcompiler.link_shared_object | |
407 if ext.language=='c++' and cxx_compiler is not None: | |
408 linker = cxx_compiler.link_shared_object | |
409 | |
410 if sys.version[:3]>='2.3': | |
411 kws = {'target_lang':ext.language} | |
412 else: | |
413 kws = {} | |
414 | |
415 linker(objects, ext_filename, | |
416 libraries=libraries, | |
417 library_dirs=library_dirs, | |
418 runtime_library_dirs=ext.runtime_library_dirs, | |
419 extra_postargs=extra_args, | |
420 export_symbols=self.get_export_symbols(ext), | |
421 debug=self.debug, | |
422 build_temp=self.build_temp,**kws) | |
423 | |
424 def _add_dummy_mingwex_sym(self, c_sources): | |
425 build_src = self.get_finalized_command("build_src").build_src | |
426 build_clib = self.get_finalized_command("build_clib").build_clib | |
427 objects = self.compiler.compile([os.path.join(build_src, | |
428 "gfortran_vs2003_hack.c")], | |
429 output_dir=self.build_temp) | |
430 self.compiler.create_static_lib(objects, "_gfortran_workaround", output_dir=build_clib, debug=self.debug) | |
431 | |
432 def _libs_with_msvc_and_fortran(self, fcompiler, c_libraries, | |
433 c_library_dirs): | |
434 if fcompiler is None: return | |
435 | |
436 for libname in c_libraries: | |
437 if libname.startswith('msvc'): continue | |
438 fileexists = False | |
439 for libdir in c_library_dirs or []: | |
440 libfile = os.path.join(libdir, '%s.lib' % (libname)) | |
441 if os.path.isfile(libfile): | |
442 fileexists = True | |
443 break | |
444 if fileexists: continue | |
445 # make g77-compiled static libs available to MSVC | |
446 fileexists = False | |
447 for libdir in c_library_dirs: | |
448 libfile = os.path.join(libdir, 'lib%s.a' % (libname)) | |
449 if os.path.isfile(libfile): | |
450 # copy libname.a file to name.lib so that MSVC linker | |
451 # can find it | |
452 libfile2 = os.path.join(self.build_temp, libname + '.lib') | |
453 copy_file(libfile, libfile2) | |
454 if self.build_temp not in c_library_dirs: | |
455 c_library_dirs.append(self.build_temp) | |
456 fileexists = True | |
457 break | |
458 if fileexists: continue | |
459 log.warn('could not find library %r in directories %s' | |
460 % (libname, c_library_dirs)) | |
461 | |
462 # Always use system linker when using MSVC compiler. | |
463 f_lib_dirs = [] | |
464 for dir in fcompiler.library_dirs: | |
465 # correct path when compiling in Cygwin but with normal Win | |
466 # Python | |
467 if dir.startswith('/usr/lib'): | |
468 s, o = exec_command(['cygpath', '-w', dir], use_tee=False) | |
469 if not s: | |
470 dir = o | |
471 f_lib_dirs.append(dir) | |
472 c_library_dirs.extend(f_lib_dirs) | |
473 | |
474 # make g77-compiled static libs available to MSVC | |
475 for lib in fcompiler.libraries: | |
476 if not lib.startswith('msvc'): | |
477 c_libraries.append(lib) | |
478 p = combine_paths(f_lib_dirs, 'lib' + lib + '.a') | |
479 if p: | |
480 dst_name = os.path.join(self.build_temp, lib + '.lib') | |
481 if not os.path.isfile(dst_name): | |
482 copy_file(p[0], dst_name) | |
483 if self.build_temp not in c_library_dirs: | |
484 c_library_dirs.append(self.build_temp) | |
485 | |
486 def get_source_files (self): | |
487 self.check_extensions_list(self.extensions) | |
488 filenames = [] | |
489 for ext in self.extensions: | |
490 filenames.extend(get_ext_source_files(ext)) | |
491 return filenames | |
492 | |
493 def get_outputs (self): | |
494 self.check_extensions_list(self.extensions) | |
495 | |
496 outputs = [] | |
497 for ext in self.extensions: | |
498 if not ext.sources: | |
499 continue | |
500 fullname = self.get_ext_fullname(ext.name) | |
501 outputs.append(os.path.join(self.build_lib, | |
502 self.get_ext_filename(fullname))) | |
503 return outputs |