Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/distutils/system_info.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 #!/bin/env python | |
2 """ | |
3 This file defines a set of system_info classes for getting | |
4 information about various resources (libraries, library directories, | |
5 include directories, etc.) in the system. Currently, the following | |
6 classes are available: | |
7 | |
8 atlas_info | |
9 atlas_threads_info | |
10 atlas_blas_info | |
11 atlas_blas_threads_info | |
12 lapack_atlas_info | |
13 blas_info | |
14 lapack_info | |
15 openblas_info | |
16 blas_opt_info # usage recommended | |
17 lapack_opt_info # usage recommended | |
18 fftw_info,dfftw_info,sfftw_info | |
19 fftw_threads_info,dfftw_threads_info,sfftw_threads_info | |
20 djbfft_info | |
21 x11_info | |
22 lapack_src_info | |
23 blas_src_info | |
24 numpy_info | |
25 numarray_info | |
26 numpy_info | |
27 boost_python_info | |
28 agg2_info | |
29 wx_info | |
30 gdk_pixbuf_xlib_2_info | |
31 gdk_pixbuf_2_info | |
32 gdk_x11_2_info | |
33 gtkp_x11_2_info | |
34 gtkp_2_info | |
35 xft_info | |
36 freetype2_info | |
37 umfpack_info | |
38 | |
39 Usage: | |
40 info_dict = get_info(<name>) | |
41 where <name> is a string 'atlas','x11','fftw','lapack','blas', | |
42 'lapack_src', 'blas_src', etc. For a complete list of allowed names, | |
43 see the definition of get_info() function below. | |
44 | |
45 Returned info_dict is a dictionary which is compatible with | |
46 distutils.setup keyword arguments. If info_dict == {}, then the | |
47 asked resource is not available (system_info could not find it). | |
48 | |
49 Several *_info classes specify an environment variable to specify | |
50 the locations of software. When setting the corresponding environment | |
51 variable to 'None' then the software will be ignored, even when it | |
52 is available in system. | |
53 | |
54 Global parameters: | |
55 system_info.search_static_first - search static libraries (.a) | |
56 in precedence to shared ones (.so, .sl) if enabled. | |
57 system_info.verbosity - output the results to stdout if enabled. | |
58 | |
59 The file 'site.cfg' is looked for in | |
60 | |
61 1) Directory of main setup.py file being run. | |
62 2) Home directory of user running the setup.py file as ~/.numpy-site.cfg | |
63 3) System wide directory (location of this file...) | |
64 | |
65 The first one found is used to get system configuration options The | |
66 format is that used by ConfigParser (i.e., Windows .INI style). The | |
67 section ALL has options that are the default for each section. The | |
68 available sections are fftw, atlas, and x11. Appropiate defaults are | |
69 used if nothing is specified. | |
70 | |
71 The order of finding the locations of resources is the following: | |
72 1. environment variable | |
73 2. section in site.cfg | |
74 3. ALL section in site.cfg | |
75 Only the first complete match is returned. | |
76 | |
77 Example: | |
78 ---------- | |
79 [ALL] | |
80 library_dirs = /usr/lib:/usr/local/lib:/opt/lib | |
81 include_dirs = /usr/include:/usr/local/include:/opt/include | |
82 src_dirs = /usr/local/src:/opt/src | |
83 # search static libraries (.a) in preference to shared ones (.so) | |
84 search_static_first = 0 | |
85 | |
86 [fftw] | |
87 fftw_libs = rfftw, fftw | |
88 fftw_opt_libs = rfftw_threaded, fftw_threaded | |
89 # if the above aren't found, look for {s,d}fftw_libs and {s,d}fftw_opt_libs | |
90 | |
91 [atlas] | |
92 library_dirs = /usr/lib/3dnow:/usr/lib/3dnow/atlas | |
93 # for overriding the names of the atlas libraries | |
94 atlas_libs = lapack, f77blas, cblas, atlas | |
95 | |
96 [x11] | |
97 library_dirs = /usr/X11R6/lib | |
98 include_dirs = /usr/X11R6/include | |
99 ---------- | |
100 | |
101 Authors: | |
102 Pearu Peterson <pearu@cens.ioc.ee>, February 2002 | |
103 David M. Cooke <cookedm@physics.mcmaster.ca>, April 2002 | |
104 | |
105 Copyright 2002 Pearu Peterson all rights reserved, | |
106 Pearu Peterson <pearu@cens.ioc.ee> | |
107 Permission to use, modify, and distribute this software is given under the | |
108 terms of the NumPy (BSD style) license. See LICENSE.txt that came with | |
109 this distribution for specifics. | |
110 | |
111 NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. | |
112 | |
113 """ | |
114 from __future__ import division, absolute_import, print_function | |
115 | |
116 import sys | |
117 import os | |
118 import re | |
119 import copy | |
120 import warnings | |
121 from glob import glob | |
122 from functools import reduce | |
123 if sys.version_info[0] < 3: | |
124 from ConfigParser import NoOptionError, ConfigParser | |
125 else: | |
126 from configparser import NoOptionError, ConfigParser | |
127 | |
128 from distutils.errors import DistutilsError | |
129 from distutils.dist import Distribution | |
130 import distutils.sysconfig | |
131 from distutils import log | |
132 from distutils.util import get_platform | |
133 | |
134 from numpy.distutils.exec_command import \ | |
135 find_executable, exec_command, get_pythonexe | |
136 from numpy.distutils.misc_util import is_sequence, is_string, \ | |
137 get_shared_lib_extension | |
138 from numpy.distutils.command.config import config as cmd_config | |
139 from numpy.distutils.compat import get_exception | |
140 import distutils.ccompiler | |
141 import tempfile | |
142 import shutil | |
143 | |
144 | |
145 # Determine number of bits | |
146 import platform | |
147 _bits = {'32bit': 32, '64bit': 64} | |
148 platform_bits = _bits[platform.architecture()[0]] | |
149 | |
150 | |
151 def libpaths(paths, bits): | |
152 """Return a list of library paths valid on 32 or 64 bit systems. | |
153 | |
154 Inputs: | |
155 paths : sequence | |
156 A sequence of strings (typically paths) | |
157 bits : int | |
158 An integer, the only valid values are 32 or 64. A ValueError exception | |
159 is raised otherwise. | |
160 | |
161 Examples: | |
162 | |
163 Consider a list of directories | |
164 >>> paths = ['/usr/X11R6/lib','/usr/X11/lib','/usr/lib'] | |
165 | |
166 For a 32-bit platform, this is already valid: | |
167 >>> np.distutils.system_info.libpaths(paths,32) | |
168 ['/usr/X11R6/lib', '/usr/X11/lib', '/usr/lib'] | |
169 | |
170 On 64 bits, we prepend the '64' postfix | |
171 >>> np.distutils.system_info.libpaths(paths,64) | |
172 ['/usr/X11R6/lib64', '/usr/X11R6/lib', '/usr/X11/lib64', '/usr/X11/lib', | |
173 '/usr/lib64', '/usr/lib'] | |
174 """ | |
175 if bits not in (32, 64): | |
176 raise ValueError("Invalid bit size in libpaths: 32 or 64 only") | |
177 | |
178 # Handle 32bit case | |
179 if bits == 32: | |
180 return paths | |
181 | |
182 # Handle 64bit case | |
183 out = [] | |
184 for p in paths: | |
185 out.extend([p + '64', p]) | |
186 | |
187 return out | |
188 | |
189 | |
190 if sys.platform == 'win32': | |
191 default_lib_dirs = ['C:\\', | |
192 os.path.join(distutils.sysconfig.EXEC_PREFIX, | |
193 'libs')] | |
194 default_include_dirs = [] | |
195 default_src_dirs = ['.'] | |
196 default_x11_lib_dirs = [] | |
197 default_x11_include_dirs = [] | |
198 else: | |
199 default_lib_dirs = libpaths(['/usr/local/lib', '/opt/lib', '/usr/lib', | |
200 '/opt/local/lib', '/sw/lib'], platform_bits) | |
201 default_include_dirs = ['/usr/local/include', | |
202 '/opt/include', '/usr/include', | |
203 # path of umfpack under macports | |
204 '/opt/local/include/ufsparse', | |
205 '/opt/local/include', '/sw/include', | |
206 '/usr/include/suitesparse'] | |
207 default_src_dirs = ['.', '/usr/local/src', '/opt/src', '/sw/src'] | |
208 | |
209 default_x11_lib_dirs = libpaths(['/usr/X11R6/lib', '/usr/X11/lib', | |
210 '/usr/lib'], platform_bits) | |
211 default_x11_include_dirs = ['/usr/X11R6/include', '/usr/X11/include', | |
212 '/usr/include'] | |
213 | |
214 if os.path.exists('/usr/lib/X11'): | |
215 globbed_x11_dir = glob('/usr/lib/*/libX11.so') | |
216 if globbed_x11_dir: | |
217 x11_so_dir = os.path.split(globbed_x11_dir[0])[0] | |
218 default_x11_lib_dirs.extend([x11_so_dir, '/usr/lib/X11']) | |
219 default_x11_include_dirs.extend(['/usr/lib/X11/include', | |
220 '/usr/include/X11']) | |
221 | |
222 import subprocess as sp | |
223 tmp = None | |
224 try: | |
225 # Explicitly open/close file to avoid ResourceWarning when | |
226 # tests are run in debug mode Python 3. | |
227 tmp = open(os.devnull, 'w') | |
228 p = sp.Popen(["gcc", "-print-multiarch"], stdout=sp.PIPE, | |
229 stderr=tmp) | |
230 except (OSError, DistutilsError): | |
231 # OSError if gcc is not installed, or SandboxViolation (DistutilsError | |
232 # subclass) if an old setuptools bug is triggered (see gh-3160). | |
233 pass | |
234 else: | |
235 triplet = str(p.communicate()[0].decode().strip()) | |
236 if p.returncode == 0: | |
237 # gcc supports the "-print-multiarch" option | |
238 default_x11_lib_dirs += [os.path.join("/usr/lib/", triplet)] | |
239 default_lib_dirs += [os.path.join("/usr/lib/", triplet)] | |
240 finally: | |
241 if tmp is not None: | |
242 tmp.close() | |
243 | |
244 if os.path.join(sys.prefix, 'lib') not in default_lib_dirs: | |
245 default_lib_dirs.insert(0, os.path.join(sys.prefix, 'lib')) | |
246 default_include_dirs.append(os.path.join(sys.prefix, 'include')) | |
247 default_src_dirs.append(os.path.join(sys.prefix, 'src')) | |
248 | |
249 default_lib_dirs = [_m for _m in default_lib_dirs if os.path.isdir(_m)] | |
250 default_include_dirs = [_m for _m in default_include_dirs if os.path.isdir(_m)] | |
251 default_src_dirs = [_m for _m in default_src_dirs if os.path.isdir(_m)] | |
252 | |
253 so_ext = get_shared_lib_extension() | |
254 | |
255 | |
256 def get_standard_file(fname): | |
257 """Returns a list of files named 'fname' from | |
258 1) System-wide directory (directory-location of this module) | |
259 2) Users HOME directory (os.environ['HOME']) | |
260 3) Local directory | |
261 """ | |
262 # System-wide file | |
263 filenames = [] | |
264 try: | |
265 f = __file__ | |
266 except NameError: | |
267 f = sys.argv[0] | |
268 else: | |
269 sysfile = os.path.join(os.path.split(os.path.abspath(f))[0], | |
270 fname) | |
271 if os.path.isfile(sysfile): | |
272 filenames.append(sysfile) | |
273 | |
274 # Home directory | |
275 # And look for the user config file | |
276 try: | |
277 f = os.path.expanduser('~') | |
278 except KeyError: | |
279 pass | |
280 else: | |
281 user_file = os.path.join(f, fname) | |
282 if os.path.isfile(user_file): | |
283 filenames.append(user_file) | |
284 | |
285 # Local file | |
286 if os.path.isfile(fname): | |
287 filenames.append(os.path.abspath(fname)) | |
288 | |
289 return filenames | |
290 | |
291 | |
292 def get_info(name, notfound_action=0): | |
293 """ | |
294 notfound_action: | |
295 0 - do nothing | |
296 1 - display warning message | |
297 2 - raise error | |
298 """ | |
299 cl = {'atlas': atlas_info, # use lapack_opt or blas_opt instead | |
300 'atlas_threads': atlas_threads_info, # ditto | |
301 'atlas_blas': atlas_blas_info, | |
302 'atlas_blas_threads': atlas_blas_threads_info, | |
303 'lapack_atlas': lapack_atlas_info, # use lapack_opt instead | |
304 'lapack_atlas_threads': lapack_atlas_threads_info, # ditto | |
305 'mkl': mkl_info, | |
306 # openblas which may or may not have embedded lapack | |
307 'openblas': openblas_info, # use blas_opt instead | |
308 # openblas with embedded lapack | |
309 'openblas_lapack': openblas_lapack_info, # use blas_opt instead | |
310 'lapack_mkl': lapack_mkl_info, # use lapack_opt instead | |
311 'blas_mkl': blas_mkl_info, # use blas_opt instead | |
312 'x11': x11_info, | |
313 'fft_opt': fft_opt_info, | |
314 'fftw': fftw_info, | |
315 'fftw2': fftw2_info, | |
316 'fftw3': fftw3_info, | |
317 'dfftw': dfftw_info, | |
318 'sfftw': sfftw_info, | |
319 'fftw_threads': fftw_threads_info, | |
320 'dfftw_threads': dfftw_threads_info, | |
321 'sfftw_threads': sfftw_threads_info, | |
322 'djbfft': djbfft_info, | |
323 'blas': blas_info, # use blas_opt instead | |
324 'lapack': lapack_info, # use lapack_opt instead | |
325 'lapack_src': lapack_src_info, | |
326 'blas_src': blas_src_info, | |
327 'numpy': numpy_info, | |
328 'f2py': f2py_info, | |
329 'Numeric': Numeric_info, | |
330 'numeric': Numeric_info, | |
331 'numarray': numarray_info, | |
332 'numerix': numerix_info, | |
333 'lapack_opt': lapack_opt_info, | |
334 'blas_opt': blas_opt_info, | |
335 'boost_python': boost_python_info, | |
336 'agg2': agg2_info, | |
337 'wx': wx_info, | |
338 'gdk_pixbuf_xlib_2': gdk_pixbuf_xlib_2_info, | |
339 'gdk-pixbuf-xlib-2.0': gdk_pixbuf_xlib_2_info, | |
340 'gdk_pixbuf_2': gdk_pixbuf_2_info, | |
341 'gdk-pixbuf-2.0': gdk_pixbuf_2_info, | |
342 'gdk': gdk_info, | |
343 'gdk_2': gdk_2_info, | |
344 'gdk-2.0': gdk_2_info, | |
345 'gdk_x11_2': gdk_x11_2_info, | |
346 'gdk-x11-2.0': gdk_x11_2_info, | |
347 'gtkp_x11_2': gtkp_x11_2_info, | |
348 'gtk+-x11-2.0': gtkp_x11_2_info, | |
349 'gtkp_2': gtkp_2_info, | |
350 'gtk+-2.0': gtkp_2_info, | |
351 'xft': xft_info, | |
352 'freetype2': freetype2_info, | |
353 'umfpack': umfpack_info, | |
354 'amd': amd_info, | |
355 }.get(name.lower(), system_info) | |
356 return cl().get_info(notfound_action) | |
357 | |
358 | |
359 class NotFoundError(DistutilsError): | |
360 """Some third-party program or library is not found.""" | |
361 | |
362 | |
363 class AtlasNotFoundError(NotFoundError): | |
364 """ | |
365 Atlas (http://math-atlas.sourceforge.net/) libraries not found. | |
366 Directories to search for the libraries can be specified in the | |
367 numpy/distutils/site.cfg file (section [atlas]) or by setting | |
368 the ATLAS environment variable.""" | |
369 | |
370 | |
371 class LapackNotFoundError(NotFoundError): | |
372 """ | |
373 Lapack (http://www.netlib.org/lapack/) libraries not found. | |
374 Directories to search for the libraries can be specified in the | |
375 numpy/distutils/site.cfg file (section [lapack]) or by setting | |
376 the LAPACK environment variable.""" | |
377 | |
378 | |
379 class LapackSrcNotFoundError(LapackNotFoundError): | |
380 """ | |
381 Lapack (http://www.netlib.org/lapack/) sources not found. | |
382 Directories to search for the sources can be specified in the | |
383 numpy/distutils/site.cfg file (section [lapack_src]) or by setting | |
384 the LAPACK_SRC environment variable.""" | |
385 | |
386 | |
387 class BlasNotFoundError(NotFoundError): | |
388 """ | |
389 Blas (http://www.netlib.org/blas/) libraries not found. | |
390 Directories to search for the libraries can be specified in the | |
391 numpy/distutils/site.cfg file (section [blas]) or by setting | |
392 the BLAS environment variable.""" | |
393 | |
394 | |
395 class BlasSrcNotFoundError(BlasNotFoundError): | |
396 """ | |
397 Blas (http://www.netlib.org/blas/) sources not found. | |
398 Directories to search for the sources can be specified in the | |
399 numpy/distutils/site.cfg file (section [blas_src]) or by setting | |
400 the BLAS_SRC environment variable.""" | |
401 | |
402 | |
403 class FFTWNotFoundError(NotFoundError): | |
404 """ | |
405 FFTW (http://www.fftw.org/) libraries not found. | |
406 Directories to search for the libraries can be specified in the | |
407 numpy/distutils/site.cfg file (section [fftw]) or by setting | |
408 the FFTW environment variable.""" | |
409 | |
410 | |
411 class DJBFFTNotFoundError(NotFoundError): | |
412 """ | |
413 DJBFFT (http://cr.yp.to/djbfft.html) libraries not found. | |
414 Directories to search for the libraries can be specified in the | |
415 numpy/distutils/site.cfg file (section [djbfft]) or by setting | |
416 the DJBFFT environment variable.""" | |
417 | |
418 | |
419 class NumericNotFoundError(NotFoundError): | |
420 """ | |
421 Numeric (http://www.numpy.org/) module not found. | |
422 Get it from above location, install it, and retry setup.py.""" | |
423 | |
424 | |
425 class X11NotFoundError(NotFoundError): | |
426 """X11 libraries not found.""" | |
427 | |
428 | |
429 class UmfpackNotFoundError(NotFoundError): | |
430 """ | |
431 UMFPACK sparse solver (http://www.cise.ufl.edu/research/sparse/umfpack/) | |
432 not found. Directories to search for the libraries can be specified in the | |
433 numpy/distutils/site.cfg file (section [umfpack]) or by setting | |
434 the UMFPACK environment variable.""" | |
435 | |
436 | |
437 class system_info: | |
438 | |
439 """ get_info() is the only public method. Don't use others. | |
440 """ | |
441 section = 'ALL' | |
442 dir_env_var = None | |
443 search_static_first = 0 # XXX: disabled by default, may disappear in | |
444 # future unless it is proved to be useful. | |
445 verbosity = 1 | |
446 saved_results = {} | |
447 | |
448 notfounderror = NotFoundError | |
449 | |
450 def __init__(self, | |
451 default_lib_dirs=default_lib_dirs, | |
452 default_include_dirs=default_include_dirs, | |
453 verbosity=1, | |
454 ): | |
455 self.__class__.info = {} | |
456 self.local_prefixes = [] | |
457 defaults = {} | |
458 defaults['library_dirs'] = os.pathsep.join(default_lib_dirs) | |
459 defaults['include_dirs'] = os.pathsep.join(default_include_dirs) | |
460 defaults['src_dirs'] = os.pathsep.join(default_src_dirs) | |
461 defaults['search_static_first'] = str(self.search_static_first) | |
462 self.cp = ConfigParser(defaults) | |
463 self.files = [] | |
464 self.files.extend(get_standard_file('.numpy-site.cfg')) | |
465 self.files.extend(get_standard_file('site.cfg')) | |
466 self.parse_config_files() | |
467 if self.section is not None: | |
468 self.search_static_first = self.cp.getboolean( | |
469 self.section, 'search_static_first') | |
470 assert isinstance(self.search_static_first, int) | |
471 | |
472 def parse_config_files(self): | |
473 self.cp.read(self.files) | |
474 if not self.cp.has_section(self.section): | |
475 if self.section is not None: | |
476 self.cp.add_section(self.section) | |
477 | |
478 def calc_libraries_info(self): | |
479 libs = self.get_libraries() | |
480 dirs = self.get_lib_dirs() | |
481 info = {} | |
482 for lib in libs: | |
483 i = self.check_libs(dirs, [lib]) | |
484 if i is not None: | |
485 dict_append(info, **i) | |
486 else: | |
487 log.info('Library %s was not found. Ignoring' % (lib)) | |
488 return info | |
489 | |
490 def set_info(self, **info): | |
491 if info: | |
492 lib_info = self.calc_libraries_info() | |
493 dict_append(info, **lib_info) | |
494 self.saved_results[self.__class__.__name__] = info | |
495 | |
496 def has_info(self): | |
497 return self.__class__.__name__ in self.saved_results | |
498 | |
499 def get_info(self, notfound_action=0): | |
500 """ Return a dictonary with items that are compatible | |
501 with numpy.distutils.setup keyword arguments. | |
502 """ | |
503 flag = 0 | |
504 if not self.has_info(): | |
505 flag = 1 | |
506 log.info(self.__class__.__name__ + ':') | |
507 if hasattr(self, 'calc_info'): | |
508 self.calc_info() | |
509 if notfound_action: | |
510 if not self.has_info(): | |
511 if notfound_action == 1: | |
512 warnings.warn(self.notfounderror.__doc__) | |
513 elif notfound_action == 2: | |
514 raise self.notfounderror(self.notfounderror.__doc__) | |
515 else: | |
516 raise ValueError(repr(notfound_action)) | |
517 | |
518 if not self.has_info(): | |
519 log.info(' NOT AVAILABLE') | |
520 self.set_info() | |
521 else: | |
522 log.info(' FOUND:') | |
523 | |
524 res = self.saved_results.get(self.__class__.__name__) | |
525 if self.verbosity > 0 and flag: | |
526 for k, v in res.items(): | |
527 v = str(v) | |
528 if k in ['sources', 'libraries'] and len(v) > 270: | |
529 v = v[:120] + '...\n...\n...' + v[-120:] | |
530 log.info(' %s = %s', k, v) | |
531 log.info('') | |
532 | |
533 return copy.deepcopy(res) | |
534 | |
535 def get_paths(self, section, key): | |
536 dirs = self.cp.get(section, key).split(os.pathsep) | |
537 env_var = self.dir_env_var | |
538 if env_var: | |
539 if is_sequence(env_var): | |
540 e0 = env_var[-1] | |
541 for e in env_var: | |
542 if e in os.environ: | |
543 e0 = e | |
544 break | |
545 if not env_var[0] == e0: | |
546 log.info('Setting %s=%s' % (env_var[0], e0)) | |
547 env_var = e0 | |
548 if env_var and env_var in os.environ: | |
549 d = os.environ[env_var] | |
550 if d == 'None': | |
551 log.info('Disabled %s: %s', | |
552 self.__class__.__name__, '(%s is None)' | |
553 % (env_var,)) | |
554 return [] | |
555 if os.path.isfile(d): | |
556 dirs = [os.path.dirname(d)] + dirs | |
557 l = getattr(self, '_lib_names', []) | |
558 if len(l) == 1: | |
559 b = os.path.basename(d) | |
560 b = os.path.splitext(b)[0] | |
561 if b[:3] == 'lib': | |
562 log.info('Replacing _lib_names[0]==%r with %r' \ | |
563 % (self._lib_names[0], b[3:])) | |
564 self._lib_names[0] = b[3:] | |
565 else: | |
566 ds = d.split(os.pathsep) | |
567 ds2 = [] | |
568 for d in ds: | |
569 if os.path.isdir(d): | |
570 ds2.append(d) | |
571 for dd in ['include', 'lib']: | |
572 d1 = os.path.join(d, dd) | |
573 if os.path.isdir(d1): | |
574 ds2.append(d1) | |
575 dirs = ds2 + dirs | |
576 default_dirs = self.cp.get(self.section, key).split(os.pathsep) | |
577 dirs.extend(default_dirs) | |
578 ret = [] | |
579 for d in dirs: | |
580 if not os.path.isdir(d): | |
581 warnings.warn('Specified path %s is invalid.' % d) | |
582 continue | |
583 | |
584 if d not in ret: | |
585 ret.append(d) | |
586 | |
587 log.debug('( %s = %s )', key, ':'.join(ret)) | |
588 return ret | |
589 | |
590 def get_lib_dirs(self, key='library_dirs'): | |
591 return self.get_paths(self.section, key) | |
592 | |
593 def get_include_dirs(self, key='include_dirs'): | |
594 return self.get_paths(self.section, key) | |
595 | |
596 def get_src_dirs(self, key='src_dirs'): | |
597 return self.get_paths(self.section, key) | |
598 | |
599 def get_libs(self, key, default): | |
600 try: | |
601 libs = self.cp.get(self.section, key) | |
602 except NoOptionError: | |
603 if not default: | |
604 return [] | |
605 if is_string(default): | |
606 return [default] | |
607 return default | |
608 return [b for b in [a.strip() for a in libs.split(',')] if b] | |
609 | |
610 def get_libraries(self, key='libraries'): | |
611 return self.get_libs(key, '') | |
612 | |
613 def library_extensions(self): | |
614 static_exts = ['.a'] | |
615 if sys.platform == 'win32': | |
616 static_exts.append('.lib') # .lib is used by MSVC | |
617 if self.search_static_first: | |
618 exts = static_exts + [so_ext] | |
619 else: | |
620 exts = [so_ext] + static_exts | |
621 if sys.platform == 'cygwin': | |
622 exts.append('.dll.a') | |
623 if sys.platform == 'darwin': | |
624 exts.append('.dylib') | |
625 # Debian and Ubuntu added a g3f suffix to shared library to deal with | |
626 # g77 -> gfortran ABI transition | |
627 # XXX: disabled, it hides more problem than it solves. | |
628 #if sys.platform[:5] == 'linux': | |
629 # exts.append('.so.3gf') | |
630 return exts | |
631 | |
632 def check_libs(self, lib_dirs, libs, opt_libs=[]): | |
633 """If static or shared libraries are available then return | |
634 their info dictionary. | |
635 | |
636 Checks for all libraries as shared libraries first, then | |
637 static (or vice versa if self.search_static_first is True). | |
638 """ | |
639 exts = self.library_extensions() | |
640 info = None | |
641 for ext in exts: | |
642 info = self._check_libs(lib_dirs, libs, opt_libs, [ext]) | |
643 if info is not None: | |
644 break | |
645 if not info: | |
646 log.info(' libraries %s not found in %s', ','.join(libs), | |
647 lib_dirs) | |
648 return info | |
649 | |
650 def check_libs2(self, lib_dirs, libs, opt_libs=[]): | |
651 """If static or shared libraries are available then return | |
652 their info dictionary. | |
653 | |
654 Checks each library for shared or static. | |
655 """ | |
656 exts = self.library_extensions() | |
657 info = self._check_libs(lib_dirs, libs, opt_libs, exts) | |
658 if not info: | |
659 log.info(' libraries %s not found in %s', ','.join(libs), | |
660 lib_dirs) | |
661 return info | |
662 | |
663 def _lib_list(self, lib_dir, libs, exts): | |
664 assert is_string(lib_dir) | |
665 liblist = [] | |
666 # under windows first try without 'lib' prefix | |
667 if sys.platform == 'win32': | |
668 lib_prefixes = ['', 'lib'] | |
669 else: | |
670 lib_prefixes = ['lib'] | |
671 # for each library name, see if we can find a file for it. | |
672 for l in libs: | |
673 for ext in exts: | |
674 for prefix in lib_prefixes: | |
675 p = self.combine_paths(lib_dir, prefix + l + ext) | |
676 if p: | |
677 break | |
678 if p: | |
679 assert len(p) == 1 | |
680 # ??? splitext on p[0] would do this for cygwin | |
681 # doesn't seem correct | |
682 if ext == '.dll.a': | |
683 l += '.dll' | |
684 liblist.append(l) | |
685 break | |
686 return liblist | |
687 | |
688 def _check_libs(self, lib_dirs, libs, opt_libs, exts): | |
689 """Find mandatory and optional libs in expected paths. | |
690 | |
691 Missing optional libraries are silently forgotten. | |
692 """ | |
693 # First, try to find the mandatory libraries | |
694 if is_sequence(lib_dirs): | |
695 found_libs, found_dirs = [], [] | |
696 for dir_ in lib_dirs: | |
697 found_libs1 = self._lib_list(dir_, libs, exts) | |
698 # It's possible that we'll find the same library in multiple | |
699 # directories. It's also possible that we'll find some | |
700 # libraries on in directory, and some in another. So the | |
701 # obvious thing would be to use a set instead of a list, but I | |
702 # don't know if preserving order matters (does it?). | |
703 for found_lib in found_libs1: | |
704 if found_lib not in found_libs: | |
705 found_libs.append(found_lib) | |
706 if dir_ not in found_dirs: | |
707 found_dirs.append(dir_) | |
708 else: | |
709 found_libs = self._lib_list(lib_dirs, libs, exts) | |
710 found_dirs = [lib_dirs] | |
711 if len(found_libs) > 0 and len(found_libs) == len(libs): | |
712 info = {'libraries': found_libs, 'library_dirs': found_dirs} | |
713 # Now, check for optional libraries | |
714 if is_sequence(lib_dirs): | |
715 for dir_ in lib_dirs: | |
716 opt_found_libs = self._lib_list(dir_, opt_libs, exts) | |
717 if opt_found_libs: | |
718 if dir_ not in found_dirs: | |
719 found_dirs.extend(dir_) | |
720 found_libs.extend(opt_found_libs) | |
721 else: | |
722 opt_found_libs = self._lib_list(lib_dirs, opt_libs, exts) | |
723 if opt_found_libs: | |
724 found_libs.extend(opt_found_libs) | |
725 return info | |
726 else: | |
727 return None | |
728 | |
729 def combine_paths(self, *args): | |
730 """Return a list of existing paths composed by all combinations | |
731 of items from the arguments. | |
732 """ | |
733 return combine_paths(*args, **{'verbosity': self.verbosity}) | |
734 | |
735 | |
736 class fft_opt_info(system_info): | |
737 | |
738 def calc_info(self): | |
739 info = {} | |
740 fftw_info = get_info('fftw3') or get_info('fftw2') or get_info('dfftw') | |
741 djbfft_info = get_info('djbfft') | |
742 if fftw_info: | |
743 dict_append(info, **fftw_info) | |
744 if djbfft_info: | |
745 dict_append(info, **djbfft_info) | |
746 self.set_info(**info) | |
747 return | |
748 | |
749 | |
750 class fftw_info(system_info): | |
751 #variables to override | |
752 section = 'fftw' | |
753 dir_env_var = 'FFTW' | |
754 notfounderror = FFTWNotFoundError | |
755 ver_info = [{'name':'fftw3', | |
756 'libs':['fftw3'], | |
757 'includes':['fftw3.h'], | |
758 'macros':[('SCIPY_FFTW3_H', None)]}, | |
759 {'name':'fftw2', | |
760 'libs':['rfftw', 'fftw'], | |
761 'includes':['fftw.h', 'rfftw.h'], | |
762 'macros':[('SCIPY_FFTW_H', None)]}] | |
763 | |
764 def calc_ver_info(self, ver_param): | |
765 """Returns True on successful version detection, else False""" | |
766 lib_dirs = self.get_lib_dirs() | |
767 incl_dirs = self.get_include_dirs() | |
768 incl_dir = None | |
769 libs = self.get_libs(self.section + '_libs', ver_param['libs']) | |
770 info = self.check_libs(lib_dirs, libs) | |
771 if info is not None: | |
772 flag = 0 | |
773 for d in incl_dirs: | |
774 if len(self.combine_paths(d, ver_param['includes'])) \ | |
775 == len(ver_param['includes']): | |
776 dict_append(info, include_dirs=[d]) | |
777 flag = 1 | |
778 incl_dirs = [d] | |
779 break | |
780 if flag: | |
781 dict_append(info, define_macros=ver_param['macros']) | |
782 else: | |
783 info = None | |
784 if info is not None: | |
785 self.set_info(**info) | |
786 return True | |
787 else: | |
788 log.info(' %s not found' % (ver_param['name'])) | |
789 return False | |
790 | |
791 def calc_info(self): | |
792 for i in self.ver_info: | |
793 if self.calc_ver_info(i): | |
794 break | |
795 | |
796 | |
797 class fftw2_info(fftw_info): | |
798 #variables to override | |
799 section = 'fftw' | |
800 dir_env_var = 'FFTW' | |
801 notfounderror = FFTWNotFoundError | |
802 ver_info = [{'name':'fftw2', | |
803 'libs':['rfftw', 'fftw'], | |
804 'includes':['fftw.h', 'rfftw.h'], | |
805 'macros':[('SCIPY_FFTW_H', None)]} | |
806 ] | |
807 | |
808 | |
809 class fftw3_info(fftw_info): | |
810 #variables to override | |
811 section = 'fftw3' | |
812 dir_env_var = 'FFTW3' | |
813 notfounderror = FFTWNotFoundError | |
814 ver_info = [{'name':'fftw3', | |
815 'libs':['fftw3'], | |
816 'includes':['fftw3.h'], | |
817 'macros':[('SCIPY_FFTW3_H', None)]}, | |
818 ] | |
819 | |
820 | |
821 class dfftw_info(fftw_info): | |
822 section = 'fftw' | |
823 dir_env_var = 'FFTW' | |
824 ver_info = [{'name':'dfftw', | |
825 'libs':['drfftw', 'dfftw'], | |
826 'includes':['dfftw.h', 'drfftw.h'], | |
827 'macros':[('SCIPY_DFFTW_H', None)]}] | |
828 | |
829 | |
830 class sfftw_info(fftw_info): | |
831 section = 'fftw' | |
832 dir_env_var = 'FFTW' | |
833 ver_info = [{'name':'sfftw', | |
834 'libs':['srfftw', 'sfftw'], | |
835 'includes':['sfftw.h', 'srfftw.h'], | |
836 'macros':[('SCIPY_SFFTW_H', None)]}] | |
837 | |
838 | |
839 class fftw_threads_info(fftw_info): | |
840 section = 'fftw' | |
841 dir_env_var = 'FFTW' | |
842 ver_info = [{'name':'fftw threads', | |
843 'libs':['rfftw_threads', 'fftw_threads'], | |
844 'includes':['fftw_threads.h', 'rfftw_threads.h'], | |
845 'macros':[('SCIPY_FFTW_THREADS_H', None)]}] | |
846 | |
847 | |
848 class dfftw_threads_info(fftw_info): | |
849 section = 'fftw' | |
850 dir_env_var = 'FFTW' | |
851 ver_info = [{'name':'dfftw threads', | |
852 'libs':['drfftw_threads', 'dfftw_threads'], | |
853 'includes':['dfftw_threads.h', 'drfftw_threads.h'], | |
854 'macros':[('SCIPY_DFFTW_THREADS_H', None)]}] | |
855 | |
856 | |
857 class sfftw_threads_info(fftw_info): | |
858 section = 'fftw' | |
859 dir_env_var = 'FFTW' | |
860 ver_info = [{'name':'sfftw threads', | |
861 'libs':['srfftw_threads', 'sfftw_threads'], | |
862 'includes':['sfftw_threads.h', 'srfftw_threads.h'], | |
863 'macros':[('SCIPY_SFFTW_THREADS_H', None)]}] | |
864 | |
865 | |
866 class djbfft_info(system_info): | |
867 section = 'djbfft' | |
868 dir_env_var = 'DJBFFT' | |
869 notfounderror = DJBFFTNotFoundError | |
870 | |
871 def get_paths(self, section, key): | |
872 pre_dirs = system_info.get_paths(self, section, key) | |
873 dirs = [] | |
874 for d in pre_dirs: | |
875 dirs.extend(self.combine_paths(d, ['djbfft']) + [d]) | |
876 return [d for d in dirs if os.path.isdir(d)] | |
877 | |
878 def calc_info(self): | |
879 lib_dirs = self.get_lib_dirs() | |
880 incl_dirs = self.get_include_dirs() | |
881 info = None | |
882 for d in lib_dirs: | |
883 p = self.combine_paths(d, ['djbfft.a']) | |
884 if p: | |
885 info = {'extra_objects': p} | |
886 break | |
887 p = self.combine_paths(d, ['libdjbfft.a', 'libdjbfft' + so_ext]) | |
888 if p: | |
889 info = {'libraries': ['djbfft'], 'library_dirs': [d]} | |
890 break | |
891 if info is None: | |
892 return | |
893 for d in incl_dirs: | |
894 if len(self.combine_paths(d, ['fftc8.h', 'fftfreq.h'])) == 2: | |
895 dict_append(info, include_dirs=[d], | |
896 define_macros=[('SCIPY_DJBFFT_H', None)]) | |
897 self.set_info(**info) | |
898 return | |
899 return | |
900 | |
901 | |
902 class mkl_info(system_info): | |
903 section = 'mkl' | |
904 dir_env_var = 'MKL' | |
905 _lib_mkl = ['mkl', 'vml', 'guide'] | |
906 | |
907 def get_mkl_rootdir(self): | |
908 mklroot = os.environ.get('MKLROOT', None) | |
909 if mklroot is not None: | |
910 return mklroot | |
911 paths = os.environ.get('LD_LIBRARY_PATH', '').split(os.pathsep) | |
912 ld_so_conf = '/etc/ld.so.conf' | |
913 if os.path.isfile(ld_so_conf): | |
914 for d in open(ld_so_conf, 'r'): | |
915 d = d.strip() | |
916 if d: | |
917 paths.append(d) | |
918 intel_mkl_dirs = [] | |
919 for path in paths: | |
920 path_atoms = path.split(os.sep) | |
921 for m in path_atoms: | |
922 if m.startswith('mkl'): | |
923 d = os.sep.join(path_atoms[:path_atoms.index(m) + 2]) | |
924 intel_mkl_dirs.append(d) | |
925 break | |
926 for d in paths: | |
927 dirs = glob(os.path.join(d, 'mkl', '*')) | |
928 dirs += glob(os.path.join(d, 'mkl*')) | |
929 for d in dirs: | |
930 if os.path.isdir(os.path.join(d, 'lib')): | |
931 return d | |
932 return None | |
933 | |
934 def __init__(self): | |
935 mklroot = self.get_mkl_rootdir() | |
936 if mklroot is None: | |
937 system_info.__init__(self) | |
938 else: | |
939 from .cpuinfo import cpu | |
940 l = 'mkl' # use shared library | |
941 if cpu.is_Itanium(): | |
942 plt = '64' | |
943 #l = 'mkl_ipf' | |
944 elif cpu.is_Xeon(): | |
945 plt = 'em64t' | |
946 #l = 'mkl_em64t' | |
947 else: | |
948 plt = '32' | |
949 #l = 'mkl_ia32' | |
950 if l not in self._lib_mkl: | |
951 self._lib_mkl.insert(0, l) | |
952 system_info.__init__( | |
953 self, | |
954 default_lib_dirs=[os.path.join(mklroot, 'lib', plt)], | |
955 default_include_dirs=[os.path.join(mklroot, 'include')]) | |
956 | |
957 def calc_info(self): | |
958 lib_dirs = self.get_lib_dirs() | |
959 incl_dirs = self.get_include_dirs() | |
960 mkl_libs = self.get_libs('mkl_libs', self._lib_mkl) | |
961 info = self.check_libs2(lib_dirs, mkl_libs) | |
962 if info is None: | |
963 return | |
964 dict_append(info, | |
965 define_macros=[('SCIPY_MKL_H', None)], | |
966 include_dirs=incl_dirs) | |
967 if sys.platform == 'win32': | |
968 pass # win32 has no pthread library | |
969 else: | |
970 dict_append(info, libraries=['pthread']) | |
971 self.set_info(**info) | |
972 | |
973 | |
974 class lapack_mkl_info(mkl_info): | |
975 | |
976 def calc_info(self): | |
977 mkl = get_info('mkl') | |
978 if not mkl: | |
979 return | |
980 if sys.platform == 'win32': | |
981 lapack_libs = self.get_libs('lapack_libs', ['mkl_lapack']) | |
982 else: | |
983 lapack_libs = self.get_libs('lapack_libs', | |
984 ['mkl_lapack32', 'mkl_lapack64']) | |
985 | |
986 info = {'libraries': lapack_libs} | |
987 dict_append(info, **mkl) | |
988 self.set_info(**info) | |
989 | |
990 | |
991 class blas_mkl_info(mkl_info): | |
992 pass | |
993 | |
994 | |
995 class atlas_info(system_info): | |
996 section = 'atlas' | |
997 dir_env_var = 'ATLAS' | |
998 _lib_names = ['f77blas', 'cblas'] | |
999 if sys.platform[:7] == 'freebsd': | |
1000 _lib_atlas = ['atlas_r'] | |
1001 _lib_lapack = ['alapack_r'] | |
1002 else: | |
1003 _lib_atlas = ['atlas'] | |
1004 _lib_lapack = ['lapack'] | |
1005 | |
1006 notfounderror = AtlasNotFoundError | |
1007 | |
1008 def get_paths(self, section, key): | |
1009 pre_dirs = system_info.get_paths(self, section, key) | |
1010 dirs = [] | |
1011 for d in pre_dirs: | |
1012 dirs.extend(self.combine_paths(d, ['atlas*', 'ATLAS*', | |
1013 'sse', '3dnow', 'sse2']) + [d]) | |
1014 return [d for d in dirs if os.path.isdir(d)] | |
1015 | |
1016 def calc_info(self): | |
1017 lib_dirs = self.get_lib_dirs() | |
1018 info = {} | |
1019 atlas_libs = self.get_libs('atlas_libs', | |
1020 self._lib_names + self._lib_atlas) | |
1021 lapack_libs = self.get_libs('lapack_libs', self._lib_lapack) | |
1022 atlas = None | |
1023 lapack = None | |
1024 atlas_1 = None | |
1025 for d in lib_dirs: | |
1026 atlas = self.check_libs2(d, atlas_libs, []) | |
1027 lapack_atlas = self.check_libs2(d, ['lapack_atlas'], []) | |
1028 if atlas is not None: | |
1029 lib_dirs2 = [d] + self.combine_paths(d, ['atlas*', 'ATLAS*']) | |
1030 lapack = self.check_libs2(lib_dirs2, lapack_libs, []) | |
1031 if lapack is not None: | |
1032 break | |
1033 if atlas: | |
1034 atlas_1 = atlas | |
1035 log.info(self.__class__) | |
1036 if atlas is None: | |
1037 atlas = atlas_1 | |
1038 if atlas is None: | |
1039 return | |
1040 include_dirs = self.get_include_dirs() | |
1041 h = (self.combine_paths(lib_dirs + include_dirs, 'cblas.h') or [None]) | |
1042 h = h[0] | |
1043 if h: | |
1044 h = os.path.dirname(h) | |
1045 dict_append(info, include_dirs=[h]) | |
1046 info['language'] = 'c' | |
1047 if lapack is not None: | |
1048 dict_append(info, **lapack) | |
1049 dict_append(info, **atlas) | |
1050 elif 'lapack_atlas' in atlas['libraries']: | |
1051 dict_append(info, **atlas) | |
1052 dict_append(info, | |
1053 define_macros=[('ATLAS_WITH_LAPACK_ATLAS', None)]) | |
1054 self.set_info(**info) | |
1055 return | |
1056 else: | |
1057 dict_append(info, **atlas) | |
1058 dict_append(info, define_macros=[('ATLAS_WITHOUT_LAPACK', None)]) | |
1059 message = """ | |
1060 ********************************************************************* | |
1061 Could not find lapack library within the ATLAS installation. | |
1062 ********************************************************************* | |
1063 """ | |
1064 warnings.warn(message) | |
1065 self.set_info(**info) | |
1066 return | |
1067 | |
1068 # Check if lapack library is complete, only warn if it is not. | |
1069 lapack_dir = lapack['library_dirs'][0] | |
1070 lapack_name = lapack['libraries'][0] | |
1071 lapack_lib = None | |
1072 lib_prefixes = ['lib'] | |
1073 if sys.platform == 'win32': | |
1074 lib_prefixes.append('') | |
1075 for e in self.library_extensions(): | |
1076 for prefix in lib_prefixes: | |
1077 fn = os.path.join(lapack_dir, prefix + lapack_name + e) | |
1078 if os.path.exists(fn): | |
1079 lapack_lib = fn | |
1080 break | |
1081 if lapack_lib: | |
1082 break | |
1083 if lapack_lib is not None: | |
1084 sz = os.stat(lapack_lib)[6] | |
1085 if sz <= 4000 * 1024: | |
1086 message = """ | |
1087 ********************************************************************* | |
1088 Lapack library (from ATLAS) is probably incomplete: | |
1089 size of %s is %sk (expected >4000k) | |
1090 | |
1091 Follow the instructions in the KNOWN PROBLEMS section of the file | |
1092 numpy/INSTALL.txt. | |
1093 ********************************************************************* | |
1094 """ % (lapack_lib, sz / 1024) | |
1095 warnings.warn(message) | |
1096 else: | |
1097 info['language'] = 'f77' | |
1098 | |
1099 atlas_version, atlas_extra_info = get_atlas_version(**atlas) | |
1100 dict_append(info, **atlas_extra_info) | |
1101 | |
1102 self.set_info(**info) | |
1103 | |
1104 | |
1105 class atlas_blas_info(atlas_info): | |
1106 _lib_names = ['f77blas', 'cblas'] | |
1107 | |
1108 def calc_info(self): | |
1109 lib_dirs = self.get_lib_dirs() | |
1110 info = {} | |
1111 atlas_libs = self.get_libs('atlas_libs', | |
1112 self._lib_names + self._lib_atlas) | |
1113 atlas = self.check_libs2(lib_dirs, atlas_libs, []) | |
1114 if atlas is None: | |
1115 return | |
1116 include_dirs = self.get_include_dirs() | |
1117 h = (self.combine_paths(lib_dirs + include_dirs, 'cblas.h') or [None]) | |
1118 h = h[0] | |
1119 if h: | |
1120 h = os.path.dirname(h) | |
1121 dict_append(info, include_dirs=[h]) | |
1122 info['language'] = 'c' | |
1123 | |
1124 atlas_version, atlas_extra_info = get_atlas_version(**atlas) | |
1125 dict_append(atlas, **atlas_extra_info) | |
1126 | |
1127 dict_append(info, **atlas) | |
1128 | |
1129 self.set_info(**info) | |
1130 return | |
1131 | |
1132 | |
1133 class atlas_threads_info(atlas_info): | |
1134 dir_env_var = ['PTATLAS', 'ATLAS'] | |
1135 _lib_names = ['ptf77blas', 'ptcblas'] | |
1136 | |
1137 | |
1138 class atlas_blas_threads_info(atlas_blas_info): | |
1139 dir_env_var = ['PTATLAS', 'ATLAS'] | |
1140 _lib_names = ['ptf77blas', 'ptcblas'] | |
1141 | |
1142 | |
1143 class lapack_atlas_info(atlas_info): | |
1144 _lib_names = ['lapack_atlas'] + atlas_info._lib_names | |
1145 | |
1146 | |
1147 class lapack_atlas_threads_info(atlas_threads_info): | |
1148 _lib_names = ['lapack_atlas'] + atlas_threads_info._lib_names | |
1149 | |
1150 | |
1151 class lapack_info(system_info): | |
1152 section = 'lapack' | |
1153 dir_env_var = 'LAPACK' | |
1154 _lib_names = ['lapack'] | |
1155 notfounderror = LapackNotFoundError | |
1156 | |
1157 def calc_info(self): | |
1158 lib_dirs = self.get_lib_dirs() | |
1159 | |
1160 lapack_libs = self.get_libs('lapack_libs', self._lib_names) | |
1161 info = self.check_libs(lib_dirs, lapack_libs, []) | |
1162 if info is None: | |
1163 return | |
1164 info['language'] = 'f77' | |
1165 self.set_info(**info) | |
1166 | |
1167 | |
1168 class lapack_src_info(system_info): | |
1169 section = 'lapack_src' | |
1170 dir_env_var = 'LAPACK_SRC' | |
1171 notfounderror = LapackSrcNotFoundError | |
1172 | |
1173 def get_paths(self, section, key): | |
1174 pre_dirs = system_info.get_paths(self, section, key) | |
1175 dirs = [] | |
1176 for d in pre_dirs: | |
1177 dirs.extend([d] + self.combine_paths(d, ['LAPACK*/SRC', 'SRC'])) | |
1178 return [d for d in dirs if os.path.isdir(d)] | |
1179 | |
1180 def calc_info(self): | |
1181 src_dirs = self.get_src_dirs() | |
1182 src_dir = '' | |
1183 for d in src_dirs: | |
1184 if os.path.isfile(os.path.join(d, 'dgesv.f')): | |
1185 src_dir = d | |
1186 break | |
1187 if not src_dir: | |
1188 #XXX: Get sources from netlib. May be ask first. | |
1189 return | |
1190 # The following is extracted from LAPACK-3.0/SRC/Makefile. | |
1191 # Added missing names from lapack-lite-3.1.1/SRC/Makefile | |
1192 # while keeping removed names for Lapack-3.0 compatibility. | |
1193 allaux = ''' | |
1194 ilaenv ieeeck lsame lsamen xerbla | |
1195 iparmq | |
1196 ''' # *.f | |
1197 laux = ''' | |
1198 bdsdc bdsqr disna labad lacpy ladiv lae2 laebz laed0 laed1 | |
1199 laed2 laed3 laed4 laed5 laed6 laed7 laed8 laed9 laeda laev2 | |
1200 lagtf lagts lamch lamrg lanst lapy2 lapy3 larnv larrb larre | |
1201 larrf lartg laruv las2 lascl lasd0 lasd1 lasd2 lasd3 lasd4 | |
1202 lasd5 lasd6 lasd7 lasd8 lasd9 lasda lasdq lasdt laset lasq1 | |
1203 lasq2 lasq3 lasq4 lasq5 lasq6 lasr lasrt lassq lasv2 pttrf | |
1204 stebz stedc steqr sterf | |
1205 | |
1206 larra larrc larrd larr larrk larrj larrr laneg laisnan isnan | |
1207 lazq3 lazq4 | |
1208 ''' # [s|d]*.f | |
1209 lasrc = ''' | |
1210 gbbrd gbcon gbequ gbrfs gbsv gbsvx gbtf2 gbtrf gbtrs gebak | |
1211 gebal gebd2 gebrd gecon geequ gees geesx geev geevx gegs gegv | |
1212 gehd2 gehrd gelq2 gelqf gels gelsd gelss gelsx gelsy geql2 | |
1213 geqlf geqp3 geqpf geqr2 geqrf gerfs gerq2 gerqf gesc2 gesdd | |
1214 gesv gesvd gesvx getc2 getf2 getrf getri getrs ggbak ggbal | |
1215 gges ggesx ggev ggevx ggglm gghrd gglse ggqrf ggrqf ggsvd | |
1216 ggsvp gtcon gtrfs gtsv gtsvx gttrf gttrs gtts2 hgeqz hsein | |
1217 hseqr labrd lacon laein lags2 lagtm lahqr lahrd laic1 lals0 | |
1218 lalsa lalsd langb lange langt lanhs lansb lansp lansy lantb | |
1219 lantp lantr lapll lapmt laqgb laqge laqp2 laqps laqsb laqsp | |
1220 laqsy lar1v lar2v larf larfb larfg larft larfx largv larrv | |
1221 lartv larz larzb larzt laswp lasyf latbs latdf latps latrd | |
1222 latrs latrz latzm lauu2 lauum pbcon pbequ pbrfs pbstf pbsv | |
1223 pbsvx pbtf2 pbtrf pbtrs pocon poequ porfs posv posvx potf2 | |
1224 potrf potri potrs ppcon ppequ pprfs ppsv ppsvx pptrf pptri | |
1225 pptrs ptcon pteqr ptrfs ptsv ptsvx pttrs ptts2 spcon sprfs | |
1226 spsv spsvx sptrf sptri sptrs stegr stein sycon syrfs sysv | |
1227 sysvx sytf2 sytrf sytri sytrs tbcon tbrfs tbtrs tgevc tgex2 | |
1228 tgexc tgsen tgsja tgsna tgsy2 tgsyl tpcon tprfs tptri tptrs | |
1229 trcon trevc trexc trrfs trsen trsna trsyl trti2 trtri trtrs | |
1230 tzrqf tzrzf | |
1231 | |
1232 lacn2 lahr2 stemr laqr0 laqr1 laqr2 laqr3 laqr4 laqr5 | |
1233 ''' # [s|c|d|z]*.f | |
1234 sd_lasrc = ''' | |
1235 laexc lag2 lagv2 laln2 lanv2 laqtr lasy2 opgtr opmtr org2l | |
1236 org2r orgbr orghr orgl2 orglq orgql orgqr orgr2 orgrq orgtr | |
1237 orm2l orm2r ormbr ormhr orml2 ormlq ormql ormqr ormr2 ormr3 | |
1238 ormrq ormrz ormtr rscl sbev sbevd sbevx sbgst sbgv sbgvd sbgvx | |
1239 sbtrd spev spevd spevx spgst spgv spgvd spgvx sptrd stev stevd | |
1240 stevr stevx syev syevd syevr syevx sygs2 sygst sygv sygvd | |
1241 sygvx sytd2 sytrd | |
1242 ''' # [s|d]*.f | |
1243 cz_lasrc = ''' | |
1244 bdsqr hbev hbevd hbevx hbgst hbgv hbgvd hbgvx hbtrd hecon heev | |
1245 heevd heevr heevx hegs2 hegst hegv hegvd hegvx herfs hesv | |
1246 hesvx hetd2 hetf2 hetrd hetrf hetri hetrs hpcon hpev hpevd | |
1247 hpevx hpgst hpgv hpgvd hpgvx hprfs hpsv hpsvx hptrd hptrf | |
1248 hptri hptrs lacgv lacp2 lacpy lacrm lacrt ladiv laed0 laed7 | |
1249 laed8 laesy laev2 lahef lanhb lanhe lanhp lanht laqhb laqhe | |
1250 laqhp larcm larnv lartg lascl laset lasr lassq pttrf rot spmv | |
1251 spr stedc steqr symv syr ung2l ung2r ungbr unghr ungl2 unglq | |
1252 ungql ungqr ungr2 ungrq ungtr unm2l unm2r unmbr unmhr unml2 | |
1253 unmlq unmql unmqr unmr2 unmr3 unmrq unmrz unmtr upgtr upmtr | |
1254 ''' # [c|z]*.f | |
1255 ####### | |
1256 sclaux = laux + ' econd ' # s*.f | |
1257 dzlaux = laux + ' secnd ' # d*.f | |
1258 slasrc = lasrc + sd_lasrc # s*.f | |
1259 dlasrc = lasrc + sd_lasrc # d*.f | |
1260 clasrc = lasrc + cz_lasrc + ' srot srscl ' # c*.f | |
1261 zlasrc = lasrc + cz_lasrc + ' drot drscl ' # z*.f | |
1262 oclasrc = ' icmax1 scsum1 ' # *.f | |
1263 ozlasrc = ' izmax1 dzsum1 ' # *.f | |
1264 sources = ['s%s.f' % f for f in (sclaux + slasrc).split()] \ | |
1265 + ['d%s.f' % f for f in (dzlaux + dlasrc).split()] \ | |
1266 + ['c%s.f' % f for f in (clasrc).split()] \ | |
1267 + ['z%s.f' % f for f in (zlasrc).split()] \ | |
1268 + ['%s.f' % f for f in (allaux + oclasrc + ozlasrc).split()] | |
1269 sources = [os.path.join(src_dir, f) for f in sources] | |
1270 # Lapack 3.1: | |
1271 src_dir2 = os.path.join(src_dir, '..', 'INSTALL') | |
1272 sources += [os.path.join(src_dir2, p + 'lamch.f') for p in 'sdcz'] | |
1273 # Lapack 3.2.1: | |
1274 sources += [os.path.join(src_dir, p + 'larfp.f') for p in 'sdcz'] | |
1275 sources += [os.path.join(src_dir, 'ila' + p + 'lr.f') for p in 'sdcz'] | |
1276 sources += [os.path.join(src_dir, 'ila' + p + 'lc.f') for p in 'sdcz'] | |
1277 # Should we check here actual existence of source files? | |
1278 # Yes, the file listing is different between 3.0 and 3.1 | |
1279 # versions. | |
1280 sources = [f for f in sources if os.path.isfile(f)] | |
1281 info = {'sources': sources, 'language': 'f77'} | |
1282 self.set_info(**info) | |
1283 | |
1284 atlas_version_c_text = r''' | |
1285 /* This file is generated from numpy/distutils/system_info.py */ | |
1286 void ATL_buildinfo(void); | |
1287 int main(void) { | |
1288 ATL_buildinfo(); | |
1289 return 0; | |
1290 } | |
1291 ''' | |
1292 | |
1293 _cached_atlas_version = {} | |
1294 | |
1295 | |
1296 def get_atlas_version(**config): | |
1297 libraries = config.get('libraries', []) | |
1298 library_dirs = config.get('library_dirs', []) | |
1299 key = (tuple(libraries), tuple(library_dirs)) | |
1300 if key in _cached_atlas_version: | |
1301 return _cached_atlas_version[key] | |
1302 c = cmd_config(Distribution()) | |
1303 atlas_version = None | |
1304 info = {} | |
1305 try: | |
1306 s, o = c.get_output(atlas_version_c_text, | |
1307 libraries=libraries, library_dirs=library_dirs, | |
1308 use_tee=(system_info.verbosity > 0)) | |
1309 if s and re.search(r'undefined reference to `_gfortran', o, re.M): | |
1310 s, o = c.get_output(atlas_version_c_text, | |
1311 libraries=libraries + ['gfortran'], | |
1312 library_dirs=library_dirs, | |
1313 use_tee=(system_info.verbosity > 0)) | |
1314 if not s: | |
1315 warnings.warn(""" | |
1316 ***************************************************** | |
1317 Linkage with ATLAS requires gfortran. Use | |
1318 | |
1319 python setup.py config_fc --fcompiler=gnu95 ... | |
1320 | |
1321 when building extension libraries that use ATLAS. | |
1322 Make sure that -lgfortran is used for C++ extensions. | |
1323 ***************************************************** | |
1324 """) | |
1325 dict_append(info, language='f90', | |
1326 define_macros=[('ATLAS_REQUIRES_GFORTRAN', None)]) | |
1327 except Exception: # failed to get version from file -- maybe on Windows | |
1328 # look at directory name | |
1329 for o in library_dirs: | |
1330 m = re.search(r'ATLAS_(?P<version>\d+[.]\d+[.]\d+)_', o) | |
1331 if m: | |
1332 atlas_version = m.group('version') | |
1333 if atlas_version is not None: | |
1334 break | |
1335 | |
1336 # final choice --- look at ATLAS_VERSION environment | |
1337 # variable | |
1338 if atlas_version is None: | |
1339 atlas_version = os.environ.get('ATLAS_VERSION', None) | |
1340 if atlas_version: | |
1341 dict_append(info, define_macros=[( | |
1342 'ATLAS_INFO', '"\\"%s\\""' % atlas_version) | |
1343 ]) | |
1344 else: | |
1345 dict_append(info, define_macros=[('NO_ATLAS_INFO', -1)]) | |
1346 return atlas_version or '?.?.?', info | |
1347 | |
1348 if not s: | |
1349 m = re.search(r'ATLAS version (?P<version>\d+[.]\d+[.]\d+)', o) | |
1350 if m: | |
1351 atlas_version = m.group('version') | |
1352 if atlas_version is None: | |
1353 if re.search(r'undefined symbol: ATL_buildinfo', o, re.M): | |
1354 atlas_version = '3.2.1_pre3.3.6' | |
1355 else: | |
1356 log.info('Status: %d', s) | |
1357 log.info('Output: %s', o) | |
1358 | |
1359 if atlas_version == '3.2.1_pre3.3.6': | |
1360 dict_append(info, define_macros=[('NO_ATLAS_INFO', -2)]) | |
1361 else: | |
1362 dict_append(info, define_macros=[( | |
1363 'ATLAS_INFO', '"\\"%s\\""' % atlas_version) | |
1364 ]) | |
1365 result = _cached_atlas_version[key] = atlas_version, info | |
1366 return result | |
1367 | |
1368 | |
1369 | |
1370 class lapack_opt_info(system_info): | |
1371 | |
1372 notfounderror = LapackNotFoundError | |
1373 | |
1374 def calc_info(self): | |
1375 | |
1376 openblas_info = get_info('openblas_lapack') | |
1377 if openblas_info: | |
1378 self.set_info(**openblas_info) | |
1379 return | |
1380 | |
1381 lapack_mkl_info = get_info('lapack_mkl') | |
1382 if lapack_mkl_info: | |
1383 self.set_info(**lapack_mkl_info) | |
1384 return | |
1385 | |
1386 atlas_info = get_info('atlas_threads') | |
1387 if not atlas_info: | |
1388 atlas_info = get_info('atlas') | |
1389 | |
1390 if sys.platform == 'darwin' and not atlas_info: | |
1391 # Use the system lapack from Accelerate or vecLib under OSX | |
1392 args = [] | |
1393 link_args = [] | |
1394 if get_platform()[-4:] == 'i386' or 'intel' in get_platform() or \ | |
1395 'x86_64' in get_platform() or \ | |
1396 'i386' in platform.platform(): | |
1397 intel = 1 | |
1398 else: | |
1399 intel = 0 | |
1400 if os.path.exists('/System/Library/Frameworks' | |
1401 '/Accelerate.framework/'): | |
1402 if intel: | |
1403 args.extend(['-msse3', '-DAPPLE_ACCELERATE_SGEMV_PATCH']) | |
1404 else: | |
1405 args.extend(['-faltivec']) | |
1406 link_args.extend(['-Wl,-framework', '-Wl,Accelerate']) | |
1407 elif os.path.exists('/System/Library/Frameworks' | |
1408 '/vecLib.framework/'): | |
1409 if intel: | |
1410 args.extend(['-msse3']) | |
1411 else: | |
1412 args.extend(['-faltivec']) | |
1413 link_args.extend(['-Wl,-framework', '-Wl,vecLib']) | |
1414 if args: | |
1415 self.set_info(extra_compile_args=args, | |
1416 extra_link_args=link_args, | |
1417 define_macros=[('NO_ATLAS_INFO', 3)]) | |
1418 return | |
1419 | |
1420 #atlas_info = {} ## uncomment for testing | |
1421 need_lapack = 0 | |
1422 need_blas = 0 | |
1423 info = {} | |
1424 if atlas_info: | |
1425 l = atlas_info.get('define_macros', []) | |
1426 if ('ATLAS_WITH_LAPACK_ATLAS', None) in l \ | |
1427 or ('ATLAS_WITHOUT_LAPACK', None) in l: | |
1428 need_lapack = 1 | |
1429 info = atlas_info | |
1430 | |
1431 else: | |
1432 warnings.warn(AtlasNotFoundError.__doc__) | |
1433 need_blas = 1 | |
1434 need_lapack = 1 | |
1435 dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)]) | |
1436 | |
1437 if need_lapack: | |
1438 lapack_info = get_info('lapack') | |
1439 #lapack_info = {} ## uncomment for testing | |
1440 if lapack_info: | |
1441 dict_append(info, **lapack_info) | |
1442 else: | |
1443 warnings.warn(LapackNotFoundError.__doc__) | |
1444 lapack_src_info = get_info('lapack_src') | |
1445 if not lapack_src_info: | |
1446 warnings.warn(LapackSrcNotFoundError.__doc__) | |
1447 return | |
1448 dict_append(info, libraries=[('flapack_src', lapack_src_info)]) | |
1449 | |
1450 if need_blas: | |
1451 blas_info = get_info('blas') | |
1452 #blas_info = {} ## uncomment for testing | |
1453 if blas_info: | |
1454 dict_append(info, **blas_info) | |
1455 else: | |
1456 warnings.warn(BlasNotFoundError.__doc__) | |
1457 blas_src_info = get_info('blas_src') | |
1458 if not blas_src_info: | |
1459 warnings.warn(BlasSrcNotFoundError.__doc__) | |
1460 return | |
1461 dict_append(info, libraries=[('fblas_src', blas_src_info)]) | |
1462 | |
1463 self.set_info(**info) | |
1464 return | |
1465 | |
1466 | |
1467 class blas_opt_info(system_info): | |
1468 | |
1469 notfounderror = BlasNotFoundError | |
1470 | |
1471 def calc_info(self): | |
1472 | |
1473 blas_mkl_info = get_info('blas_mkl') | |
1474 if blas_mkl_info: | |
1475 self.set_info(**blas_mkl_info) | |
1476 return | |
1477 | |
1478 openblas_info = get_info('openblas') | |
1479 if openblas_info: | |
1480 self.set_info(**openblas_info) | |
1481 return | |
1482 | |
1483 atlas_info = get_info('atlas_blas_threads') | |
1484 if not atlas_info: | |
1485 atlas_info = get_info('atlas_blas') | |
1486 | |
1487 if sys.platform == 'darwin' and not atlas_info: | |
1488 # Use the system BLAS from Accelerate or vecLib under OSX | |
1489 args = [] | |
1490 link_args = [] | |
1491 if get_platform()[-4:] == 'i386' or 'intel' in get_platform() or \ | |
1492 'x86_64' in get_platform() or \ | |
1493 'i386' in platform.platform(): | |
1494 intel = 1 | |
1495 else: | |
1496 intel = 0 | |
1497 if os.path.exists('/System/Library/Frameworks' | |
1498 '/Accelerate.framework/'): | |
1499 if intel: | |
1500 args.extend(['-msse3', '-DAPPLE_ACCELERATE_SGEMV_PATCH']) | |
1501 else: | |
1502 args.extend(['-faltivec']) | |
1503 args.extend([ | |
1504 '-I/System/Library/Frameworks/vecLib.framework/Headers']) | |
1505 link_args.extend(['-Wl,-framework', '-Wl,Accelerate']) | |
1506 elif os.path.exists('/System/Library/Frameworks' | |
1507 '/vecLib.framework/'): | |
1508 if intel: | |
1509 args.extend(['-msse3']) | |
1510 else: | |
1511 args.extend(['-faltivec']) | |
1512 args.extend([ | |
1513 '-I/System/Library/Frameworks/vecLib.framework/Headers']) | |
1514 link_args.extend(['-Wl,-framework', '-Wl,vecLib']) | |
1515 if args: | |
1516 self.set_info(extra_compile_args=args, | |
1517 extra_link_args=link_args, | |
1518 define_macros=[('NO_ATLAS_INFO', 3)]) | |
1519 return | |
1520 | |
1521 need_blas = 0 | |
1522 info = {} | |
1523 if atlas_info: | |
1524 info = atlas_info | |
1525 else: | |
1526 warnings.warn(AtlasNotFoundError.__doc__) | |
1527 need_blas = 1 | |
1528 dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)]) | |
1529 | |
1530 if need_blas: | |
1531 blas_info = get_info('blas') | |
1532 if blas_info: | |
1533 dict_append(info, **blas_info) | |
1534 else: | |
1535 warnings.warn(BlasNotFoundError.__doc__) | |
1536 blas_src_info = get_info('blas_src') | |
1537 if not blas_src_info: | |
1538 warnings.warn(BlasSrcNotFoundError.__doc__) | |
1539 return | |
1540 dict_append(info, libraries=[('fblas_src', blas_src_info)]) | |
1541 | |
1542 self.set_info(**info) | |
1543 return | |
1544 | |
1545 | |
1546 class blas_info(system_info): | |
1547 section = 'blas' | |
1548 dir_env_var = 'BLAS' | |
1549 _lib_names = ['blas'] | |
1550 notfounderror = BlasNotFoundError | |
1551 | |
1552 def calc_info(self): | |
1553 lib_dirs = self.get_lib_dirs() | |
1554 | |
1555 blas_libs = self.get_libs('blas_libs', self._lib_names) | |
1556 info = self.check_libs(lib_dirs, blas_libs, []) | |
1557 if info is None: | |
1558 return | |
1559 info['language'] = 'f77' # XXX: is it generally true? | |
1560 self.set_info(**info) | |
1561 | |
1562 | |
1563 class openblas_info(blas_info): | |
1564 section = 'openblas' | |
1565 dir_env_var = 'OPENBLAS' | |
1566 _lib_names = ['openblas'] | |
1567 notfounderror = BlasNotFoundError | |
1568 | |
1569 def check_embedded_lapack(self, info): | |
1570 return True | |
1571 | |
1572 def calc_info(self): | |
1573 lib_dirs = self.get_lib_dirs() | |
1574 | |
1575 openblas_libs = self.get_libs('libraries', self._lib_names) | |
1576 if openblas_libs == self._lib_names: # backward compat with 1.8.0 | |
1577 openblas_libs = self.get_libs('openblas_libs', self._lib_names) | |
1578 info = self.check_libs(lib_dirs, openblas_libs, []) | |
1579 if info is None: | |
1580 return | |
1581 | |
1582 if not self.check_embedded_lapack(info): | |
1583 return None | |
1584 | |
1585 info['language'] = 'f77' # XXX: is it generally true? | |
1586 self.set_info(**info) | |
1587 | |
1588 | |
1589 class openblas_lapack_info(openblas_info): | |
1590 section = 'openblas' | |
1591 dir_env_var = 'OPENBLAS' | |
1592 _lib_names = ['openblas'] | |
1593 notfounderror = BlasNotFoundError | |
1594 | |
1595 def check_embedded_lapack(self, info): | |
1596 res = False | |
1597 c = distutils.ccompiler.new_compiler() | |
1598 tmpdir = tempfile.mkdtemp() | |
1599 s = """void zungqr(); | |
1600 int main(int argc, const char *argv[]) | |
1601 { | |
1602 zungqr_(); | |
1603 return 0; | |
1604 }""" | |
1605 src = os.path.join(tmpdir, 'source.c') | |
1606 out = os.path.join(tmpdir, 'a.out') | |
1607 try: | |
1608 with open(src, 'wt') as f: | |
1609 f.write(s) | |
1610 obj = c.compile([src], output_dir=tmpdir) | |
1611 try: | |
1612 c.link_executable(obj, out, libraries=info['libraries'], | |
1613 library_dirs=info['library_dirs']) | |
1614 res = True | |
1615 except distutils.ccompiler.LinkError: | |
1616 res = False | |
1617 finally: | |
1618 shutil.rmtree(tmpdir) | |
1619 return res | |
1620 | |
1621 | |
1622 class blas_src_info(system_info): | |
1623 section = 'blas_src' | |
1624 dir_env_var = 'BLAS_SRC' | |
1625 notfounderror = BlasSrcNotFoundError | |
1626 | |
1627 def get_paths(self, section, key): | |
1628 pre_dirs = system_info.get_paths(self, section, key) | |
1629 dirs = [] | |
1630 for d in pre_dirs: | |
1631 dirs.extend([d] + self.combine_paths(d, ['blas'])) | |
1632 return [d for d in dirs if os.path.isdir(d)] | |
1633 | |
1634 def calc_info(self): | |
1635 src_dirs = self.get_src_dirs() | |
1636 src_dir = '' | |
1637 for d in src_dirs: | |
1638 if os.path.isfile(os.path.join(d, 'daxpy.f')): | |
1639 src_dir = d | |
1640 break | |
1641 if not src_dir: | |
1642 #XXX: Get sources from netlib. May be ask first. | |
1643 return | |
1644 blas1 = ''' | |
1645 caxpy csscal dnrm2 dzasum saxpy srotg zdotc ccopy cswap drot | |
1646 dznrm2 scasum srotm zdotu cdotc dasum drotg icamax scnrm2 | |
1647 srotmg zdrot cdotu daxpy drotm idamax scopy sscal zdscal crotg | |
1648 dcabs1 drotmg isamax sdot sswap zrotg cscal dcopy dscal izamax | |
1649 snrm2 zaxpy zscal csrot ddot dswap sasum srot zcopy zswap | |
1650 scabs1 | |
1651 ''' | |
1652 blas2 = ''' | |
1653 cgbmv chpmv ctrsv dsymv dtrsv sspr2 strmv zhemv ztpmv cgemv | |
1654 chpr dgbmv dsyr lsame ssymv strsv zher ztpsv cgerc chpr2 dgemv | |
1655 dsyr2 sgbmv ssyr xerbla zher2 ztrmv cgeru ctbmv dger dtbmv | |
1656 sgemv ssyr2 zgbmv zhpmv ztrsv chbmv ctbsv dsbmv dtbsv sger | |
1657 stbmv zgemv zhpr chemv ctpmv dspmv dtpmv ssbmv stbsv zgerc | |
1658 zhpr2 cher ctpsv dspr dtpsv sspmv stpmv zgeru ztbmv cher2 | |
1659 ctrmv dspr2 dtrmv sspr stpsv zhbmv ztbsv | |
1660 ''' | |
1661 blas3 = ''' | |
1662 cgemm csymm ctrsm dsyrk sgemm strmm zhemm zsyr2k chemm csyr2k | |
1663 dgemm dtrmm ssymm strsm zher2k zsyrk cher2k csyrk dsymm dtrsm | |
1664 ssyr2k zherk ztrmm cherk ctrmm dsyr2k ssyrk zgemm zsymm ztrsm | |
1665 ''' | |
1666 sources = [os.path.join(src_dir, f + '.f') \ | |
1667 for f in (blas1 + blas2 + blas3).split()] | |
1668 #XXX: should we check here actual existence of source files? | |
1669 sources = [f for f in sources if os.path.isfile(f)] | |
1670 info = {'sources': sources, 'language': 'f77'} | |
1671 self.set_info(**info) | |
1672 | |
1673 | |
1674 class x11_info(system_info): | |
1675 section = 'x11' | |
1676 notfounderror = X11NotFoundError | |
1677 | |
1678 def __init__(self): | |
1679 system_info.__init__(self, | |
1680 default_lib_dirs=default_x11_lib_dirs, | |
1681 default_include_dirs=default_x11_include_dirs) | |
1682 | |
1683 def calc_info(self): | |
1684 if sys.platform in ['win32']: | |
1685 return | |
1686 lib_dirs = self.get_lib_dirs() | |
1687 include_dirs = self.get_include_dirs() | |
1688 x11_libs = self.get_libs('x11_libs', ['X11']) | |
1689 info = self.check_libs(lib_dirs, x11_libs, []) | |
1690 if info is None: | |
1691 return | |
1692 inc_dir = None | |
1693 for d in include_dirs: | |
1694 if self.combine_paths(d, 'X11/X.h'): | |
1695 inc_dir = d | |
1696 break | |
1697 if inc_dir is not None: | |
1698 dict_append(info, include_dirs=[inc_dir]) | |
1699 self.set_info(**info) | |
1700 | |
1701 | |
1702 class _numpy_info(system_info): | |
1703 section = 'Numeric' | |
1704 modulename = 'Numeric' | |
1705 notfounderror = NumericNotFoundError | |
1706 | |
1707 def __init__(self): | |
1708 include_dirs = [] | |
1709 try: | |
1710 module = __import__(self.modulename) | |
1711 prefix = [] | |
1712 for name in module.__file__.split(os.sep): | |
1713 if name == 'lib': | |
1714 break | |
1715 prefix.append(name) | |
1716 | |
1717 # Ask numpy for its own include path before attempting | |
1718 # anything else | |
1719 try: | |
1720 include_dirs.append(getattr(module, 'get_include')()) | |
1721 except AttributeError: | |
1722 pass | |
1723 | |
1724 include_dirs.append(distutils.sysconfig.get_python_inc( | |
1725 prefix=os.sep.join(prefix))) | |
1726 except ImportError: | |
1727 pass | |
1728 py_incl_dir = distutils.sysconfig.get_python_inc() | |
1729 include_dirs.append(py_incl_dir) | |
1730 py_pincl_dir = distutils.sysconfig.get_python_inc(plat_specific=True) | |
1731 if py_pincl_dir not in include_dirs: | |
1732 include_dirs.append(py_pincl_dir) | |
1733 for d in default_include_dirs: | |
1734 d = os.path.join(d, os.path.basename(py_incl_dir)) | |
1735 if d not in include_dirs: | |
1736 include_dirs.append(d) | |
1737 system_info.__init__(self, | |
1738 default_lib_dirs=[], | |
1739 default_include_dirs=include_dirs) | |
1740 | |
1741 def calc_info(self): | |
1742 try: | |
1743 module = __import__(self.modulename) | |
1744 except ImportError: | |
1745 return | |
1746 info = {} | |
1747 macros = [] | |
1748 for v in ['__version__', 'version']: | |
1749 vrs = getattr(module, v, None) | |
1750 if vrs is None: | |
1751 continue | |
1752 macros = [(self.modulename.upper() + '_VERSION', | |
1753 '"\\"%s\\""' % (vrs)), | |
1754 (self.modulename.upper(), None)] | |
1755 break | |
1756 ## try: | |
1757 ## macros.append( | |
1758 ## (self.modulename.upper()+'_VERSION_HEX', | |
1759 ## hex(vstr2hex(module.__version__))), | |
1760 ## ) | |
1761 ## except Exception as msg: | |
1762 ## print msg | |
1763 dict_append(info, define_macros=macros) | |
1764 include_dirs = self.get_include_dirs() | |
1765 inc_dir = None | |
1766 for d in include_dirs: | |
1767 if self.combine_paths(d, | |
1768 os.path.join(self.modulename, | |
1769 'arrayobject.h')): | |
1770 inc_dir = d | |
1771 break | |
1772 if inc_dir is not None: | |
1773 dict_append(info, include_dirs=[inc_dir]) | |
1774 if info: | |
1775 self.set_info(**info) | |
1776 return | |
1777 | |
1778 | |
1779 class numarray_info(_numpy_info): | |
1780 section = 'numarray' | |
1781 modulename = 'numarray' | |
1782 | |
1783 | |
1784 class Numeric_info(_numpy_info): | |
1785 section = 'Numeric' | |
1786 modulename = 'Numeric' | |
1787 | |
1788 | |
1789 class numpy_info(_numpy_info): | |
1790 section = 'numpy' | |
1791 modulename = 'numpy' | |
1792 | |
1793 | |
1794 class numerix_info(system_info): | |
1795 section = 'numerix' | |
1796 | |
1797 def calc_info(self): | |
1798 which = None, None | |
1799 if os.getenv("NUMERIX"): | |
1800 which = os.getenv("NUMERIX"), "environment var" | |
1801 # If all the above fail, default to numpy. | |
1802 if which[0] is None: | |
1803 which = "numpy", "defaulted" | |
1804 try: | |
1805 import numpy | |
1806 which = "numpy", "defaulted" | |
1807 except ImportError: | |
1808 msg1 = str(get_exception()) | |
1809 try: | |
1810 import Numeric | |
1811 which = "numeric", "defaulted" | |
1812 except ImportError: | |
1813 msg2 = str(get_exception()) | |
1814 try: | |
1815 import numarray | |
1816 which = "numarray", "defaulted" | |
1817 except ImportError: | |
1818 msg3 = str(get_exception()) | |
1819 log.info(msg1) | |
1820 log.info(msg2) | |
1821 log.info(msg3) | |
1822 which = which[0].strip().lower(), which[1] | |
1823 if which[0] not in ["numeric", "numarray", "numpy"]: | |
1824 raise ValueError("numerix selector must be either 'Numeric' " | |
1825 "or 'numarray' or 'numpy' but the value obtained" | |
1826 " from the %s was '%s'." % (which[1], which[0])) | |
1827 os.environ['NUMERIX'] = which[0] | |
1828 self.set_info(**get_info(which[0])) | |
1829 | |
1830 | |
1831 class f2py_info(system_info): | |
1832 def calc_info(self): | |
1833 try: | |
1834 import numpy.f2py as f2py | |
1835 except ImportError: | |
1836 return | |
1837 f2py_dir = os.path.join(os.path.dirname(f2py.__file__), 'src') | |
1838 self.set_info(sources=[os.path.join(f2py_dir, 'fortranobject.c')], | |
1839 include_dirs=[f2py_dir]) | |
1840 return | |
1841 | |
1842 | |
1843 class boost_python_info(system_info): | |
1844 section = 'boost_python' | |
1845 dir_env_var = 'BOOST' | |
1846 | |
1847 def get_paths(self, section, key): | |
1848 pre_dirs = system_info.get_paths(self, section, key) | |
1849 dirs = [] | |
1850 for d in pre_dirs: | |
1851 dirs.extend([d] + self.combine_paths(d, ['boost*'])) | |
1852 return [d for d in dirs if os.path.isdir(d)] | |
1853 | |
1854 def calc_info(self): | |
1855 src_dirs = self.get_src_dirs() | |
1856 src_dir = '' | |
1857 for d in src_dirs: | |
1858 if os.path.isfile(os.path.join(d, 'libs', 'python', 'src', | |
1859 'module.cpp')): | |
1860 src_dir = d | |
1861 break | |
1862 if not src_dir: | |
1863 return | |
1864 py_incl_dirs = [distutils.sysconfig.get_python_inc()] | |
1865 py_pincl_dir = distutils.sysconfig.get_python_inc(plat_specific=True) | |
1866 if py_pincl_dir not in py_incl_dirs: | |
1867 py_incl_dirs.append(py_pincl_dir) | |
1868 srcs_dir = os.path.join(src_dir, 'libs', 'python', 'src') | |
1869 bpl_srcs = glob(os.path.join(srcs_dir, '*.cpp')) | |
1870 bpl_srcs += glob(os.path.join(srcs_dir, '*', '*.cpp')) | |
1871 info = {'libraries': [('boost_python_src', | |
1872 {'include_dirs': [src_dir] + py_incl_dirs, | |
1873 'sources':bpl_srcs} | |
1874 )], | |
1875 'include_dirs': [src_dir], | |
1876 } | |
1877 if info: | |
1878 self.set_info(**info) | |
1879 return | |
1880 | |
1881 | |
1882 class agg2_info(system_info): | |
1883 section = 'agg2' | |
1884 dir_env_var = 'AGG2' | |
1885 | |
1886 def get_paths(self, section, key): | |
1887 pre_dirs = system_info.get_paths(self, section, key) | |
1888 dirs = [] | |
1889 for d in pre_dirs: | |
1890 dirs.extend([d] + self.combine_paths(d, ['agg2*'])) | |
1891 return [d for d in dirs if os.path.isdir(d)] | |
1892 | |
1893 def calc_info(self): | |
1894 src_dirs = self.get_src_dirs() | |
1895 src_dir = '' | |
1896 for d in src_dirs: | |
1897 if os.path.isfile(os.path.join(d, 'src', 'agg_affine_matrix.cpp')): | |
1898 src_dir = d | |
1899 break | |
1900 if not src_dir: | |
1901 return | |
1902 if sys.platform == 'win32': | |
1903 agg2_srcs = glob(os.path.join(src_dir, 'src', 'platform', | |
1904 'win32', 'agg_win32_bmp.cpp')) | |
1905 else: | |
1906 agg2_srcs = glob(os.path.join(src_dir, 'src', '*.cpp')) | |
1907 agg2_srcs += [os.path.join(src_dir, 'src', 'platform', | |
1908 'X11', | |
1909 'agg_platform_support.cpp')] | |
1910 | |
1911 info = {'libraries': | |
1912 [('agg2_src', | |
1913 {'sources': agg2_srcs, | |
1914 'include_dirs': [os.path.join(src_dir, 'include')], | |
1915 } | |
1916 )], | |
1917 'include_dirs': [os.path.join(src_dir, 'include')], | |
1918 } | |
1919 if info: | |
1920 self.set_info(**info) | |
1921 return | |
1922 | |
1923 | |
1924 class _pkg_config_info(system_info): | |
1925 section = None | |
1926 config_env_var = 'PKG_CONFIG' | |
1927 default_config_exe = 'pkg-config' | |
1928 append_config_exe = '' | |
1929 version_macro_name = None | |
1930 release_macro_name = None | |
1931 version_flag = '--modversion' | |
1932 cflags_flag = '--cflags' | |
1933 | |
1934 def get_config_exe(self): | |
1935 if self.config_env_var in os.environ: | |
1936 return os.environ[self.config_env_var] | |
1937 return self.default_config_exe | |
1938 | |
1939 def get_config_output(self, config_exe, option): | |
1940 cmd = config_exe + ' ' + self.append_config_exe + ' ' + option | |
1941 s, o = exec_command(cmd, use_tee=0) | |
1942 if not s: | |
1943 return o | |
1944 | |
1945 def calc_info(self): | |
1946 config_exe = find_executable(self.get_config_exe()) | |
1947 if not config_exe: | |
1948 log.warn('File not found: %s. Cannot determine %s info.' \ | |
1949 % (config_exe, self.section)) | |
1950 return | |
1951 info = {} | |
1952 macros = [] | |
1953 libraries = [] | |
1954 library_dirs = [] | |
1955 include_dirs = [] | |
1956 extra_link_args = [] | |
1957 extra_compile_args = [] | |
1958 version = self.get_config_output(config_exe, self.version_flag) | |
1959 if version: | |
1960 macros.append((self.__class__.__name__.split('.')[-1].upper(), | |
1961 '"\\"%s\\""' % (version))) | |
1962 if self.version_macro_name: | |
1963 macros.append((self.version_macro_name + '_%s' | |
1964 % (version.replace('.', '_')), None)) | |
1965 if self.release_macro_name: | |
1966 release = self.get_config_output(config_exe, '--release') | |
1967 if release: | |
1968 macros.append((self.release_macro_name + '_%s' | |
1969 % (release.replace('.', '_')), None)) | |
1970 opts = self.get_config_output(config_exe, '--libs') | |
1971 if opts: | |
1972 for opt in opts.split(): | |
1973 if opt[:2] == '-l': | |
1974 libraries.append(opt[2:]) | |
1975 elif opt[:2] == '-L': | |
1976 library_dirs.append(opt[2:]) | |
1977 else: | |
1978 extra_link_args.append(opt) | |
1979 opts = self.get_config_output(config_exe, self.cflags_flag) | |
1980 if opts: | |
1981 for opt in opts.split(): | |
1982 if opt[:2] == '-I': | |
1983 include_dirs.append(opt[2:]) | |
1984 elif opt[:2] == '-D': | |
1985 if '=' in opt: | |
1986 n, v = opt[2:].split('=') | |
1987 macros.append((n, v)) | |
1988 else: | |
1989 macros.append((opt[2:], None)) | |
1990 else: | |
1991 extra_compile_args.append(opt) | |
1992 if macros: | |
1993 dict_append(info, define_macros=macros) | |
1994 if libraries: | |
1995 dict_append(info, libraries=libraries) | |
1996 if library_dirs: | |
1997 dict_append(info, library_dirs=library_dirs) | |
1998 if include_dirs: | |
1999 dict_append(info, include_dirs=include_dirs) | |
2000 if extra_link_args: | |
2001 dict_append(info, extra_link_args=extra_link_args) | |
2002 if extra_compile_args: | |
2003 dict_append(info, extra_compile_args=extra_compile_args) | |
2004 if info: | |
2005 self.set_info(**info) | |
2006 return | |
2007 | |
2008 | |
2009 class wx_info(_pkg_config_info): | |
2010 section = 'wx' | |
2011 config_env_var = 'WX_CONFIG' | |
2012 default_config_exe = 'wx-config' | |
2013 append_config_exe = '' | |
2014 version_macro_name = 'WX_VERSION' | |
2015 release_macro_name = 'WX_RELEASE' | |
2016 version_flag = '--version' | |
2017 cflags_flag = '--cxxflags' | |
2018 | |
2019 | |
2020 class gdk_pixbuf_xlib_2_info(_pkg_config_info): | |
2021 section = 'gdk_pixbuf_xlib_2' | |
2022 append_config_exe = 'gdk-pixbuf-xlib-2.0' | |
2023 version_macro_name = 'GDK_PIXBUF_XLIB_VERSION' | |
2024 | |
2025 | |
2026 class gdk_pixbuf_2_info(_pkg_config_info): | |
2027 section = 'gdk_pixbuf_2' | |
2028 append_config_exe = 'gdk-pixbuf-2.0' | |
2029 version_macro_name = 'GDK_PIXBUF_VERSION' | |
2030 | |
2031 | |
2032 class gdk_x11_2_info(_pkg_config_info): | |
2033 section = 'gdk_x11_2' | |
2034 append_config_exe = 'gdk-x11-2.0' | |
2035 version_macro_name = 'GDK_X11_VERSION' | |
2036 | |
2037 | |
2038 class gdk_2_info(_pkg_config_info): | |
2039 section = 'gdk_2' | |
2040 append_config_exe = 'gdk-2.0' | |
2041 version_macro_name = 'GDK_VERSION' | |
2042 | |
2043 | |
2044 class gdk_info(_pkg_config_info): | |
2045 section = 'gdk' | |
2046 append_config_exe = 'gdk' | |
2047 version_macro_name = 'GDK_VERSION' | |
2048 | |
2049 | |
2050 class gtkp_x11_2_info(_pkg_config_info): | |
2051 section = 'gtkp_x11_2' | |
2052 append_config_exe = 'gtk+-x11-2.0' | |
2053 version_macro_name = 'GTK_X11_VERSION' | |
2054 | |
2055 | |
2056 class gtkp_2_info(_pkg_config_info): | |
2057 section = 'gtkp_2' | |
2058 append_config_exe = 'gtk+-2.0' | |
2059 version_macro_name = 'GTK_VERSION' | |
2060 | |
2061 | |
2062 class xft_info(_pkg_config_info): | |
2063 section = 'xft' | |
2064 append_config_exe = 'xft' | |
2065 version_macro_name = 'XFT_VERSION' | |
2066 | |
2067 | |
2068 class freetype2_info(_pkg_config_info): | |
2069 section = 'freetype2' | |
2070 append_config_exe = 'freetype2' | |
2071 version_macro_name = 'FREETYPE2_VERSION' | |
2072 | |
2073 | |
2074 class amd_info(system_info): | |
2075 section = 'amd' | |
2076 dir_env_var = 'AMD' | |
2077 _lib_names = ['amd'] | |
2078 | |
2079 def calc_info(self): | |
2080 lib_dirs = self.get_lib_dirs() | |
2081 | |
2082 amd_libs = self.get_libs('amd_libs', self._lib_names) | |
2083 info = self.check_libs(lib_dirs, amd_libs, []) | |
2084 if info is None: | |
2085 return | |
2086 | |
2087 include_dirs = self.get_include_dirs() | |
2088 | |
2089 inc_dir = None | |
2090 for d in include_dirs: | |
2091 p = self.combine_paths(d, 'amd.h') | |
2092 if p: | |
2093 inc_dir = os.path.dirname(p[0]) | |
2094 break | |
2095 if inc_dir is not None: | |
2096 dict_append(info, include_dirs=[inc_dir], | |
2097 define_macros=[('SCIPY_AMD_H', None)], | |
2098 swig_opts=['-I' + inc_dir]) | |
2099 | |
2100 self.set_info(**info) | |
2101 return | |
2102 | |
2103 | |
2104 class umfpack_info(system_info): | |
2105 section = 'umfpack' | |
2106 dir_env_var = 'UMFPACK' | |
2107 notfounderror = UmfpackNotFoundError | |
2108 _lib_names = ['umfpack'] | |
2109 | |
2110 def calc_info(self): | |
2111 lib_dirs = self.get_lib_dirs() | |
2112 | |
2113 umfpack_libs = self.get_libs('umfpack_libs', self._lib_names) | |
2114 info = self.check_libs(lib_dirs, umfpack_libs, []) | |
2115 if info is None: | |
2116 return | |
2117 | |
2118 include_dirs = self.get_include_dirs() | |
2119 | |
2120 inc_dir = None | |
2121 for d in include_dirs: | |
2122 p = self.combine_paths(d, ['', 'umfpack'], 'umfpack.h') | |
2123 if p: | |
2124 inc_dir = os.path.dirname(p[0]) | |
2125 break | |
2126 if inc_dir is not None: | |
2127 dict_append(info, include_dirs=[inc_dir], | |
2128 define_macros=[('SCIPY_UMFPACK_H', None)], | |
2129 swig_opts=['-I' + inc_dir]) | |
2130 | |
2131 amd = get_info('amd') | |
2132 dict_append(info, **get_info('amd')) | |
2133 | |
2134 self.set_info(**info) | |
2135 return | |
2136 | |
2137 ## def vstr2hex(version): | |
2138 ## bits = [] | |
2139 ## n = [24,16,8,4,0] | |
2140 ## r = 0 | |
2141 ## for s in version.split('.'): | |
2142 ## r |= int(s) << n[0] | |
2143 ## del n[0] | |
2144 ## return r | |
2145 | |
2146 #-------------------------------------------------------------------- | |
2147 | |
2148 | |
2149 def combine_paths(*args, **kws): | |
2150 """ Return a list of existing paths composed by all combinations of | |
2151 items from arguments. | |
2152 """ | |
2153 r = [] | |
2154 for a in args: | |
2155 if not a: | |
2156 continue | |
2157 if is_string(a): | |
2158 a = [a] | |
2159 r.append(a) | |
2160 args = r | |
2161 if not args: | |
2162 return [] | |
2163 if len(args) == 1: | |
2164 result = reduce(lambda a, b: a + b, map(glob, args[0]), []) | |
2165 elif len(args) == 2: | |
2166 result = [] | |
2167 for a0 in args[0]: | |
2168 for a1 in args[1]: | |
2169 result.extend(glob(os.path.join(a0, a1))) | |
2170 else: | |
2171 result = combine_paths(*(combine_paths(args[0], args[1]) + args[2:])) | |
2172 verbosity = kws.get('verbosity', 1) | |
2173 log.debug('(paths: %s)', ','.join(result)) | |
2174 return result | |
2175 | |
2176 language_map = {'c': 0, 'c++': 1, 'f77': 2, 'f90': 3} | |
2177 inv_language_map = {0: 'c', 1: 'c++', 2: 'f77', 3: 'f90'} | |
2178 | |
2179 | |
2180 def dict_append(d, **kws): | |
2181 languages = [] | |
2182 for k, v in kws.items(): | |
2183 if k == 'language': | |
2184 languages.append(v) | |
2185 continue | |
2186 if k in d: | |
2187 if k in ['library_dirs', 'include_dirs', 'define_macros']: | |
2188 [d[k].append(vv) for vv in v if vv not in d[k]] | |
2189 else: | |
2190 d[k].extend(v) | |
2191 else: | |
2192 d[k] = v | |
2193 if languages: | |
2194 l = inv_language_map[max([language_map.get(l, 0) for l in languages])] | |
2195 d['language'] = l | |
2196 return | |
2197 | |
2198 | |
2199 def parseCmdLine(argv=(None,)): | |
2200 import optparse | |
2201 parser = optparse.OptionParser("usage: %prog [-v] [info objs]") | |
2202 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', | |
2203 default=False, | |
2204 help='be verbose and print more messages') | |
2205 | |
2206 opts, args = parser.parse_args(args=argv[1:]) | |
2207 return opts, args | |
2208 | |
2209 | |
2210 def show_all(argv=None): | |
2211 import inspect | |
2212 if argv is None: | |
2213 argv = sys.argv | |
2214 opts, args = parseCmdLine(argv) | |
2215 if opts.verbose: | |
2216 log.set_threshold(log.DEBUG) | |
2217 else: | |
2218 log.set_threshold(log.INFO) | |
2219 show_only = [] | |
2220 for n in args: | |
2221 if n[-5:] != '_info': | |
2222 n = n + '_info' | |
2223 show_only.append(n) | |
2224 show_all = not show_only | |
2225 _gdict_ = globals().copy() | |
2226 for name, c in _gdict_.items(): | |
2227 if not inspect.isclass(c): | |
2228 continue | |
2229 if not issubclass(c, system_info) or c is system_info: | |
2230 continue | |
2231 if not show_all: | |
2232 if name not in show_only: | |
2233 continue | |
2234 del show_only[show_only.index(name)] | |
2235 conf = c() | |
2236 conf.verbosity = 2 | |
2237 r = conf.get_info() | |
2238 if show_only: | |
2239 log.info('Info classes not defined: %s', ','.join(show_only)) | |
2240 | |
2241 if __name__ == "__main__": | |
2242 show_all() |