123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556 |
- #!/usr/bin/env python
- """
- This file defines a set of system_info classes for getting
- information about various resources (libraries, library directories,
- include directories, etc.) in the system. Currently, the following
- classes are available:
- atlas_info
- atlas_threads_info
- atlas_blas_info
- atlas_blas_threads_info
- lapack_atlas_info
- lapack_atlas_threads_info
- atlas_3_10_info
- atlas_3_10_threads_info
- atlas_3_10_blas_info,
- atlas_3_10_blas_threads_info,
- lapack_atlas_3_10_info
- lapack_atlas_3_10_threads_info
- blas_info
- lapack_info
- openblas_info
- blis_info
- blas_opt_info # usage recommended
- lapack_opt_info # usage recommended
- fftw_info,dfftw_info,sfftw_info
- fftw_threads_info,dfftw_threads_info,sfftw_threads_info
- djbfft_info
- x11_info
- lapack_src_info
- blas_src_info
- numpy_info
- numarray_info
- numpy_info
- boost_python_info
- agg2_info
- wx_info
- gdk_pixbuf_xlib_2_info
- gdk_pixbuf_2_info
- gdk_x11_2_info
- gtkp_x11_2_info
- gtkp_2_info
- xft_info
- freetype2_info
- umfpack_info
- Usage:
- info_dict = get_info(<name>)
- where <name> is a string 'atlas','x11','fftw','lapack','blas',
- 'lapack_src', 'blas_src', etc. For a complete list of allowed names,
- see the definition of get_info() function below.
- Returned info_dict is a dictionary which is compatible with
- distutils.setup keyword arguments. If info_dict == {}, then the
- asked resource is not available (system_info could not find it).
- Several *_info classes specify an environment variable to specify
- the locations of software. When setting the corresponding environment
- variable to 'None' then the software will be ignored, even when it
- is available in system.
- Global parameters:
- system_info.search_static_first - search static libraries (.a)
- in precedence to shared ones (.so, .sl) if enabled.
- system_info.verbosity - output the results to stdout if enabled.
- The file 'site.cfg' is looked for in
- 1) Directory of main setup.py file being run.
- 2) Home directory of user running the setup.py file as ~/.numpy-site.cfg
- 3) System wide directory (location of this file...)
- The first one found is used to get system configuration options The
- format is that used by ConfigParser (i.e., Windows .INI style). The
- section ALL has options that are the default for each section. The
- available sections are fftw, atlas, and x11. Appropriate defaults are
- used if nothing is specified.
- The order of finding the locations of resources is the following:
- 1. environment variable
- 2. section in site.cfg
- 3. ALL section in site.cfg
- Only the first complete match is returned.
- Example:
- ----------
- [ALL]
- library_dirs = /usr/lib:/usr/local/lib:/opt/lib
- include_dirs = /usr/include:/usr/local/include:/opt/include
- src_dirs = /usr/local/src:/opt/src
- # search static libraries (.a) in preference to shared ones (.so)
- search_static_first = 0
- [fftw]
- fftw_libs = rfftw, fftw
- fftw_opt_libs = rfftw_threaded, fftw_threaded
- # if the above aren't found, look for {s,d}fftw_libs and {s,d}fftw_opt_libs
- [atlas]
- library_dirs = /usr/lib/3dnow:/usr/lib/3dnow/atlas
- # for overriding the names of the atlas libraries
- atlas_libs = lapack, f77blas, cblas, atlas
- [x11]
- library_dirs = /usr/X11R6/lib
- include_dirs = /usr/X11R6/include
- ----------
- Authors:
- Pearu Peterson <pearu@cens.ioc.ee>, February 2002
- David M. Cooke <cookedm@physics.mcmaster.ca>, April 2002
- Copyright 2002 Pearu Peterson all rights reserved,
- Pearu Peterson <pearu@cens.ioc.ee>
- Permission to use, modify, and distribute this software is given under the
- terms of the NumPy (BSD style) license. See LICENSE.txt that came with
- this distribution for specifics.
- NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
- """
- from __future__ import division, absolute_import, print_function
- import sys
- import os
- import re
- import copy
- import warnings
- import subprocess
- from glob import glob
- from functools import reduce
- if sys.version_info[0] < 3:
- from ConfigParser import NoOptionError
- from ConfigParser import RawConfigParser as ConfigParser
- else:
- from configparser import NoOptionError
- from configparser import RawConfigParser as ConfigParser
- # It seems that some people are importing ConfigParser from here so is
- # good to keep its class name. Use of RawConfigParser is needed in
- # order to be able to load path names with percent in them, like
- # `feature%2Fcool` which is common on git flow branch names.
- from distutils.errors import DistutilsError
- from distutils.dist import Distribution
- import distutils.sysconfig
- from distutils import log
- from distutils.util import get_platform
- from numpy.distutils.exec_command import (
- find_executable, filepath_from_subprocess_output,
- get_pythonexe)
- from numpy.distutils.misc_util import (is_sequence, is_string,
- get_shared_lib_extension)
- from numpy.distutils.command.config import config as cmd_config
- from numpy.distutils.compat import get_exception
- from numpy.distutils import customized_ccompiler
- from numpy.distutils import _shell_utils
- import distutils.ccompiler
- import tempfile
- import shutil
- # Determine number of bits
- import platform
- _bits = {'32bit': 32, '64bit': 64}
- platform_bits = _bits[platform.architecture()[0]]
- def _c_string_literal(s):
- """
- Convert a python string into a literal suitable for inclusion into C code
- """
- # only these three characters are forbidden in C strings
- s = s.replace('\\', r'\\')
- s = s.replace('"', r'\"')
- s = s.replace('\n', r'\n')
- return '"{}"'.format(s)
- def libpaths(paths, bits):
- """Return a list of library paths valid on 32 or 64 bit systems.
- Inputs:
- paths : sequence
- A sequence of strings (typically paths)
- bits : int
- An integer, the only valid values are 32 or 64. A ValueError exception
- is raised otherwise.
- Examples:
- Consider a list of directories
- >>> paths = ['/usr/X11R6/lib','/usr/X11/lib','/usr/lib']
- For a 32-bit platform, this is already valid:
- >>> np.distutils.system_info.libpaths(paths,32)
- ['/usr/X11R6/lib', '/usr/X11/lib', '/usr/lib']
- On 64 bits, we prepend the '64' postfix
- >>> np.distutils.system_info.libpaths(paths,64)
- ['/usr/X11R6/lib64', '/usr/X11R6/lib', '/usr/X11/lib64', '/usr/X11/lib',
- '/usr/lib64', '/usr/lib']
- """
- if bits not in (32, 64):
- raise ValueError("Invalid bit size in libpaths: 32 or 64 only")
- # Handle 32bit case
- if bits == 32:
- return paths
- # Handle 64bit case
- out = []
- for p in paths:
- out.extend([p + '64', p])
- return out
- if sys.platform == 'win32':
- default_lib_dirs = ['C:\\',
- os.path.join(distutils.sysconfig.EXEC_PREFIX,
- 'libs')]
- default_runtime_dirs = []
- default_include_dirs = []
- default_src_dirs = ['.']
- default_x11_lib_dirs = []
- default_x11_include_dirs = []
- _include_dirs = [
- 'include',
- 'include/suitesparse',
- ]
- _lib_dirs = [
- 'lib',
- ]
- _include_dirs = [d.replace('/', os.sep) for d in _include_dirs]
- _lib_dirs = [d.replace('/', os.sep) for d in _lib_dirs]
- def add_system_root(library_root):
- """Add a package manager root to the include directories"""
- global default_lib_dirs
- global default_include_dirs
- library_root = os.path.normpath(library_root)
- default_lib_dirs.extend(
- os.path.join(library_root, d) for d in _lib_dirs)
- default_include_dirs.extend(
- os.path.join(library_root, d) for d in _include_dirs)
- if sys.version_info >= (3, 3):
- # VCpkg is the de-facto package manager on windows for C/C++
- # libraries. If it is on the PATH, then we append its paths here.
- # We also don't re-implement shutil.which for Python 2.7 because
- # vcpkg doesn't support MSVC 2008.
- vcpkg = shutil.which('vcpkg')
- if vcpkg:
- vcpkg_dir = os.path.dirname(vcpkg)
- if platform.architecture() == '32bit':
- specifier = 'x86'
- else:
- specifier = 'x64'
- vcpkg_installed = os.path.join(vcpkg_dir, 'installed')
- for vcpkg_root in [
- os.path.join(vcpkg_installed, specifier + '-windows'),
- os.path.join(vcpkg_installed, specifier + '-windows-static'),
- ]:
- add_system_root(vcpkg_root)
- # Conda is another popular package manager that provides libraries
- conda = shutil.which('conda')
- if conda:
- conda_dir = os.path.dirname(conda)
- add_system_root(os.path.join(conda_dir, '..', 'Library'))
- add_system_root(os.path.join(conda_dir, 'Library'))
- else:
- default_lib_dirs = libpaths(['/usr/local/lib', '/opt/lib', '/usr/lib',
- '/opt/local/lib', '/sw/lib'], platform_bits)
- default_runtime_dirs = []
- default_include_dirs = ['/usr/local/include',
- '/opt/include', '/usr/include',
- # path of umfpack under macports
- '/opt/local/include/ufsparse',
- '/opt/local/include', '/sw/include',
- '/usr/include/suitesparse']
- default_src_dirs = ['.', '/usr/local/src', '/opt/src', '/sw/src']
- default_x11_lib_dirs = libpaths(['/usr/X11R6/lib', '/usr/X11/lib',
- '/usr/lib'], platform_bits)
- default_x11_include_dirs = ['/usr/X11R6/include', '/usr/X11/include',
- '/usr/include']
- if os.path.exists('/usr/lib/X11'):
- globbed_x11_dir = glob('/usr/lib/*/libX11.so')
- if globbed_x11_dir:
- x11_so_dir = os.path.split(globbed_x11_dir[0])[0]
- default_x11_lib_dirs.extend([x11_so_dir, '/usr/lib/X11'])
- default_x11_include_dirs.extend(['/usr/lib/X11/include',
- '/usr/include/X11'])
- tmp = None
- try:
- # Explicitly open/close file to avoid ResourceWarning when
- # tests are run in debug mode Python 3.
- tmp = open(os.devnull, 'w')
- p = subprocess.Popen(["gcc", "-print-multiarch"], stdout=subprocess.PIPE,
- stderr=tmp)
- except (OSError, DistutilsError):
- # OSError if gcc is not installed, or SandboxViolation (DistutilsError
- # subclass) if an old setuptools bug is triggered (see gh-3160).
- pass
- else:
- triplet = str(p.communicate()[0].decode().strip())
- if p.returncode == 0:
- # gcc supports the "-print-multiarch" option
- default_x11_lib_dirs += [os.path.join("/usr/lib/", triplet)]
- default_lib_dirs += [os.path.join("/usr/lib/", triplet)]
- finally:
- if tmp is not None:
- tmp.close()
- if os.path.join(sys.prefix, 'lib') not in default_lib_dirs:
- default_lib_dirs.insert(0, os.path.join(sys.prefix, 'lib'))
- default_include_dirs.append(os.path.join(sys.prefix, 'include'))
- default_src_dirs.append(os.path.join(sys.prefix, 'src'))
- default_lib_dirs = [_m for _m in default_lib_dirs if os.path.isdir(_m)]
- default_runtime_dirs = [_m for _m in default_runtime_dirs if os.path.isdir(_m)]
- default_include_dirs = [_m for _m in default_include_dirs if os.path.isdir(_m)]
- default_src_dirs = [_m for _m in default_src_dirs if os.path.isdir(_m)]
- so_ext = get_shared_lib_extension()
- def get_standard_file(fname):
- """Returns a list of files named 'fname' from
- 1) System-wide directory (directory-location of this module)
- 2) Users HOME directory (os.environ['HOME'])
- 3) Local directory
- """
- # System-wide file
- filenames = []
- try:
- f = __file__
- except NameError:
- f = sys.argv[0]
- else:
- sysfile = os.path.join(os.path.split(os.path.abspath(f))[0],
- fname)
- if os.path.isfile(sysfile):
- filenames.append(sysfile)
- # Home directory
- # And look for the user config file
- try:
- f = os.path.expanduser('~')
- except KeyError:
- pass
- else:
- user_file = os.path.join(f, fname)
- if os.path.isfile(user_file):
- filenames.append(user_file)
- # Local file
- if os.path.isfile(fname):
- filenames.append(os.path.abspath(fname))
- return filenames
- def get_info(name, notfound_action=0):
- """
- notfound_action:
- 0 - do nothing
- 1 - display warning message
- 2 - raise error
- """
- cl = {'atlas': atlas_info, # use lapack_opt or blas_opt instead
- 'atlas_threads': atlas_threads_info, # ditto
- 'atlas_blas': atlas_blas_info,
- 'atlas_blas_threads': atlas_blas_threads_info,
- 'lapack_atlas': lapack_atlas_info, # use lapack_opt instead
- 'lapack_atlas_threads': lapack_atlas_threads_info, # ditto
- 'atlas_3_10': atlas_3_10_info, # use lapack_opt or blas_opt instead
- 'atlas_3_10_threads': atlas_3_10_threads_info, # ditto
- 'atlas_3_10_blas': atlas_3_10_blas_info,
- 'atlas_3_10_blas_threads': atlas_3_10_blas_threads_info,
- 'lapack_atlas_3_10': lapack_atlas_3_10_info, # use lapack_opt instead
- 'lapack_atlas_3_10_threads': lapack_atlas_3_10_threads_info, # ditto
- 'mkl': mkl_info,
- # openblas which may or may not have embedded lapack
- 'openblas': openblas_info, # use blas_opt instead
- # openblas with embedded lapack
- 'openblas_lapack': openblas_lapack_info, # use blas_opt instead
- 'openblas_clapack': openblas_clapack_info, # use blas_opt instead
- 'blis': blis_info, # use blas_opt instead
- 'lapack_mkl': lapack_mkl_info, # use lapack_opt instead
- 'blas_mkl': blas_mkl_info, # use blas_opt instead
- 'accelerate': accelerate_info, # use blas_opt instead
- 'x11': x11_info,
- 'fft_opt': fft_opt_info,
- 'fftw': fftw_info,
- 'fftw2': fftw2_info,
- 'fftw3': fftw3_info,
- 'dfftw': dfftw_info,
- 'sfftw': sfftw_info,
- 'fftw_threads': fftw_threads_info,
- 'dfftw_threads': dfftw_threads_info,
- 'sfftw_threads': sfftw_threads_info,
- 'djbfft': djbfft_info,
- 'blas': blas_info, # use blas_opt instead
- 'lapack': lapack_info, # use lapack_opt instead
- 'lapack_src': lapack_src_info,
- 'blas_src': blas_src_info,
- 'numpy': numpy_info,
- 'f2py': f2py_info,
- 'Numeric': Numeric_info,
- 'numeric': Numeric_info,
- 'numarray': numarray_info,
- 'numerix': numerix_info,
- 'lapack_opt': lapack_opt_info,
- 'blas_opt': blas_opt_info,
- 'boost_python': boost_python_info,
- 'agg2': agg2_info,
- 'wx': wx_info,
- 'gdk_pixbuf_xlib_2': gdk_pixbuf_xlib_2_info,
- 'gdk-pixbuf-xlib-2.0': gdk_pixbuf_xlib_2_info,
- 'gdk_pixbuf_2': gdk_pixbuf_2_info,
- 'gdk-pixbuf-2.0': gdk_pixbuf_2_info,
- 'gdk': gdk_info,
- 'gdk_2': gdk_2_info,
- 'gdk-2.0': gdk_2_info,
- 'gdk_x11_2': gdk_x11_2_info,
- 'gdk-x11-2.0': gdk_x11_2_info,
- 'gtkp_x11_2': gtkp_x11_2_info,
- 'gtk+-x11-2.0': gtkp_x11_2_info,
- 'gtkp_2': gtkp_2_info,
- 'gtk+-2.0': gtkp_2_info,
- 'xft': xft_info,
- 'freetype2': freetype2_info,
- 'umfpack': umfpack_info,
- 'amd': amd_info,
- }.get(name.lower(), system_info)
- return cl().get_info(notfound_action)
- class NotFoundError(DistutilsError):
- """Some third-party program or library is not found."""
- class AtlasNotFoundError(NotFoundError):
- """
- Atlas (http://math-atlas.sourceforge.net/) libraries not found.
- Directories to search for the libraries can be specified in the
- numpy/distutils/site.cfg file (section [atlas]) or by setting
- the ATLAS environment variable."""
- class LapackNotFoundError(NotFoundError):
- """
- Lapack (http://www.netlib.org/lapack/) libraries not found.
- Directories to search for the libraries can be specified in the
- numpy/distutils/site.cfg file (section [lapack]) or by setting
- the LAPACK environment variable."""
- class LapackSrcNotFoundError(LapackNotFoundError):
- """
- Lapack (http://www.netlib.org/lapack/) sources not found.
- Directories to search for the sources can be specified in the
- numpy/distutils/site.cfg file (section [lapack_src]) or by setting
- the LAPACK_SRC environment variable."""
- class BlasNotFoundError(NotFoundError):
- """
- Blas (http://www.netlib.org/blas/) libraries not found.
- Directories to search for the libraries can be specified in the
- numpy/distutils/site.cfg file (section [blas]) or by setting
- the BLAS environment variable."""
- class BlasSrcNotFoundError(BlasNotFoundError):
- """
- Blas (http://www.netlib.org/blas/) sources not found.
- Directories to search for the sources can be specified in the
- numpy/distutils/site.cfg file (section [blas_src]) or by setting
- the BLAS_SRC environment variable."""
- class FFTWNotFoundError(NotFoundError):
- """
- FFTW (http://www.fftw.org/) libraries not found.
- Directories to search for the libraries can be specified in the
- numpy/distutils/site.cfg file (section [fftw]) or by setting
- the FFTW environment variable."""
- class DJBFFTNotFoundError(NotFoundError):
- """
- DJBFFT (https://cr.yp.to/djbfft.html) libraries not found.
- Directories to search for the libraries can be specified in the
- numpy/distutils/site.cfg file (section [djbfft]) or by setting
- the DJBFFT environment variable."""
- class NumericNotFoundError(NotFoundError):
- """
- Numeric (https://www.numpy.org/) module not found.
- Get it from above location, install it, and retry setup.py."""
- class X11NotFoundError(NotFoundError):
- """X11 libraries not found."""
- class UmfpackNotFoundError(NotFoundError):
- """
- UMFPACK sparse solver (https://www.cise.ufl.edu/research/sparse/umfpack/)
- not found. Directories to search for the libraries can be specified in the
- numpy/distutils/site.cfg file (section [umfpack]) or by setting
- the UMFPACK environment variable."""
- class system_info(object):
- """ get_info() is the only public method. Don't use others.
- """
- section = 'ALL'
- dir_env_var = None
- search_static_first = 0 # XXX: disabled by default, may disappear in
- # future unless it is proved to be useful.
- verbosity = 1
- saved_results = {}
- notfounderror = NotFoundError
- def __init__(self,
- default_lib_dirs=default_lib_dirs,
- default_include_dirs=default_include_dirs,
- verbosity=1,
- ):
- self.__class__.info = {}
- self.local_prefixes = []
- defaults = {'library_dirs': os.pathsep.join(default_lib_dirs),
- 'include_dirs': os.pathsep.join(default_include_dirs),
- 'runtime_library_dirs': os.pathsep.join(default_runtime_dirs),
- 'rpath': '',
- 'src_dirs': os.pathsep.join(default_src_dirs),
- 'search_static_first': str(self.search_static_first),
- 'extra_compile_args': '', 'extra_link_args': ''}
- self.cp = ConfigParser(defaults)
- self.files = []
- self.files.extend(get_standard_file('.numpy-site.cfg'))
- self.files.extend(get_standard_file('site.cfg'))
- self.parse_config_files()
- if self.section is not None:
- self.search_static_first = self.cp.getboolean(
- self.section, 'search_static_first')
- assert isinstance(self.search_static_first, int)
- def parse_config_files(self):
- self.cp.read(self.files)
- if not self.cp.has_section(self.section):
- if self.section is not None:
- self.cp.add_section(self.section)
- def calc_libraries_info(self):
- libs = self.get_libraries()
- dirs = self.get_lib_dirs()
- # The extensions use runtime_library_dirs
- r_dirs = self.get_runtime_lib_dirs()
- # Intrinsic distutils use rpath, we simply append both entries
- # as though they were one entry
- r_dirs.extend(self.get_runtime_lib_dirs(key='rpath'))
- info = {}
- for lib in libs:
- i = self.check_libs(dirs, [lib])
- if i is not None:
- dict_append(info, **i)
- else:
- log.info('Library %s was not found. Ignoring' % (lib))
- if r_dirs:
- i = self.check_libs(r_dirs, [lib])
- if i is not None:
- # Swap library keywords found to runtime_library_dirs
- # the libraries are insisting on the user having defined
- # them using the library_dirs, and not necessarily by
- # runtime_library_dirs
- del i['libraries']
- i['runtime_library_dirs'] = i.pop('library_dirs')
- dict_append(info, **i)
- else:
- log.info('Runtime library %s was not found. Ignoring' % (lib))
- return info
- def set_info(self, **info):
- if info:
- lib_info = self.calc_libraries_info()
- dict_append(info, **lib_info)
- # Update extra information
- extra_info = self.calc_extra_info()
- dict_append(info, **extra_info)
- self.saved_results[self.__class__.__name__] = info
- def has_info(self):
- return self.__class__.__name__ in self.saved_results
- def calc_extra_info(self):
- """ Updates the information in the current information with
- respect to these flags:
- extra_compile_args
- extra_link_args
- """
- info = {}
- for key in ['extra_compile_args', 'extra_link_args']:
- # Get values
- opt = self.cp.get(self.section, key)
- opt = _shell_utils.NativeParser.split(opt)
- if opt:
- tmp = {key: opt}
- dict_append(info, **tmp)
- return info
- def get_info(self, notfound_action=0):
- """ Return a dictonary with items that are compatible
- with numpy.distutils.setup keyword arguments.
- """
- flag = 0
- if not self.has_info():
- flag = 1
- log.info(self.__class__.__name__ + ':')
- if hasattr(self, 'calc_info'):
- self.calc_info()
- if notfound_action:
- if not self.has_info():
- if notfound_action == 1:
- warnings.warn(self.notfounderror.__doc__, stacklevel=2)
- elif notfound_action == 2:
- raise self.notfounderror(self.notfounderror.__doc__)
- else:
- raise ValueError(repr(notfound_action))
- if not self.has_info():
- log.info(' NOT AVAILABLE')
- self.set_info()
- else:
- log.info(' FOUND:')
- res = self.saved_results.get(self.__class__.__name__)
- if self.verbosity > 0 and flag:
- for k, v in res.items():
- v = str(v)
- if k in ['sources', 'libraries'] and len(v) > 270:
- v = v[:120] + '...\n...\n...' + v[-120:]
- log.info(' %s = %s', k, v)
- log.info('')
- return copy.deepcopy(res)
- def get_paths(self, section, key):
- dirs = self.cp.get(section, key).split(os.pathsep)
- env_var = self.dir_env_var
- if env_var:
- if is_sequence(env_var):
- e0 = env_var[-1]
- for e in env_var:
- if e in os.environ:
- e0 = e
- break
- if not env_var[0] == e0:
- log.info('Setting %s=%s' % (env_var[0], e0))
- env_var = e0
- if env_var and env_var in os.environ:
- d = os.environ[env_var]
- if d == 'None':
- log.info('Disabled %s: %s',
- self.__class__.__name__, '(%s is None)'
- % (env_var,))
- return []
- if os.path.isfile(d):
- dirs = [os.path.dirname(d)] + dirs
- l = getattr(self, '_lib_names', [])
- if len(l) == 1:
- b = os.path.basename(d)
- b = os.path.splitext(b)[0]
- if b[:3] == 'lib':
- log.info('Replacing _lib_names[0]==%r with %r' \
- % (self._lib_names[0], b[3:]))
- self._lib_names[0] = b[3:]
- else:
- ds = d.split(os.pathsep)
- ds2 = []
- for d in ds:
- if os.path.isdir(d):
- ds2.append(d)
- for dd in ['include', 'lib']:
- d1 = os.path.join(d, dd)
- if os.path.isdir(d1):
- ds2.append(d1)
- dirs = ds2 + dirs
- default_dirs = self.cp.get(self.section, key).split(os.pathsep)
- dirs.extend(default_dirs)
- ret = []
- for d in dirs:
- if len(d) > 0 and not os.path.isdir(d):
- warnings.warn('Specified path %s is invalid.' % d, stacklevel=2)
- continue
- if d not in ret:
- ret.append(d)
- log.debug('( %s = %s )', key, ':'.join(ret))
- return ret
- def get_lib_dirs(self, key='library_dirs'):
- return self.get_paths(self.section, key)
- def get_runtime_lib_dirs(self, key='runtime_library_dirs'):
- path = self.get_paths(self.section, key)
- if path == ['']:
- path = []
- return path
- def get_include_dirs(self, key='include_dirs'):
- return self.get_paths(self.section, key)
- def get_src_dirs(self, key='src_dirs'):
- return self.get_paths(self.section, key)
- def get_libs(self, key, default):
- try:
- libs = self.cp.get(self.section, key)
- except NoOptionError:
- if not default:
- return []
- if is_string(default):
- return [default]
- return default
- return [b for b in [a.strip() for a in libs.split(',')] if b]
- def get_libraries(self, key='libraries'):
- if hasattr(self, '_lib_names'):
- return self.get_libs(key, default=self._lib_names)
- else:
- return self.get_libs(key, '')
- def library_extensions(self):
- c = customized_ccompiler()
- static_exts = []
- if c.compiler_type != 'msvc':
- # MSVC doesn't understand binutils
- static_exts.append('.a')
- if sys.platform == 'win32':
- static_exts.append('.lib') # .lib is used by MSVC and others
- if self.search_static_first:
- exts = static_exts + [so_ext]
- else:
- exts = [so_ext] + static_exts
- if sys.platform == 'cygwin':
- exts.append('.dll.a')
- if sys.platform == 'darwin':
- exts.append('.dylib')
- return exts
- def check_libs(self, lib_dirs, libs, opt_libs=[]):
- """If static or shared libraries are available then return
- their info dictionary.
- Checks for all libraries as shared libraries first, then
- static (or vice versa if self.search_static_first is True).
- """
- exts = self.library_extensions()
- info = None
- for ext in exts:
- info = self._check_libs(lib_dirs, libs, opt_libs, [ext])
- if info is not None:
- break
- if not info:
- log.info(' libraries %s not found in %s', ','.join(libs),
- lib_dirs)
- return info
- def check_libs2(self, lib_dirs, libs, opt_libs=[]):
- """If static or shared libraries are available then return
- their info dictionary.
- Checks each library for shared or static.
- """
- exts = self.library_extensions()
- info = self._check_libs(lib_dirs, libs, opt_libs, exts)
- if not info:
- log.info(' libraries %s not found in %s', ','.join(libs),
- lib_dirs)
- return info
- def _find_lib(self, lib_dir, lib, exts):
- assert is_string(lib_dir)
- # under windows first try without 'lib' prefix
- if sys.platform == 'win32':
- lib_prefixes = ['', 'lib']
- else:
- lib_prefixes = ['lib']
- # for each library name, see if we can find a file for it.
- for ext in exts:
- for prefix in lib_prefixes:
- p = self.combine_paths(lib_dir, prefix + lib + ext)
- if p:
- break
- if p:
- assert len(p) == 1
- # ??? splitext on p[0] would do this for cygwin
- # doesn't seem correct
- if ext == '.dll.a':
- lib += '.dll'
- if ext == '.lib':
- lib = prefix + lib
- return lib
- return False
- def _find_libs(self, lib_dirs, libs, exts):
- # make sure we preserve the order of libs, as it can be important
- found_dirs, found_libs = [], []
- for lib in libs:
- for lib_dir in lib_dirs:
- found_lib = self._find_lib(lib_dir, lib, exts)
- if found_lib:
- found_libs.append(found_lib)
- if lib_dir not in found_dirs:
- found_dirs.append(lib_dir)
- break
- return found_dirs, found_libs
- def _check_libs(self, lib_dirs, libs, opt_libs, exts):
- """Find mandatory and optional libs in expected paths.
- Missing optional libraries are silently forgotten.
- """
- if not is_sequence(lib_dirs):
- lib_dirs = [lib_dirs]
- # First, try to find the mandatory libraries
- found_dirs, found_libs = self._find_libs(lib_dirs, libs, exts)
- if len(found_libs) > 0 and len(found_libs) == len(libs):
- # Now, check for optional libraries
- opt_found_dirs, opt_found_libs = self._find_libs(lib_dirs, opt_libs, exts)
- found_libs.extend(opt_found_libs)
- for lib_dir in opt_found_dirs:
- if lib_dir not in found_dirs:
- found_dirs.append(lib_dir)
- info = {'libraries': found_libs, 'library_dirs': found_dirs}
- return info
- else:
- return None
- def combine_paths(self, *args):
- """Return a list of existing paths composed by all combinations
- of items from the arguments.
- """
- return combine_paths(*args, **{'verbosity': self.verbosity})
- class fft_opt_info(system_info):
- def calc_info(self):
- info = {}
- fftw_info = get_info('fftw3') or get_info('fftw2') or get_info('dfftw')
- djbfft_info = get_info('djbfft')
- if fftw_info:
- dict_append(info, **fftw_info)
- if djbfft_info:
- dict_append(info, **djbfft_info)
- self.set_info(**info)
- return
- class fftw_info(system_info):
- #variables to override
- section = 'fftw'
- dir_env_var = 'FFTW'
- notfounderror = FFTWNotFoundError
- ver_info = [{'name':'fftw3',
- 'libs':['fftw3'],
- 'includes':['fftw3.h'],
- 'macros':[('SCIPY_FFTW3_H', None)]},
- {'name':'fftw2',
- 'libs':['rfftw', 'fftw'],
- 'includes':['fftw.h', 'rfftw.h'],
- 'macros':[('SCIPY_FFTW_H', None)]}]
- def calc_ver_info(self, ver_param):
- """Returns True on successful version detection, else False"""
- lib_dirs = self.get_lib_dirs()
- incl_dirs = self.get_include_dirs()
- libs = self.get_libs(self.section + '_libs', ver_param['libs'])
- info = self.check_libs(lib_dirs, libs)
- if info is not None:
- flag = 0
- for d in incl_dirs:
- if len(self.combine_paths(d, ver_param['includes'])) \
- == len(ver_param['includes']):
- dict_append(info, include_dirs=[d])
- flag = 1
- incl_dirs = [d]
- break
- if flag:
- dict_append(info, define_macros=ver_param['macros'])
- else:
- info = None
- if info is not None:
- self.set_info(**info)
- return True
- else:
- log.info(' %s not found' % (ver_param['name']))
- return False
- def calc_info(self):
- for i in self.ver_info:
- if self.calc_ver_info(i):
- break
- class fftw2_info(fftw_info):
- #variables to override
- section = 'fftw'
- dir_env_var = 'FFTW'
- notfounderror = FFTWNotFoundError
- ver_info = [{'name':'fftw2',
- 'libs':['rfftw', 'fftw'],
- 'includes':['fftw.h', 'rfftw.h'],
- 'macros':[('SCIPY_FFTW_H', None)]}
- ]
- class fftw3_info(fftw_info):
- #variables to override
- section = 'fftw3'
- dir_env_var = 'FFTW3'
- notfounderror = FFTWNotFoundError
- ver_info = [{'name':'fftw3',
- 'libs':['fftw3'],
- 'includes':['fftw3.h'],
- 'macros':[('SCIPY_FFTW3_H', None)]},
- ]
- class dfftw_info(fftw_info):
- section = 'fftw'
- dir_env_var = 'FFTW'
- ver_info = [{'name':'dfftw',
- 'libs':['drfftw', 'dfftw'],
- 'includes':['dfftw.h', 'drfftw.h'],
- 'macros':[('SCIPY_DFFTW_H', None)]}]
- class sfftw_info(fftw_info):
- section = 'fftw'
- dir_env_var = 'FFTW'
- ver_info = [{'name':'sfftw',
- 'libs':['srfftw', 'sfftw'],
- 'includes':['sfftw.h', 'srfftw.h'],
- 'macros':[('SCIPY_SFFTW_H', None)]}]
- class fftw_threads_info(fftw_info):
- section = 'fftw'
- dir_env_var = 'FFTW'
- ver_info = [{'name':'fftw threads',
- 'libs':['rfftw_threads', 'fftw_threads'],
- 'includes':['fftw_threads.h', 'rfftw_threads.h'],
- 'macros':[('SCIPY_FFTW_THREADS_H', None)]}]
- class dfftw_threads_info(fftw_info):
- section = 'fftw'
- dir_env_var = 'FFTW'
- ver_info = [{'name':'dfftw threads',
- 'libs':['drfftw_threads', 'dfftw_threads'],
- 'includes':['dfftw_threads.h', 'drfftw_threads.h'],
- 'macros':[('SCIPY_DFFTW_THREADS_H', None)]}]
- class sfftw_threads_info(fftw_info):
- section = 'fftw'
- dir_env_var = 'FFTW'
- ver_info = [{'name':'sfftw threads',
- 'libs':['srfftw_threads', 'sfftw_threads'],
- 'includes':['sfftw_threads.h', 'srfftw_threads.h'],
- 'macros':[('SCIPY_SFFTW_THREADS_H', None)]}]
- class djbfft_info(system_info):
- section = 'djbfft'
- dir_env_var = 'DJBFFT'
- notfounderror = DJBFFTNotFoundError
- def get_paths(self, section, key):
- pre_dirs = system_info.get_paths(self, section, key)
- dirs = []
- for d in pre_dirs:
- dirs.extend(self.combine_paths(d, ['djbfft']) + [d])
- return [d for d in dirs if os.path.isdir(d)]
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- incl_dirs = self.get_include_dirs()
- info = None
- for d in lib_dirs:
- p = self.combine_paths(d, ['djbfft.a'])
- if p:
- info = {'extra_objects': p}
- break
- p = self.combine_paths(d, ['libdjbfft.a', 'libdjbfft' + so_ext])
- if p:
- info = {'libraries': ['djbfft'], 'library_dirs': [d]}
- break
- if info is None:
- return
- for d in incl_dirs:
- if len(self.combine_paths(d, ['fftc8.h', 'fftfreq.h'])) == 2:
- dict_append(info, include_dirs=[d],
- define_macros=[('SCIPY_DJBFFT_H', None)])
- self.set_info(**info)
- return
- return
- class mkl_info(system_info):
- section = 'mkl'
- dir_env_var = 'MKLROOT'
- _lib_mkl = ['mkl_rt']
- def get_mkl_rootdir(self):
- mklroot = os.environ.get('MKLROOT', None)
- if mklroot is not None:
- return mklroot
- paths = os.environ.get('LD_LIBRARY_PATH', '').split(os.pathsep)
- ld_so_conf = '/etc/ld.so.conf'
- if os.path.isfile(ld_so_conf):
- with open(ld_so_conf, 'r') as f:
- for d in f:
- d = d.strip()
- if d:
- paths.append(d)
- intel_mkl_dirs = []
- for path in paths:
- path_atoms = path.split(os.sep)
- for m in path_atoms:
- if m.startswith('mkl'):
- d = os.sep.join(path_atoms[:path_atoms.index(m) + 2])
- intel_mkl_dirs.append(d)
- break
- for d in paths:
- dirs = glob(os.path.join(d, 'mkl', '*'))
- dirs += glob(os.path.join(d, 'mkl*'))
- for d in dirs:
- if os.path.isdir(os.path.join(d, 'lib')):
- return d
- return None
- def __init__(self):
- mklroot = self.get_mkl_rootdir()
- if mklroot is None:
- system_info.__init__(self)
- else:
- from .cpuinfo import cpu
- if cpu.is_Itanium():
- plt = '64'
- elif cpu.is_Intel() and cpu.is_64bit():
- plt = 'intel64'
- else:
- plt = '32'
- system_info.__init__(
- self,
- default_lib_dirs=[os.path.join(mklroot, 'lib', plt)],
- default_include_dirs=[os.path.join(mklroot, 'include')])
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- incl_dirs = self.get_include_dirs()
- mkl_libs = self.get_libs('mkl_libs', self._lib_mkl)
- info = self.check_libs2(lib_dirs, mkl_libs)
- if info is None:
- return
- dict_append(info,
- define_macros=[('SCIPY_MKL_H', None),
- ('HAVE_CBLAS', None)],
- include_dirs=incl_dirs)
- if sys.platform == 'win32':
- pass # win32 has no pthread library
- else:
- dict_append(info, libraries=['pthread'])
- self.set_info(**info)
- class lapack_mkl_info(mkl_info):
- pass
- class blas_mkl_info(mkl_info):
- pass
- class atlas_info(system_info):
- section = 'atlas'
- dir_env_var = 'ATLAS'
- _lib_names = ['f77blas', 'cblas']
- if sys.platform[:7] == 'freebsd':
- _lib_atlas = ['atlas_r']
- _lib_lapack = ['alapack_r']
- else:
- _lib_atlas = ['atlas']
- _lib_lapack = ['lapack']
- notfounderror = AtlasNotFoundError
- def get_paths(self, section, key):
- pre_dirs = system_info.get_paths(self, section, key)
- dirs = []
- for d in pre_dirs:
- dirs.extend(self.combine_paths(d, ['atlas*', 'ATLAS*',
- 'sse', '3dnow', 'sse2']) + [d])
- return [d for d in dirs if os.path.isdir(d)]
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- info = {}
- atlas_libs = self.get_libs('atlas_libs',
- self._lib_names + self._lib_atlas)
- lapack_libs = self.get_libs('lapack_libs', self._lib_lapack)
- atlas = None
- lapack = None
- atlas_1 = None
- for d in lib_dirs:
- # FIXME: lapack_atlas is unused
- lapack_atlas = self.check_libs2(d, ['lapack_atlas'], [])
- atlas = self.check_libs2(d, atlas_libs, [])
- if atlas is not None:
- lib_dirs2 = [d] + self.combine_paths(d, ['atlas*', 'ATLAS*'])
- lapack = self.check_libs2(lib_dirs2, lapack_libs, [])
- if lapack is not None:
- break
- if atlas:
- atlas_1 = atlas
- log.info(self.__class__)
- if atlas is None:
- atlas = atlas_1
- if atlas is None:
- return
- include_dirs = self.get_include_dirs()
- h = (self.combine_paths(lib_dirs + include_dirs, 'cblas.h') or [None])
- h = h[0]
- if h:
- h = os.path.dirname(h)
- dict_append(info, include_dirs=[h])
- info['language'] = 'c'
- if lapack is not None:
- dict_append(info, **lapack)
- dict_append(info, **atlas)
- elif 'lapack_atlas' in atlas['libraries']:
- dict_append(info, **atlas)
- dict_append(info,
- define_macros=[('ATLAS_WITH_LAPACK_ATLAS', None)])
- self.set_info(**info)
- return
- else:
- dict_append(info, **atlas)
- dict_append(info, define_macros=[('ATLAS_WITHOUT_LAPACK', None)])
- message = """
- *********************************************************************
- Could not find lapack library within the ATLAS installation.
- *********************************************************************
- """
- warnings.warn(message, stacklevel=2)
- self.set_info(**info)
- return
- # Check if lapack library is complete, only warn if it is not.
- lapack_dir = lapack['library_dirs'][0]
- lapack_name = lapack['libraries'][0]
- lapack_lib = None
- lib_prefixes = ['lib']
- if sys.platform == 'win32':
- lib_prefixes.append('')
- for e in self.library_extensions():
- for prefix in lib_prefixes:
- fn = os.path.join(lapack_dir, prefix + lapack_name + e)
- if os.path.exists(fn):
- lapack_lib = fn
- break
- if lapack_lib:
- break
- if lapack_lib is not None:
- sz = os.stat(lapack_lib)[6]
- if sz <= 4000 * 1024:
- message = """
- *********************************************************************
- Lapack library (from ATLAS) is probably incomplete:
- size of %s is %sk (expected >4000k)
- Follow the instructions in the KNOWN PROBLEMS section of the file
- numpy/INSTALL.txt.
- *********************************************************************
- """ % (lapack_lib, sz / 1024)
- warnings.warn(message, stacklevel=2)
- else:
- info['language'] = 'f77'
- atlas_version, atlas_extra_info = get_atlas_version(**atlas)
- dict_append(info, **atlas_extra_info)
- self.set_info(**info)
- class atlas_blas_info(atlas_info):
- _lib_names = ['f77blas', 'cblas']
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- info = {}
- atlas_libs = self.get_libs('atlas_libs',
- self._lib_names + self._lib_atlas)
- atlas = self.check_libs2(lib_dirs, atlas_libs, [])
- if atlas is None:
- return
- include_dirs = self.get_include_dirs()
- h = (self.combine_paths(lib_dirs + include_dirs, 'cblas.h') or [None])
- h = h[0]
- if h:
- h = os.path.dirname(h)
- dict_append(info, include_dirs=[h])
- info['language'] = 'c'
- info['define_macros'] = [('HAVE_CBLAS', None)]
- atlas_version, atlas_extra_info = get_atlas_version(**atlas)
- dict_append(atlas, **atlas_extra_info)
- dict_append(info, **atlas)
- self.set_info(**info)
- return
- class atlas_threads_info(atlas_info):
- dir_env_var = ['PTATLAS', 'ATLAS']
- _lib_names = ['ptf77blas', 'ptcblas']
- class atlas_blas_threads_info(atlas_blas_info):
- dir_env_var = ['PTATLAS', 'ATLAS']
- _lib_names = ['ptf77blas', 'ptcblas']
- class lapack_atlas_info(atlas_info):
- _lib_names = ['lapack_atlas'] + atlas_info._lib_names
- class lapack_atlas_threads_info(atlas_threads_info):
- _lib_names = ['lapack_atlas'] + atlas_threads_info._lib_names
- class atlas_3_10_info(atlas_info):
- _lib_names = ['satlas']
- _lib_atlas = _lib_names
- _lib_lapack = _lib_names
- class atlas_3_10_blas_info(atlas_3_10_info):
- _lib_names = ['satlas']
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- info = {}
- atlas_libs = self.get_libs('atlas_libs',
- self._lib_names)
- atlas = self.check_libs2(lib_dirs, atlas_libs, [])
- if atlas is None:
- return
- include_dirs = self.get_include_dirs()
- h = (self.combine_paths(lib_dirs + include_dirs, 'cblas.h') or [None])
- h = h[0]
- if h:
- h = os.path.dirname(h)
- dict_append(info, include_dirs=[h])
- info['language'] = 'c'
- info['define_macros'] = [('HAVE_CBLAS', None)]
- atlas_version, atlas_extra_info = get_atlas_version(**atlas)
- dict_append(atlas, **atlas_extra_info)
- dict_append(info, **atlas)
- self.set_info(**info)
- return
- class atlas_3_10_threads_info(atlas_3_10_info):
- dir_env_var = ['PTATLAS', 'ATLAS']
- _lib_names = ['tatlas']
- _lib_atlas = _lib_names
- _lib_lapack = _lib_names
- class atlas_3_10_blas_threads_info(atlas_3_10_blas_info):
- dir_env_var = ['PTATLAS', 'ATLAS']
- _lib_names = ['tatlas']
- class lapack_atlas_3_10_info(atlas_3_10_info):
- pass
- class lapack_atlas_3_10_threads_info(atlas_3_10_threads_info):
- pass
- class lapack_info(system_info):
- section = 'lapack'
- dir_env_var = 'LAPACK'
- _lib_names = ['lapack']
- notfounderror = LapackNotFoundError
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- lapack_libs = self.get_libs('lapack_libs', self._lib_names)
- info = self.check_libs(lib_dirs, lapack_libs, [])
- if info is None:
- return
- info['language'] = 'f77'
- self.set_info(**info)
- class lapack_src_info(system_info):
- section = 'lapack_src'
- dir_env_var = 'LAPACK_SRC'
- notfounderror = LapackSrcNotFoundError
- def get_paths(self, section, key):
- pre_dirs = system_info.get_paths(self, section, key)
- dirs = []
- for d in pre_dirs:
- dirs.extend([d] + self.combine_paths(d, ['LAPACK*/SRC', 'SRC']))
- return [d for d in dirs if os.path.isdir(d)]
- def calc_info(self):
- src_dirs = self.get_src_dirs()
- src_dir = ''
- for d in src_dirs:
- if os.path.isfile(os.path.join(d, 'dgesv.f')):
- src_dir = d
- break
- if not src_dir:
- #XXX: Get sources from netlib. May be ask first.
- return
- # The following is extracted from LAPACK-3.0/SRC/Makefile.
- # Added missing names from lapack-lite-3.1.1/SRC/Makefile
- # while keeping removed names for Lapack-3.0 compatibility.
- allaux = '''
- ilaenv ieeeck lsame lsamen xerbla
- iparmq
- ''' # *.f
- laux = '''
- bdsdc bdsqr disna labad lacpy ladiv lae2 laebz laed0 laed1
- laed2 laed3 laed4 laed5 laed6 laed7 laed8 laed9 laeda laev2
- lagtf lagts lamch lamrg lanst lapy2 lapy3 larnv larrb larre
- larrf lartg laruv las2 lascl lasd0 lasd1 lasd2 lasd3 lasd4
- lasd5 lasd6 lasd7 lasd8 lasd9 lasda lasdq lasdt laset lasq1
- lasq2 lasq3 lasq4 lasq5 lasq6 lasr lasrt lassq lasv2 pttrf
- stebz stedc steqr sterf
- larra larrc larrd larr larrk larrj larrr laneg laisnan isnan
- lazq3 lazq4
- ''' # [s|d]*.f
- lasrc = '''
- gbbrd gbcon gbequ gbrfs gbsv gbsvx gbtf2 gbtrf gbtrs gebak
- gebal gebd2 gebrd gecon geequ gees geesx geev geevx gegs gegv
- gehd2 gehrd gelq2 gelqf gels gelsd gelss gelsx gelsy geql2
- geqlf geqp3 geqpf geqr2 geqrf gerfs gerq2 gerqf gesc2 gesdd
- gesv gesvd gesvx getc2 getf2 getrf getri getrs ggbak ggbal
- gges ggesx ggev ggevx ggglm gghrd gglse ggqrf ggrqf ggsvd
- ggsvp gtcon gtrfs gtsv gtsvx gttrf gttrs gtts2 hgeqz hsein
- hseqr labrd lacon laein lags2 lagtm lahqr lahrd laic1 lals0
- lalsa lalsd langb lange langt lanhs lansb lansp lansy lantb
- lantp lantr lapll lapmt laqgb laqge laqp2 laqps laqsb laqsp
- laqsy lar1v lar2v larf larfb larfg larft larfx largv larrv
- lartv larz larzb larzt laswp lasyf latbs latdf latps latrd
- latrs latrz latzm lauu2 lauum pbcon pbequ pbrfs pbstf pbsv
- pbsvx pbtf2 pbtrf pbtrs pocon poequ porfs posv posvx potf2
- potrf potri potrs ppcon ppequ pprfs ppsv ppsvx pptrf pptri
- pptrs ptcon pteqr ptrfs ptsv ptsvx pttrs ptts2 spcon sprfs
- spsv spsvx sptrf sptri sptrs stegr stein sycon syrfs sysv
- sysvx sytf2 sytrf sytri sytrs tbcon tbrfs tbtrs tgevc tgex2
- tgexc tgsen tgsja tgsna tgsy2 tgsyl tpcon tprfs tptri tptrs
- trcon trevc trexc trrfs trsen trsna trsyl trti2 trtri trtrs
- tzrqf tzrzf
- lacn2 lahr2 stemr laqr0 laqr1 laqr2 laqr3 laqr4 laqr5
- ''' # [s|c|d|z]*.f
- sd_lasrc = '''
- laexc lag2 lagv2 laln2 lanv2 laqtr lasy2 opgtr opmtr org2l
- org2r orgbr orghr orgl2 orglq orgql orgqr orgr2 orgrq orgtr
- orm2l orm2r ormbr ormhr orml2 ormlq ormql ormqr ormr2 ormr3
- ormrq ormrz ormtr rscl sbev sbevd sbevx sbgst sbgv sbgvd sbgvx
- sbtrd spev spevd spevx spgst spgv spgvd spgvx sptrd stev stevd
- stevr stevx syev syevd syevr syevx sygs2 sygst sygv sygvd
- sygvx sytd2 sytrd
- ''' # [s|d]*.f
- cz_lasrc = '''
- bdsqr hbev hbevd hbevx hbgst hbgv hbgvd hbgvx hbtrd hecon heev
- heevd heevr heevx hegs2 hegst hegv hegvd hegvx herfs hesv
- hesvx hetd2 hetf2 hetrd hetrf hetri hetrs hpcon hpev hpevd
- hpevx hpgst hpgv hpgvd hpgvx hprfs hpsv hpsvx hptrd hptrf
- hptri hptrs lacgv lacp2 lacpy lacrm lacrt ladiv laed0 laed7
- laed8 laesy laev2 lahef lanhb lanhe lanhp lanht laqhb laqhe
- laqhp larcm larnv lartg lascl laset lasr lassq pttrf rot spmv
- spr stedc steqr symv syr ung2l ung2r ungbr unghr ungl2 unglq
- ungql ungqr ungr2 ungrq ungtr unm2l unm2r unmbr unmhr unml2
- unmlq unmql unmqr unmr2 unmr3 unmrq unmrz unmtr upgtr upmtr
- ''' # [c|z]*.f
- #######
- sclaux = laux + ' econd ' # s*.f
- dzlaux = laux + ' secnd ' # d*.f
- slasrc = lasrc + sd_lasrc # s*.f
- dlasrc = lasrc + sd_lasrc # d*.f
- clasrc = lasrc + cz_lasrc + ' srot srscl ' # c*.f
- zlasrc = lasrc + cz_lasrc + ' drot drscl ' # z*.f
- oclasrc = ' icmax1 scsum1 ' # *.f
- ozlasrc = ' izmax1 dzsum1 ' # *.f
- sources = ['s%s.f' % f for f in (sclaux + slasrc).split()] \
- + ['d%s.f' % f for f in (dzlaux + dlasrc).split()] \
- + ['c%s.f' % f for f in (clasrc).split()] \
- + ['z%s.f' % f for f in (zlasrc).split()] \
- + ['%s.f' % f for f in (allaux + oclasrc + ozlasrc).split()]
- sources = [os.path.join(src_dir, f) for f in sources]
- # Lapack 3.1:
- src_dir2 = os.path.join(src_dir, '..', 'INSTALL')
- sources += [os.path.join(src_dir2, p + 'lamch.f') for p in 'sdcz']
- # Lapack 3.2.1:
- sources += [os.path.join(src_dir, p + 'larfp.f') for p in 'sdcz']
- sources += [os.path.join(src_dir, 'ila' + p + 'lr.f') for p in 'sdcz']
- sources += [os.path.join(src_dir, 'ila' + p + 'lc.f') for p in 'sdcz']
- # Should we check here actual existence of source files?
- # Yes, the file listing is different between 3.0 and 3.1
- # versions.
- sources = [f for f in sources if os.path.isfile(f)]
- info = {'sources': sources, 'language': 'f77'}
- self.set_info(**info)
- atlas_version_c_text = r'''
- /* This file is generated from numpy/distutils/system_info.py */
- void ATL_buildinfo(void);
- int main(void) {
- ATL_buildinfo();
- return 0;
- }
- '''
- _cached_atlas_version = {}
- def get_atlas_version(**config):
- libraries = config.get('libraries', [])
- library_dirs = config.get('library_dirs', [])
- key = (tuple(libraries), tuple(library_dirs))
- if key in _cached_atlas_version:
- return _cached_atlas_version[key]
- c = cmd_config(Distribution())
- atlas_version = None
- info = {}
- try:
- s, o = c.get_output(atlas_version_c_text,
- libraries=libraries, library_dirs=library_dirs,
- use_tee=(system_info.verbosity > 0))
- if s and re.search(r'undefined reference to `_gfortran', o, re.M):
- s, o = c.get_output(atlas_version_c_text,
- libraries=libraries + ['gfortran'],
- library_dirs=library_dirs,
- use_tee=(system_info.verbosity > 0))
- if not s:
- warnings.warn("""
- *****************************************************
- Linkage with ATLAS requires gfortran. Use
- python setup.py config_fc --fcompiler=gnu95 ...
- when building extension libraries that use ATLAS.
- Make sure that -lgfortran is used for C++ extensions.
- *****************************************************
- """, stacklevel=2)
- dict_append(info, language='f90',
- define_macros=[('ATLAS_REQUIRES_GFORTRAN', None)])
- except Exception: # failed to get version from file -- maybe on Windows
- # look at directory name
- for o in library_dirs:
- m = re.search(r'ATLAS_(?P<version>\d+[.]\d+[.]\d+)_', o)
- if m:
- atlas_version = m.group('version')
- if atlas_version is not None:
- break
- # final choice --- look at ATLAS_VERSION environment
- # variable
- if atlas_version is None:
- atlas_version = os.environ.get('ATLAS_VERSION', None)
- if atlas_version:
- dict_append(info, define_macros=[(
- 'ATLAS_INFO', _c_string_literal(atlas_version))
- ])
- else:
- dict_append(info, define_macros=[('NO_ATLAS_INFO', -1)])
- return atlas_version or '?.?.?', info
- if not s:
- m = re.search(r'ATLAS version (?P<version>\d+[.]\d+[.]\d+)', o)
- if m:
- atlas_version = m.group('version')
- if atlas_version is None:
- if re.search(r'undefined symbol: ATL_buildinfo', o, re.M):
- atlas_version = '3.2.1_pre3.3.6'
- else:
- log.info('Status: %d', s)
- log.info('Output: %s', o)
- if atlas_version == '3.2.1_pre3.3.6':
- dict_append(info, define_macros=[('NO_ATLAS_INFO', -2)])
- else:
- dict_append(info, define_macros=[(
- 'ATLAS_INFO', _c_string_literal(atlas_version))
- ])
- result = _cached_atlas_version[key] = atlas_version, info
- return result
- class lapack_opt_info(system_info):
- notfounderror = LapackNotFoundError
- def calc_info(self):
- lapack_mkl_info = get_info('lapack_mkl')
- if lapack_mkl_info:
- self.set_info(**lapack_mkl_info)
- return
- openblas_info = get_info('openblas_lapack')
- if openblas_info:
- self.set_info(**openblas_info)
- return
- openblas_info = get_info('openblas_clapack')
- if openblas_info:
- self.set_info(**openblas_info)
- return
- atlas_info = get_info('atlas_3_10_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_3_10')
- if not atlas_info:
- atlas_info = get_info('atlas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas')
- accelerate_info = get_info('accelerate')
- if accelerate_info and not atlas_info:
- self.set_info(**accelerate_info)
- return
- need_lapack = 0
- need_blas = 0
- info = {}
- if atlas_info:
- l = atlas_info.get('define_macros', [])
- if ('ATLAS_WITH_LAPACK_ATLAS', None) in l \
- or ('ATLAS_WITHOUT_LAPACK', None) in l:
- need_lapack = 1
- info = atlas_info
- else:
- warnings.warn(AtlasNotFoundError.__doc__, stacklevel=2)
- need_blas = 1
- need_lapack = 1
- dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
- if need_lapack:
- lapack_info = get_info('lapack')
- #lapack_info = {} ## uncomment for testing
- if lapack_info:
- dict_append(info, **lapack_info)
- else:
- warnings.warn(LapackNotFoundError.__doc__, stacklevel=2)
- lapack_src_info = get_info('lapack_src')
- if not lapack_src_info:
- warnings.warn(LapackSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('flapack_src', lapack_src_info)])
- if need_blas:
- blas_info = get_info('blas')
- if blas_info:
- dict_append(info, **blas_info)
- else:
- warnings.warn(BlasNotFoundError.__doc__, stacklevel=2)
- blas_src_info = get_info('blas_src')
- if not blas_src_info:
- warnings.warn(BlasSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('fblas_src', blas_src_info)])
- self.set_info(**info)
- return
- class blas_opt_info(system_info):
- notfounderror = BlasNotFoundError
- def calc_info(self):
- blas_mkl_info = get_info('blas_mkl')
- if blas_mkl_info:
- self.set_info(**blas_mkl_info)
- return
- blis_info = get_info('blis')
- if blis_info:
- self.set_info(**blis_info)
- return
- openblas_info = get_info('openblas')
- if openblas_info:
- self.set_info(**openblas_info)
- return
- atlas_info = get_info('atlas_3_10_blas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_3_10_blas')
- if not atlas_info:
- atlas_info = get_info('atlas_blas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_blas')
- accelerate_info = get_info('accelerate')
- if accelerate_info and not atlas_info:
- self.set_info(**accelerate_info)
- return
- need_blas = 0
- info = {}
- if atlas_info:
- info = atlas_info
- else:
- warnings.warn(AtlasNotFoundError.__doc__, stacklevel=2)
- need_blas = 1
- dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
- if need_blas:
- blas_info = get_info('blas')
- if blas_info:
- dict_append(info, **blas_info)
- else:
- warnings.warn(BlasNotFoundError.__doc__, stacklevel=2)
- blas_src_info = get_info('blas_src')
- if not blas_src_info:
- warnings.warn(BlasSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('fblas_src', blas_src_info)])
- self.set_info(**info)
- return
- class blas_info(system_info):
- section = 'blas'
- dir_env_var = 'BLAS'
- _lib_names = ['blas']
- notfounderror = BlasNotFoundError
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- blas_libs = self.get_libs('blas_libs', self._lib_names)
- info = self.check_libs(lib_dirs, blas_libs, [])
- if info is None:
- return
- else:
- info['include_dirs'] = self.get_include_dirs()
- if platform.system() == 'Windows':
- # The check for windows is needed because has_cblas uses the
- # same compiler that was used to compile Python and msvc is
- # often not installed when mingw is being used. This rough
- # treatment is not desirable, but windows is tricky.
- info['language'] = 'f77' # XXX: is it generally true?
- else:
- lib = self.has_cblas(info)
- if lib is not None:
- info['language'] = 'c'
- info['libraries'] = [lib]
- info['define_macros'] = [('HAVE_CBLAS', None)]
- self.set_info(**info)
- def has_cblas(self, info):
- # primitive cblas check by looking for the header and trying to link
- # cblas or blas
- res = False
- c = customized_ccompiler()
- tmpdir = tempfile.mkdtemp()
- s = """#include <cblas.h>
- int main(int argc, const char *argv[])
- {
- double a[4] = {1,2,3,4};
- double b[4] = {5,6,7,8};
- return cblas_ddot(4, a, 1, b, 1) > 10;
- }"""
- src = os.path.join(tmpdir, 'source.c')
- try:
- with open(src, 'wt') as f:
- f.write(s)
- try:
- # check we can compile (find headers)
- obj = c.compile([src], output_dir=tmpdir,
- include_dirs=self.get_include_dirs())
- # check we can link (find library)
- # some systems have separate cblas and blas libs. First
- # check for cblas lib, and if not present check for blas lib.
- try:
- c.link_executable(obj, os.path.join(tmpdir, "a.out"),
- libraries=["cblas"],
- library_dirs=info['library_dirs'],
- extra_postargs=info.get('extra_link_args', []))
- res = "cblas"
- except distutils.ccompiler.LinkError:
- c.link_executable(obj, os.path.join(tmpdir, "a.out"),
- libraries=["blas"],
- library_dirs=info['library_dirs'],
- extra_postargs=info.get('extra_link_args', []))
- res = "blas"
- except distutils.ccompiler.CompileError:
- res = None
- finally:
- shutil.rmtree(tmpdir)
- return res
- class openblas_info(blas_info):
- section = 'openblas'
- dir_env_var = 'OPENBLAS'
- _lib_names = ['openblas']
- notfounderror = BlasNotFoundError
- def check_embedded_lapack(self, info):
- return True
- def calc_info(self):
- c = customized_ccompiler()
- lib_dirs = self.get_lib_dirs()
- openblas_libs = self.get_libs('libraries', self._lib_names)
- if openblas_libs == self._lib_names: # backward compat with 1.8.0
- openblas_libs = self.get_libs('openblas_libs', self._lib_names)
- info = self.check_libs(lib_dirs, openblas_libs, [])
- if c.compiler_type == "msvc" and info is None:
- from numpy.distutils.fcompiler import new_fcompiler
- f = new_fcompiler(c_compiler=c)
- if f and f.compiler_type == 'gnu95':
- # Try gfortran-compatible library files
- info = self.check_msvc_gfortran_libs(lib_dirs, openblas_libs)
- # Skip lapack check, we'd need build_ext to do it
- assume_lapack = True
- elif info:
- assume_lapack = False
- info['language'] = 'c'
- if info is None:
- return
- # Add extra info for OpenBLAS
- extra_info = self.calc_extra_info()
- dict_append(info, **extra_info)
- if not (assume_lapack or self.check_embedded_lapack(info)):
- return
- info['define_macros'] = [('HAVE_CBLAS', None)]
- self.set_info(**info)
- def check_msvc_gfortran_libs(self, library_dirs, libraries):
- # First, find the full path to each library directory
- library_paths = []
- for library in libraries:
- for library_dir in library_dirs:
- # MinGW static ext will be .a
- fullpath = os.path.join(library_dir, library + '.a')
- if os.path.isfile(fullpath):
- library_paths.append(fullpath)
- break
- else:
- return None
- # Generate numpy.distutils virtual static library file
- tmpdir = os.path.join(os.getcwd(), 'build', 'openblas')
- if not os.path.isdir(tmpdir):
- os.makedirs(tmpdir)
- info = {'library_dirs': [tmpdir],
- 'libraries': ['openblas'],
- 'language': 'f77'}
- fake_lib_file = os.path.join(tmpdir, 'openblas.fobjects')
- fake_clib_file = os.path.join(tmpdir, 'openblas.cobjects')
- with open(fake_lib_file, 'w') as f:
- f.write("\n".join(library_paths))
- with open(fake_clib_file, 'w') as f:
- pass
- return info
- class openblas_lapack_info(openblas_info):
- section = 'openblas'
- dir_env_var = 'OPENBLAS'
- _lib_names = ['openblas']
- notfounderror = BlasNotFoundError
- def check_embedded_lapack(self, info):
- res = False
- c = customized_ccompiler()
- tmpdir = tempfile.mkdtemp()
- s = """void zungqr_();
- int main(int argc, const char *argv[])
- {
- zungqr_();
- return 0;
- }"""
- src = os.path.join(tmpdir, 'source.c')
- out = os.path.join(tmpdir, 'a.out')
- # Add the additional "extra" arguments
- try:
- extra_args = info['extra_link_args']
- except Exception:
- extra_args = []
- if sys.version_info < (3, 5) and sys.version_info > (3, 0) and c.compiler_type == "msvc":
- extra_args.append("/MANIFEST")
- try:
- with open(src, 'wt') as f:
- f.write(s)
- obj = c.compile([src], output_dir=tmpdir)
- try:
- c.link_executable(obj, out, libraries=info['libraries'],
- library_dirs=info['library_dirs'],
- extra_postargs=extra_args)
- res = True
- except distutils.ccompiler.LinkError:
- res = False
- finally:
- shutil.rmtree(tmpdir)
- return res
- class openblas_clapack_info(openblas_lapack_info):
- _lib_names = ['openblas', 'lapack']
- class blis_info(blas_info):
- section = 'blis'
- dir_env_var = 'BLIS'
- _lib_names = ['blis']
- notfounderror = BlasNotFoundError
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- blis_libs = self.get_libs('libraries', self._lib_names)
- if blis_libs == self._lib_names:
- blis_libs = self.get_libs('blis_libs', self._lib_names)
- info = self.check_libs2(lib_dirs, blis_libs, [])
- if info is None:
- return
- # Add include dirs
- incl_dirs = self.get_include_dirs()
- dict_append(info,
- language='c',
- define_macros=[('HAVE_CBLAS', None)],
- include_dirs=incl_dirs)
- self.set_info(**info)
- class accelerate_info(system_info):
- section = 'accelerate'
- notfounderror = BlasNotFoundError
- def calc_info(self):
- # Make possible to enable/disable from config file/env var
- libraries = os.environ.get('ACCELERATE')
- if libraries:
- libraries = [libraries]
- else:
- libraries = self.get_libs('libraries', ['accelerate', 'veclib'])
- libraries = [lib.strip().lower() for lib in libraries]
- if (sys.platform == 'darwin' and
- not os.getenv('_PYTHON_HOST_PLATFORM', None)):
- # Use the system BLAS from Accelerate or vecLib under OSX
- args = []
- link_args = []
- if get_platform()[-4:] == 'i386' or 'intel' in get_platform() or \
- 'x86_64' in get_platform() or \
- 'i386' in platform.platform():
- intel = 1
- else:
- intel = 0
- if (os.path.exists('/System/Library/Frameworks'
- '/Accelerate.framework/') and
- 'accelerate' in libraries):
- if intel:
- args.extend(['-msse3'])
- else:
- args.extend(['-faltivec'])
- args.extend([
- '-I/System/Library/Frameworks/vecLib.framework/Headers'])
- link_args.extend(['-Wl,-framework', '-Wl,Accelerate'])
- elif (os.path.exists('/System/Library/Frameworks'
- '/vecLib.framework/') and
- 'veclib' in libraries):
- if intel:
- args.extend(['-msse3'])
- else:
- args.extend(['-faltivec'])
- args.extend([
- '-I/System/Library/Frameworks/vecLib.framework/Headers'])
- link_args.extend(['-Wl,-framework', '-Wl,vecLib'])
- if args:
- self.set_info(extra_compile_args=args,
- extra_link_args=link_args,
- define_macros=[('NO_ATLAS_INFO', 3),
- ('HAVE_CBLAS', None)])
- return
- class blas_src_info(system_info):
- section = 'blas_src'
- dir_env_var = 'BLAS_SRC'
- notfounderror = BlasSrcNotFoundError
- def get_paths(self, section, key):
- pre_dirs = system_info.get_paths(self, section, key)
- dirs = []
- for d in pre_dirs:
- dirs.extend([d] + self.combine_paths(d, ['blas']))
- return [d for d in dirs if os.path.isdir(d)]
- def calc_info(self):
- src_dirs = self.get_src_dirs()
- src_dir = ''
- for d in src_dirs:
- if os.path.isfile(os.path.join(d, 'daxpy.f')):
- src_dir = d
- break
- if not src_dir:
- #XXX: Get sources from netlib. May be ask first.
- return
- blas1 = '''
- caxpy csscal dnrm2 dzasum saxpy srotg zdotc ccopy cswap drot
- dznrm2 scasum srotm zdotu cdotc dasum drotg icamax scnrm2
- srotmg zdrot cdotu daxpy drotm idamax scopy sscal zdscal crotg
- dcabs1 drotmg isamax sdot sswap zrotg cscal dcopy dscal izamax
- snrm2 zaxpy zscal csrot ddot dswap sasum srot zcopy zswap
- scabs1
- '''
- blas2 = '''
- cgbmv chpmv ctrsv dsymv dtrsv sspr2 strmv zhemv ztpmv cgemv
- chpr dgbmv dsyr lsame ssymv strsv zher ztpsv cgerc chpr2 dgemv
- dsyr2 sgbmv ssyr xerbla zher2 ztrmv cgeru ctbmv dger dtbmv
- sgemv ssyr2 zgbmv zhpmv ztrsv chbmv ctbsv dsbmv dtbsv sger
- stbmv zgemv zhpr chemv ctpmv dspmv dtpmv ssbmv stbsv zgerc
- zhpr2 cher ctpsv dspr dtpsv sspmv stpmv zgeru ztbmv cher2
- ctrmv dspr2 dtrmv sspr stpsv zhbmv ztbsv
- '''
- blas3 = '''
- cgemm csymm ctrsm dsyrk sgemm strmm zhemm zsyr2k chemm csyr2k
- dgemm dtrmm ssymm strsm zher2k zsyrk cher2k csyrk dsymm dtrsm
- ssyr2k zherk ztrmm cherk ctrmm dsyr2k ssyrk zgemm zsymm ztrsm
- '''
- sources = [os.path.join(src_dir, f + '.f') \
- for f in (blas1 + blas2 + blas3).split()]
- #XXX: should we check here actual existence of source files?
- sources = [f for f in sources if os.path.isfile(f)]
- info = {'sources': sources, 'language': 'f77'}
- self.set_info(**info)
- class x11_info(system_info):
- section = 'x11'
- notfounderror = X11NotFoundError
- def __init__(self):
- system_info.__init__(self,
- default_lib_dirs=default_x11_lib_dirs,
- default_include_dirs=default_x11_include_dirs)
- def calc_info(self):
- if sys.platform in ['win32']:
- return
- lib_dirs = self.get_lib_dirs()
- include_dirs = self.get_include_dirs()
- x11_libs = self.get_libs('x11_libs', ['X11'])
- info = self.check_libs(lib_dirs, x11_libs, [])
- if info is None:
- return
- inc_dir = None
- for d in include_dirs:
- if self.combine_paths(d, 'X11/X.h'):
- inc_dir = d
- break
- if inc_dir is not None:
- dict_append(info, include_dirs=[inc_dir])
- self.set_info(**info)
- class _numpy_info(system_info):
- section = 'Numeric'
- modulename = 'Numeric'
- notfounderror = NumericNotFoundError
- def __init__(self):
- include_dirs = []
- try:
- module = __import__(self.modulename)
- prefix = []
- for name in module.__file__.split(os.sep):
- if name == 'lib':
- break
- prefix.append(name)
- # Ask numpy for its own include path before attempting
- # anything else
- try:
- include_dirs.append(getattr(module, 'get_include')())
- except AttributeError:
- pass
- include_dirs.append(distutils.sysconfig.get_python_inc(
- prefix=os.sep.join(prefix)))
- except ImportError:
- pass
- py_incl_dir = distutils.sysconfig.get_python_inc()
- include_dirs.append(py_incl_dir)
- py_pincl_dir = distutils.sysconfig.get_python_inc(plat_specific=True)
- if py_pincl_dir not in include_dirs:
- include_dirs.append(py_pincl_dir)
- for d in default_include_dirs:
- d = os.path.join(d, os.path.basename(py_incl_dir))
- if d not in include_dirs:
- include_dirs.append(d)
- system_info.__init__(self,
- default_lib_dirs=[],
- default_include_dirs=include_dirs)
- def calc_info(self):
- try:
- module = __import__(self.modulename)
- except ImportError:
- return
- info = {}
- macros = []
- for v in ['__version__', 'version']:
- vrs = getattr(module, v, None)
- if vrs is None:
- continue
- macros = [(self.modulename.upper() + '_VERSION',
- _c_string_literal(vrs)),
- (self.modulename.upper(), None)]
- break
- dict_append(info, define_macros=macros)
- include_dirs = self.get_include_dirs()
- inc_dir = None
- for d in include_dirs:
- if self.combine_paths(d,
- os.path.join(self.modulename,
- 'arrayobject.h')):
- inc_dir = d
- break
- if inc_dir is not None:
- dict_append(info, include_dirs=[inc_dir])
- if info:
- self.set_info(**info)
- return
- class numarray_info(_numpy_info):
- section = 'numarray'
- modulename = 'numarray'
- class Numeric_info(_numpy_info):
- section = 'Numeric'
- modulename = 'Numeric'
- class numpy_info(_numpy_info):
- section = 'numpy'
- modulename = 'numpy'
- class numerix_info(system_info):
- section = 'numerix'
- def calc_info(self):
- which = None, None
- if os.getenv("NUMERIX"):
- which = os.getenv("NUMERIX"), "environment var"
- # If all the above fail, default to numpy.
- if which[0] is None:
- which = "numpy", "defaulted"
- try:
- import numpy # noqa: F401
- which = "numpy", "defaulted"
- except ImportError:
- msg1 = str(get_exception())
- try:
- import Numeric # noqa: F401
- which = "numeric", "defaulted"
- except ImportError:
- msg2 = str(get_exception())
- try:
- import numarray # noqa: F401
- which = "numarray", "defaulted"
- except ImportError:
- msg3 = str(get_exception())
- log.info(msg1)
- log.info(msg2)
- log.info(msg3)
- which = which[0].strip().lower(), which[1]
- if which[0] not in ["numeric", "numarray", "numpy"]:
- raise ValueError("numerix selector must be either 'Numeric' "
- "or 'numarray' or 'numpy' but the value obtained"
- " from the %s was '%s'." % (which[1], which[0]))
- os.environ['NUMERIX'] = which[0]
- self.set_info(**get_info(which[0]))
- class f2py_info(system_info):
- def calc_info(self):
- try:
- import numpy.f2py as f2py
- except ImportError:
- return
- f2py_dir = os.path.join(os.path.dirname(f2py.__file__), 'src')
- self.set_info(sources=[os.path.join(f2py_dir, 'fortranobject.c')],
- include_dirs=[f2py_dir])
- return
- class boost_python_info(system_info):
- section = 'boost_python'
- dir_env_var = 'BOOST'
- def get_paths(self, section, key):
- pre_dirs = system_info.get_paths(self, section, key)
- dirs = []
- for d in pre_dirs:
- dirs.extend([d] + self.combine_paths(d, ['boost*']))
- return [d for d in dirs if os.path.isdir(d)]
- def calc_info(self):
- src_dirs = self.get_src_dirs()
- src_dir = ''
- for d in src_dirs:
- if os.path.isfile(os.path.join(d, 'libs', 'python', 'src',
- 'module.cpp')):
- src_dir = d
- break
- if not src_dir:
- return
- py_incl_dirs = [distutils.sysconfig.get_python_inc()]
- py_pincl_dir = distutils.sysconfig.get_python_inc(plat_specific=True)
- if py_pincl_dir not in py_incl_dirs:
- py_incl_dirs.append(py_pincl_dir)
- srcs_dir = os.path.join(src_dir, 'libs', 'python', 'src')
- bpl_srcs = glob(os.path.join(srcs_dir, '*.cpp'))
- bpl_srcs += glob(os.path.join(srcs_dir, '*', '*.cpp'))
- info = {'libraries': [('boost_python_src',
- {'include_dirs': [src_dir] + py_incl_dirs,
- 'sources':bpl_srcs}
- )],
- 'include_dirs': [src_dir],
- }
- if info:
- self.set_info(**info)
- return
- class agg2_info(system_info):
- section = 'agg2'
- dir_env_var = 'AGG2'
- def get_paths(self, section, key):
- pre_dirs = system_info.get_paths(self, section, key)
- dirs = []
- for d in pre_dirs:
- dirs.extend([d] + self.combine_paths(d, ['agg2*']))
- return [d for d in dirs if os.path.isdir(d)]
- def calc_info(self):
- src_dirs = self.get_src_dirs()
- src_dir = ''
- for d in src_dirs:
- if os.path.isfile(os.path.join(d, 'src', 'agg_affine_matrix.cpp')):
- src_dir = d
- break
- if not src_dir:
- return
- if sys.platform == 'win32':
- agg2_srcs = glob(os.path.join(src_dir, 'src', 'platform',
- 'win32', 'agg_win32_bmp.cpp'))
- else:
- agg2_srcs = glob(os.path.join(src_dir, 'src', '*.cpp'))
- agg2_srcs += [os.path.join(src_dir, 'src', 'platform',
- 'X11',
- 'agg_platform_support.cpp')]
- info = {'libraries':
- [('agg2_src',
- {'sources': agg2_srcs,
- 'include_dirs': [os.path.join(src_dir, 'include')],
- }
- )],
- 'include_dirs': [os.path.join(src_dir, 'include')],
- }
- if info:
- self.set_info(**info)
- return
- class _pkg_config_info(system_info):
- section = None
- config_env_var = 'PKG_CONFIG'
- default_config_exe = 'pkg-config'
- append_config_exe = ''
- version_macro_name = None
- release_macro_name = None
- version_flag = '--modversion'
- cflags_flag = '--cflags'
- def get_config_exe(self):
- if self.config_env_var in os.environ:
- return os.environ[self.config_env_var]
- return self.default_config_exe
- def get_config_output(self, config_exe, option):
- cmd = config_exe + ' ' + self.append_config_exe + ' ' + option
- try:
- o = subprocess.check_output(cmd)
- except (OSError, subprocess.CalledProcessError):
- pass
- else:
- o = filepath_from_subprocess_output(o)
- return o
- def calc_info(self):
- config_exe = find_executable(self.get_config_exe())
- if not config_exe:
- log.warn('File not found: %s. Cannot determine %s info.' \
- % (config_exe, self.section))
- return
- info = {}
- macros = []
- libraries = []
- library_dirs = []
- include_dirs = []
- extra_link_args = []
- extra_compile_args = []
- version = self.get_config_output(config_exe, self.version_flag)
- if version:
- macros.append((self.__class__.__name__.split('.')[-1].upper(),
- _c_string_literal(version)))
- if self.version_macro_name:
- macros.append((self.version_macro_name + '_%s'
- % (version.replace('.', '_')), None))
- if self.release_macro_name:
- release = self.get_config_output(config_exe, '--release')
- if release:
- macros.append((self.release_macro_name + '_%s'
- % (release.replace('.', '_')), None))
- opts = self.get_config_output(config_exe, '--libs')
- if opts:
- for opt in opts.split():
- if opt[:2] == '-l':
- libraries.append(opt[2:])
- elif opt[:2] == '-L':
- library_dirs.append(opt[2:])
- else:
- extra_link_args.append(opt)
- opts = self.get_config_output(config_exe, self.cflags_flag)
- if opts:
- for opt in opts.split():
- if opt[:2] == '-I':
- include_dirs.append(opt[2:])
- elif opt[:2] == '-D':
- if '=' in opt:
- n, v = opt[2:].split('=')
- macros.append((n, v))
- else:
- macros.append((opt[2:], None))
- else:
- extra_compile_args.append(opt)
- if macros:
- dict_append(info, define_macros=macros)
- if libraries:
- dict_append(info, libraries=libraries)
- if library_dirs:
- dict_append(info, library_dirs=library_dirs)
- if include_dirs:
- dict_append(info, include_dirs=include_dirs)
- if extra_link_args:
- dict_append(info, extra_link_args=extra_link_args)
- if extra_compile_args:
- dict_append(info, extra_compile_args=extra_compile_args)
- if info:
- self.set_info(**info)
- return
- class wx_info(_pkg_config_info):
- section = 'wx'
- config_env_var = 'WX_CONFIG'
- default_config_exe = 'wx-config'
- append_config_exe = ''
- version_macro_name = 'WX_VERSION'
- release_macro_name = 'WX_RELEASE'
- version_flag = '--version'
- cflags_flag = '--cxxflags'
- class gdk_pixbuf_xlib_2_info(_pkg_config_info):
- section = 'gdk_pixbuf_xlib_2'
- append_config_exe = 'gdk-pixbuf-xlib-2.0'
- version_macro_name = 'GDK_PIXBUF_XLIB_VERSION'
- class gdk_pixbuf_2_info(_pkg_config_info):
- section = 'gdk_pixbuf_2'
- append_config_exe = 'gdk-pixbuf-2.0'
- version_macro_name = 'GDK_PIXBUF_VERSION'
- class gdk_x11_2_info(_pkg_config_info):
- section = 'gdk_x11_2'
- append_config_exe = 'gdk-x11-2.0'
- version_macro_name = 'GDK_X11_VERSION'
- class gdk_2_info(_pkg_config_info):
- section = 'gdk_2'
- append_config_exe = 'gdk-2.0'
- version_macro_name = 'GDK_VERSION'
- class gdk_info(_pkg_config_info):
- section = 'gdk'
- append_config_exe = 'gdk'
- version_macro_name = 'GDK_VERSION'
- class gtkp_x11_2_info(_pkg_config_info):
- section = 'gtkp_x11_2'
- append_config_exe = 'gtk+-x11-2.0'
- version_macro_name = 'GTK_X11_VERSION'
- class gtkp_2_info(_pkg_config_info):
- section = 'gtkp_2'
- append_config_exe = 'gtk+-2.0'
- version_macro_name = 'GTK_VERSION'
- class xft_info(_pkg_config_info):
- section = 'xft'
- append_config_exe = 'xft'
- version_macro_name = 'XFT_VERSION'
- class freetype2_info(_pkg_config_info):
- section = 'freetype2'
- append_config_exe = 'freetype2'
- version_macro_name = 'FREETYPE2_VERSION'
- class amd_info(system_info):
- section = 'amd'
- dir_env_var = 'AMD'
- _lib_names = ['amd']
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- amd_libs = self.get_libs('amd_libs', self._lib_names)
- info = self.check_libs(lib_dirs, amd_libs, [])
- if info is None:
- return
- include_dirs = self.get_include_dirs()
- inc_dir = None
- for d in include_dirs:
- p = self.combine_paths(d, 'amd.h')
- if p:
- inc_dir = os.path.dirname(p[0])
- break
- if inc_dir is not None:
- dict_append(info, include_dirs=[inc_dir],
- define_macros=[('SCIPY_AMD_H', None)],
- swig_opts=['-I' + inc_dir])
- self.set_info(**info)
- return
- class umfpack_info(system_info):
- section = 'umfpack'
- dir_env_var = 'UMFPACK'
- notfounderror = UmfpackNotFoundError
- _lib_names = ['umfpack']
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- umfpack_libs = self.get_libs('umfpack_libs', self._lib_names)
- info = self.check_libs(lib_dirs, umfpack_libs, [])
- if info is None:
- return
- include_dirs = self.get_include_dirs()
- inc_dir = None
- for d in include_dirs:
- p = self.combine_paths(d, ['', 'umfpack'], 'umfpack.h')
- if p:
- inc_dir = os.path.dirname(p[0])
- break
- if inc_dir is not None:
- dict_append(info, include_dirs=[inc_dir],
- define_macros=[('SCIPY_UMFPACK_H', None)],
- swig_opts=['-I' + inc_dir])
- dict_append(info, **get_info('amd'))
- self.set_info(**info)
- return
- def combine_paths(*args, **kws):
- """ Return a list of existing paths composed by all combinations of
- items from arguments.
- """
- r = []
- for a in args:
- if not a:
- continue
- if is_string(a):
- a = [a]
- r.append(a)
- args = r
- if not args:
- return []
- if len(args) == 1:
- result = reduce(lambda a, b: a + b, map(glob, args[0]), [])
- elif len(args) == 2:
- result = []
- for a0 in args[0]:
- for a1 in args[1]:
- result.extend(glob(os.path.join(a0, a1)))
- else:
- result = combine_paths(*(combine_paths(args[0], args[1]) + args[2:]))
- log.debug('(paths: %s)', ','.join(result))
- return result
- language_map = {'c': 0, 'c++': 1, 'f77': 2, 'f90': 3}
- inv_language_map = {0: 'c', 1: 'c++', 2: 'f77', 3: 'f90'}
- def dict_append(d, **kws):
- languages = []
- for k, v in kws.items():
- if k == 'language':
- languages.append(v)
- continue
- if k in d:
- if k in ['library_dirs', 'include_dirs',
- 'extra_compile_args', 'extra_link_args',
- 'runtime_library_dirs', 'define_macros']:
- [d[k].append(vv) for vv in v if vv not in d[k]]
- else:
- d[k].extend(v)
- else:
- d[k] = v
- if languages:
- l = inv_language_map[max([language_map.get(l, 0) for l in languages])]
- d['language'] = l
- return
- def parseCmdLine(argv=(None,)):
- import optparse
- parser = optparse.OptionParser("usage: %prog [-v] [info objs]")
- parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
- default=False,
- help='be verbose and print more messages')
- opts, args = parser.parse_args(args=argv[1:])
- return opts, args
- def show_all(argv=None):
- import inspect
- if argv is None:
- argv = sys.argv
- opts, args = parseCmdLine(argv)
- if opts.verbose:
- log.set_threshold(log.DEBUG)
- else:
- log.set_threshold(log.INFO)
- show_only = []
- for n in args:
- if n[-5:] != '_info':
- n = n + '_info'
- show_only.append(n)
- show_all = not show_only
- _gdict_ = globals().copy()
- for name, c in _gdict_.items():
- if not inspect.isclass(c):
- continue
- if not issubclass(c, system_info) or c is system_info:
- continue
- if not show_all:
- if name not in show_only:
- continue
- del show_only[show_only.index(name)]
- conf = c()
- conf.verbosity = 2
- # FIXME: r not used
- r = conf.get_info()
- if show_only:
- log.info('Info classes not defined: %s', ','.join(show_only))
- if __name__ == "__main__":
- show_all()
|