1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079 |
- #!/usr/bin/env python3
- """
- This file defines a set of system_info classes for getting
- information about various resources (libraries, library directories,
- include directories, etc.) in the system. 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 is not intended for general use.
- 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. DEFAULT section in site.cfg
- 4. System default search paths (see ``default_*`` variables below).
- Only the first complete match is returned.
- Currently, the following classes are available, along with their section names:
- Numeric_info:Numeric
- _numpy_info:Numeric
- _pkg_config_info:None
- accelerate_info:accelerate
- agg2_info:agg2
- amd_info:amd
- atlas_3_10_blas_info:atlas
- atlas_3_10_blas_threads_info:atlas
- atlas_3_10_info:atlas
- atlas_3_10_threads_info:atlas
- atlas_blas_info:atlas
- atlas_blas_threads_info:atlas
- atlas_info:atlas
- atlas_threads_info:atlas
- blas64__opt_info:ALL # usage recommended (general ILP64 BLAS, 64_ symbol suffix)
- blas_ilp64_opt_info:ALL # usage recommended (general ILP64 BLAS)
- blas_ilp64_plain_opt_info:ALL # usage recommended (general ILP64 BLAS, no symbol suffix)
- blas_info:blas
- blas_mkl_info:mkl
- blas_opt_info:ALL # usage recommended
- blas_src_info:blas_src
- blis_info:blis
- boost_python_info:boost_python
- dfftw_info:fftw
- dfftw_threads_info:fftw
- djbfft_info:djbfft
- f2py_info:ALL
- fft_opt_info:ALL
- fftw2_info:fftw
- fftw3_info:fftw3
- fftw_info:fftw
- fftw_threads_info:fftw
- flame_info:flame
- freetype2_info:freetype2
- gdk_2_info:gdk_2
- gdk_info:gdk
- gdk_pixbuf_2_info:gdk_pixbuf_2
- gdk_pixbuf_xlib_2_info:gdk_pixbuf_xlib_2
- gdk_x11_2_info:gdk_x11_2
- gtkp_2_info:gtkp_2
- gtkp_x11_2_info:gtkp_x11_2
- lapack64__opt_info:ALL # usage recommended (general ILP64 LAPACK, 64_ symbol suffix)
- lapack_atlas_3_10_info:atlas
- lapack_atlas_3_10_threads_info:atlas
- lapack_atlas_info:atlas
- lapack_atlas_threads_info:atlas
- lapack_ilp64_opt_info:ALL # usage recommended (general ILP64 LAPACK)
- lapack_ilp64_plain_opt_info:ALL # usage recommended (general ILP64 LAPACK, no symbol suffix)
- lapack_info:lapack
- lapack_mkl_info:mkl
- lapack_opt_info:ALL # usage recommended
- lapack_src_info:lapack_src
- mkl_info:mkl
- numarray_info:numarray
- numerix_info:numerix
- numpy_info:numpy
- openblas64__info:openblas64_
- openblas64__lapack_info:openblas64_
- openblas_clapack_info:openblas
- openblas_ilp64_info:openblas_ilp64
- openblas_ilp64_lapack_info:openblas_ilp64
- openblas_info:openblas
- openblas_lapack_info:openblas
- sfftw_info:fftw
- sfftw_threads_info:fftw
- system_info:ALL
- umfpack_info:umfpack
- wx_info:wx
- x11_info:x11
- xft_info:xft
- Example:
- ----------
- [DEFAULT]
- # default section
- 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]
- libraries = rfftw, fftw
- [atlas]
- library_dirs = /usr/lib/3dnow:/usr/lib/3dnow/atlas
- # for overriding the names of the atlas libraries
- libraries = lapack, f77blas, cblas, atlas
- [x11]
- library_dirs = /usr/X11R6/lib
- include_dirs = /usr/X11R6/include
- ----------
- Note that the ``libraries`` key is the default setting for libraries.
- 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.
- """
- import sys
- import os
- import re
- import copy
- import warnings
- import subprocess
- import textwrap
- from glob import glob
- from functools import reduce
- 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 sysconfig
- from numpy.distutils import log
- from distutils.util import get_platform
- from numpy.distutils.exec_command import (
- find_executable, filepath_from_subprocess_output,
- )
- 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 import customized_ccompiler as _customized_ccompiler
- from numpy.distutils import _shell_utils
- import distutils.ccompiler
- import tempfile
- import shutil
- __all__ = ['system_info']
- # Determine number of bits
- import platform
- _bits = {'32bit': 32, '64bit': 64}
- platform_bits = _bits[platform.architecture()[0]]
- global_compiler = None
- def customized_ccompiler():
- global global_compiler
- if not global_compiler:
- global_compiler = _customized_ccompiler()
- return global_compiler
- 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(sysconfig.get_config_var('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)
- # 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.
- vcpkg = shutil.which('vcpkg')
- if vcpkg:
- vcpkg_dir = os.path.dirname(vcpkg)
- if platform.architecture()[0] == '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'])
- with open(os.devnull, 'w') as tmp:
- try:
- 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)]
- 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 is_symlink_to_accelerate(filename):
- accelpath = '/System/Library/Frameworks/Accelerate.framework'
- return (sys.platform == 'darwin' and os.path.islink(filename) and
- os.path.realpath(filename).startswith(accelpath))
- _accel_msg = (
- 'Found {filename}, but that file is a symbolic link to the '
- 'MacOS Accelerate framework, which is not supported by NumPy. '
- 'You must configure the build to use a different optimized library, '
- 'or disable the use of optimized BLAS and LAPACK by setting the '
- 'environment variables NPY_BLAS_ORDER="" and NPY_LAPACK_ORDER="" '
- 'before building NumPy.'
- )
- 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 _parse_env_order(base_order, env):
- """ Parse an environment variable `env` by splitting with "," and only returning elements from `base_order`
- This method will sequence the environment variable and check for their invidual elements in `base_order`.
- The items in the environment variable may be negated via '^item' or '!itema,itemb'.
- It must start with ^/! to negate all options.
- Raises
- ------
- ValueError: for mixed negated and non-negated orders or multiple negated orders
- Parameters
- ----------
- base_order : list of str
- the base list of orders
- env : str
- the environment variable to be parsed, if none is found, `base_order` is returned
- Returns
- -------
- allow_order : list of str
- allowed orders in lower-case
- unknown_order : list of str
- for values not overlapping with `base_order`
- """
- order_str = os.environ.get(env, None)
- # ensure all base-orders are lower-case (for easier comparison)
- base_order = [order.lower() for order in base_order]
- if order_str is None:
- return base_order, []
- neg = order_str.startswith('^') or order_str.startswith('!')
- # Check format
- order_str_l = list(order_str)
- sum_neg = order_str_l.count('^') + order_str_l.count('!')
- if neg:
- if sum_neg > 1:
- raise ValueError(f"Environment variable '{env}' may only contain a single (prefixed) negation: {order_str}")
- # remove prefix
- order_str = order_str[1:]
- elif sum_neg > 0:
- raise ValueError(f"Environment variable '{env}' may not mix negated an non-negated items: {order_str}")
- # Split and lower case
- orders = order_str.lower().split(',')
- # to inform callee about non-overlapping elements
- unknown_order = []
- # if negated, we have to remove from the order
- if neg:
- allow_order = base_order.copy()
- for order in orders:
- if not order:
- continue
- if order not in base_order:
- unknown_order.append(order)
- continue
- if order in allow_order:
- allow_order.remove(order)
- else:
- allow_order = []
- for order in orders:
- if not order:
- continue
- if order not in base_order:
- unknown_order.append(order)
- continue
- if order not in allow_order:
- allow_order.append(order)
- return allow_order, unknown_order
- 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
- 'flame': flame_info, # use lapack_opt instead
- '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
- 'openblas64_': openblas64__info,
- 'openblas64__lapack': openblas64__lapack_info,
- 'openblas_ilp64': openblas_ilp64_info,
- 'openblas_ilp64_lapack': openblas_ilp64_lapack_info,
- '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,
- 'lapack_ilp64_opt': lapack_ilp64_opt_info,
- 'lapack_ilp64_plain_opt': lapack_ilp64_plain_opt_info,
- 'lapack64__opt': lapack64__opt_info,
- 'blas_opt': blas_opt_info,
- 'blas_ilp64_opt': blas_ilp64_opt_info,
- 'blas_ilp64_plain_opt': blas_ilp64_plain_opt_info,
- 'blas64__opt': blas64__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 AliasedOptionError(DistutilsError):
- """
- Aliases entries in config files should not be existing.
- In section '{section}' we found multiple appearances of options {options}."""
- class AtlasNotFoundError(NotFoundError):
- """
- Atlas (http://github.com/math-atlas/math-atlas) 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 FlameNotFoundError(NotFoundError):
- """
- FLAME (http://www.cs.utexas.edu/~flame/web/) libraries not found.
- Directories to search for the libraries can be specified in the
- numpy/distutils/site.cfg file (section [flame])."""
- 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 LapackILP64NotFoundError(NotFoundError):
- """
- 64-bit Lapack libraries not found.
- Known libraries in numpy/distutils/site.cfg file are:
- openblas64_, openblas_ilp64
- """
- class BlasOptNotFoundError(NotFoundError):
- """
- Optimized (vendor) Blas libraries are not found.
- Falls back to netlib Blas library which has worse performance.
- A better performance should be easily gained by switching
- Blas library."""
- 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 BlasILP64NotFoundError(NotFoundError):
- """
- 64-bit Blas libraries not found.
- Known libraries in numpy/distutils/site.cfg file are:
- openblas64_, openblas_ilp64
- """
- 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:
- """ get_info() is the only public method. Don't use others.
- """
- dir_env_var = None
- # XXX: search_static_first is disabled by default, may disappear in
- # future unless it is proved to be useful.
- search_static_first = 0
- # The base-class section name is a random word "ALL" and is not really
- # intended for general use. It cannot be None nor can it be DEFAULT as
- # these break the ConfigParser. See gh-15338
- section = 'ALL'
- saved_results = {}
- notfounderror = NotFoundError
- def __init__(self,
- default_lib_dirs=default_lib_dirs,
- default_include_dirs=default_include_dirs,
- ):
- 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 get_option_single(self, *options):
- """ Ensure that only one of `options` are found in the section
- Parameters
- ----------
- *options : list of str
- a list of options to be found in the section (``self.section``)
- Returns
- -------
- str :
- the option that is uniquely found in the section
- Raises
- ------
- AliasedOptionError :
- in case more than one of the options are found
- """
- found = [self.cp.has_option(self.section, opt) for opt in options]
- if sum(found) == 1:
- return options[found.index(True)]
- elif sum(found) == 0:
- # nothing is found anyways
- return options[0]
- # Else we have more than 1 key found
- if AliasedOptionError.__doc__ is None:
- raise AliasedOptionError()
- raise AliasedOptionError(AliasedOptionError.__doc__.format(
- section=self.section, options='[{}]'.format(', '.join(options))))
- 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 dictionary 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 log.get_threshold() <= log.INFO 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().replace(':',',') 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:
- # p[0] is the full path to the binary library file.
- if is_symlink_to_accelerate(p[0]):
- raise RuntimeError(_accel_msg.format(filename=p[0]))
- 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:
- if lib[0] == '-':
- found_libs.append(lib)
- continue
- 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)
- 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()
- opt = self.get_option_single(self.section + '_libs', 'libraries')
- libs = self.get_libs(opt, 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
- 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 sub_dir in dirs:
- if os.path.isdir(os.path.join(sub_dir, 'lib')):
- return sub_dir
- 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()
- opt = self.get_option_single('mkl_libs', 'libraries')
- mkl_libs = self.get_libs(opt, 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 = {}
- opt = self.get_option_single('atlas_libs', 'libraries')
- atlas_libs = self.get_libs(opt, 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 = textwrap.dedent("""
- *********************************************************************
- 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 = textwrap.dedent("""
- *********************************************************************
- 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 = {}
- opt = self.get_option_single('atlas_libs', 'libraries')
- atlas_libs = self.get_libs(opt, 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 = {}
- opt = self.get_option_single('atlas_lib', 'libraries')
- atlas_libs = self.get_libs(opt, 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()
- opt = self.get_option_single('lapack_libs', 'libraries')
- lapack_libs = self.get_libs(opt, 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,
- )
- 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,
- )
- if not s:
- warnings.warn(textwrap.dedent("""
- *****************************************************
- 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)
- elif 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
- # List of all known LAPACK libraries, in the default order
- lapack_order = ['mkl', 'openblas', 'flame', 'atlas', 'lapack']
- order_env_var_name = 'NPY_LAPACK_ORDER'
- def _calc_info_mkl(self):
- info = get_info('lapack_mkl')
- if info:
- self.set_info(**info)
- return True
- return False
- def _calc_info_openblas(self):
- info = get_info('openblas_lapack')
- if info:
- self.set_info(**info)
- return True
- info = get_info('openblas_clapack')
- if info:
- self.set_info(**info)
- return True
- return False
- def _calc_info_flame(self):
- info = get_info('flame')
- if info:
- self.set_info(**info)
- return True
- return False
- def _calc_info_atlas(self):
- info = get_info('atlas_3_10_threads')
- if not info:
- info = get_info('atlas_3_10')
- if not info:
- info = get_info('atlas_threads')
- if not info:
- info = get_info('atlas')
- if info:
- # Figure out if ATLAS has lapack...
- # If not we need the lapack library, but not BLAS!
- l = info.get('define_macros', [])
- if ('ATLAS_WITH_LAPACK_ATLAS', None) in l \
- or ('ATLAS_WITHOUT_LAPACK', None) in l:
- # Get LAPACK (with possible warnings)
- # If not found we don't accept anything
- # since we can't use ATLAS with LAPACK!
- lapack_info = self._get_info_lapack()
- if not lapack_info:
- return False
- dict_append(info, **lapack_info)
- self.set_info(**info)
- return True
- return False
- def _calc_info_accelerate(self):
- info = get_info('accelerate')
- if info:
- self.set_info(**info)
- return True
- return False
- def _get_info_blas(self):
- # Default to get the optimized BLAS implementation
- info = get_info('blas_opt')
- if not info:
- warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=3)
- info_src = get_info('blas_src')
- if not info_src:
- warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=3)
- return {}
- dict_append(info, libraries=[('fblas_src', info_src)])
- return info
- def _get_info_lapack(self):
- info = get_info('lapack')
- if not info:
- warnings.warn(LapackNotFoundError.__doc__ or '', stacklevel=3)
- info_src = get_info('lapack_src')
- if not info_src:
- warnings.warn(LapackSrcNotFoundError.__doc__ or '', stacklevel=3)
- return {}
- dict_append(info, libraries=[('flapack_src', info_src)])
- return info
- def _calc_info_lapack(self):
- info = self._get_info_lapack()
- if info:
- info_blas = self._get_info_blas()
- dict_append(info, **info_blas)
- dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
- self.set_info(**info)
- return True
- return False
- def _calc_info(self, name):
- return getattr(self, '_calc_info_{}'.format(name))()
- def calc_info(self):
- lapack_order, unknown_order = _parse_env_order(self.lapack_order, self.order_env_var_name)
- if len(unknown_order) > 0:
- raise ValueError("lapack_opt_info user defined "
- "LAPACK order has unacceptable "
- "values: {}".format(unknown_order))
- for lapack in lapack_order:
- if self._calc_info(lapack):
- return
- if 'lapack' not in lapack_order:
- # Since the user may request *not* to use any library, we still need
- # to raise warnings to signal missing packages!
- warnings.warn(LapackNotFoundError.__doc__ or '', stacklevel=2)
- warnings.warn(LapackSrcNotFoundError.__doc__ or '', stacklevel=2)
- class _ilp64_opt_info_mixin:
- symbol_suffix = None
- symbol_prefix = None
- def _check_info(self, info):
- macros = dict(info.get('define_macros', []))
- prefix = macros.get('BLAS_SYMBOL_PREFIX', '')
- suffix = macros.get('BLAS_SYMBOL_SUFFIX', '')
- if self.symbol_prefix not in (None, prefix):
- return False
- if self.symbol_suffix not in (None, suffix):
- return False
- return bool(info)
- class lapack_ilp64_opt_info(lapack_opt_info, _ilp64_opt_info_mixin):
- notfounderror = LapackILP64NotFoundError
- lapack_order = ['openblas64_', 'openblas_ilp64']
- order_env_var_name = 'NPY_LAPACK_ILP64_ORDER'
- def _calc_info(self, name):
- info = get_info(name + '_lapack')
- if self._check_info(info):
- self.set_info(**info)
- return True
- return False
- class lapack_ilp64_plain_opt_info(lapack_ilp64_opt_info):
- # Same as lapack_ilp64_opt_info, but fix symbol names
- symbol_prefix = ''
- symbol_suffix = ''
- class lapack64__opt_info(lapack_ilp64_opt_info):
- symbol_prefix = ''
- symbol_suffix = '64_'
- class blas_opt_info(system_info):
- notfounderror = BlasNotFoundError
- # List of all known BLAS libraries, in the default order
- blas_order = ['mkl', 'blis', 'openblas', 'atlas', 'blas']
- order_env_var_name = 'NPY_BLAS_ORDER'
- def _calc_info_mkl(self):
- info = get_info('blas_mkl')
- if info:
- self.set_info(**info)
- return True
- return False
- def _calc_info_blis(self):
- info = get_info('blis')
- if info:
- self.set_info(**info)
- return True
- return False
- def _calc_info_openblas(self):
- info = get_info('openblas')
- if info:
- self.set_info(**info)
- return True
- return False
- def _calc_info_atlas(self):
- info = get_info('atlas_3_10_blas_threads')
- if not info:
- info = get_info('atlas_3_10_blas')
- if not info:
- info = get_info('atlas_blas_threads')
- if not info:
- info = get_info('atlas_blas')
- if info:
- self.set_info(**info)
- return True
- return False
- def _calc_info_accelerate(self):
- info = get_info('accelerate')
- if info:
- self.set_info(**info)
- return True
- return False
- def _calc_info_blas(self):
- # Warn about a non-optimized BLAS library
- warnings.warn(BlasOptNotFoundError.__doc__ or '', stacklevel=3)
- info = {}
- dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
- blas = get_info('blas')
- if blas:
- dict_append(info, **blas)
- else:
- # Not even BLAS was found!
- warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=3)
- blas_src = get_info('blas_src')
- if not blas_src:
- warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=3)
- return False
- dict_append(info, libraries=[('fblas_src', blas_src)])
- self.set_info(**info)
- return True
- def _calc_info(self, name):
- return getattr(self, '_calc_info_{}'.format(name))()
- def calc_info(self):
- blas_order, unknown_order = _parse_env_order(self.blas_order, self.order_env_var_name)
- if len(unknown_order) > 0:
- raise ValueError("blas_opt_info user defined BLAS order has unacceptable values: {}".format(unknown_order))
- for blas in blas_order:
- if self._calc_info(blas):
- return
- if 'blas' not in blas_order:
- # Since the user may request *not* to use any library, we still need
- # to raise warnings to signal missing packages!
- warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=2)
- warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=2)
- class blas_ilp64_opt_info(blas_opt_info, _ilp64_opt_info_mixin):
- notfounderror = BlasILP64NotFoundError
- blas_order = ['openblas64_', 'openblas_ilp64']
- order_env_var_name = 'NPY_BLAS_ILP64_ORDER'
- def _calc_info(self, name):
- info = get_info(name)
- if self._check_info(info):
- self.set_info(**info)
- return True
- return False
- class blas_ilp64_plain_opt_info(blas_ilp64_opt_info):
- symbol_prefix = ''
- symbol_suffix = ''
- class blas64__opt_info(blas_ilp64_opt_info):
- symbol_prefix = ''
- symbol_suffix = '64_'
- class cblas_info(system_info):
- section = 'cblas'
- dir_env_var = 'CBLAS'
- # No default as it's used only in blas_info
- _lib_names = []
- notfounderror = BlasNotFoundError
- 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()
- opt = self.get_option_single('blas_libs', 'libraries')
- blas_libs = self.get_libs(opt, 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 get_cblas_libs 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?
- # If cblas is given as an option, use those
- cblas_info_obj = cblas_info()
- cblas_opt = cblas_info_obj.get_option_single('cblas_libs', 'libraries')
- cblas_libs = cblas_info_obj.get_libs(cblas_opt, None)
- if cblas_libs:
- info['libraries'] = cblas_libs + blas_libs
- info['define_macros'] = [('HAVE_CBLAS', None)]
- else:
- lib = self.get_cblas_libs(info)
- if lib is not None:
- info['language'] = 'c'
- info['libraries'] = lib
- info['define_macros'] = [('HAVE_CBLAS', None)]
- self.set_info(**info)
- def get_cblas_libs(self, info):
- """ Check whether we can link with CBLAS interface
- This method will search through several combinations of libraries
- to check whether CBLAS is present:
- 1. Libraries in ``info['libraries']``, as is
- 2. As 1. but also explicitly adding ``'cblas'`` as a library
- 3. As 1. but also explicitly adding ``'blas'`` as a library
- 4. Check only library ``'cblas'``
- 5. Check only library ``'blas'``
- Parameters
- ----------
- info : dict
- system information dictionary for compilation and linking
- Returns
- -------
- libraries : list of str or None
- a list of libraries that enables the use of CBLAS interface.
- Returns None if not found or a compilation error occurs.
- Since 1.17 returns a list.
- """
- # primitive cblas check by looking for the header and trying to link
- # cblas or blas
- c = customized_ccompiler()
- tmpdir = tempfile.mkdtemp()
- s = textwrap.dedent("""\
- #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())
- except (distutils.ccompiler.CompileError, distutils.ccompiler.LinkError):
- return None
- # check we can link (find library)
- # some systems have separate cblas and blas libs.
- for libs in [info['libraries'], ['cblas'] + info['libraries'],
- ['blas'] + info['libraries'], ['cblas'], ['blas']]:
- try:
- c.link_executable(obj, os.path.join(tmpdir, "a.out"),
- libraries=libs,
- library_dirs=info['library_dirs'],
- extra_postargs=info.get('extra_link_args', []))
- return libs
- except distutils.ccompiler.LinkError:
- pass
- finally:
- shutil.rmtree(tmpdir)
- return None
- class openblas_info(blas_info):
- section = 'openblas'
- dir_env_var = 'OPENBLAS'
- _lib_names = ['openblas']
- _require_symbols = []
- notfounderror = BlasNotFoundError
- @property
- def symbol_prefix(self):
- try:
- return self.cp.get(self.section, 'symbol_prefix')
- except NoOptionError:
- return ''
- @property
- def symbol_suffix(self):
- try:
- return self.cp.get(self.section, 'symbol_suffix')
- except NoOptionError:
- return ''
- def _calc_info(self):
- c = customized_ccompiler()
- lib_dirs = self.get_lib_dirs()
- # Prefer to use libraries over openblas_libs
- opt = self.get_option_single('openblas_libs', 'libraries')
- openblas_libs = self.get_libs(opt, 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
- skip_symbol_check = True
- elif info:
- skip_symbol_check = False
- info['language'] = 'c'
- if info is None:
- return None
- # Add extra info for OpenBLAS
- extra_info = self.calc_extra_info()
- dict_append(info, **extra_info)
- if not (skip_symbol_check or self.check_symbols(info)):
- return None
- info['define_macros'] = [('HAVE_CBLAS', None)]
- if self.symbol_prefix:
- info['define_macros'] += [('BLAS_SYMBOL_PREFIX', self.symbol_prefix)]
- if self.symbol_suffix:
- info['define_macros'] += [('BLAS_SYMBOL_SUFFIX', self.symbol_suffix)]
- return info
- def calc_info(self):
- info = self._calc_info()
- if info is not 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
- basename = self.__class__.__name__
- tmpdir = os.path.join(os.getcwd(), 'build', basename)
- if not os.path.isdir(tmpdir):
- os.makedirs(tmpdir)
- info = {'library_dirs': [tmpdir],
- 'libraries': [basename],
- 'language': 'f77'}
- fake_lib_file = os.path.join(tmpdir, basename + '.fobjects')
- fake_clib_file = os.path.join(tmpdir, basename + '.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
- def check_symbols(self, info):
- res = False
- c = customized_ccompiler()
- tmpdir = tempfile.mkdtemp()
- prototypes = "\n".join("void %s%s%s();" % (self.symbol_prefix,
- symbol_name,
- self.symbol_suffix)
- for symbol_name in self._require_symbols)
- calls = "\n".join("%s%s%s();" % (self.symbol_prefix,
- symbol_name,
- self.symbol_suffix)
- for symbol_name in self._require_symbols)
- s = textwrap.dedent("""\
- %(prototypes)s
- int main(int argc, const char *argv[])
- {
- %(calls)s
- return 0;
- }""") % dict(prototypes=prototypes, calls=calls)
- 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 = []
- 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_lapack_info(openblas_info):
- section = 'openblas'
- dir_env_var = 'OPENBLAS'
- _lib_names = ['openblas']
- _require_symbols = ['zungqr_']
- notfounderror = BlasNotFoundError
- class openblas_clapack_info(openblas_lapack_info):
- _lib_names = ['openblas', 'lapack']
- class openblas_ilp64_info(openblas_info):
- section = 'openblas_ilp64'
- dir_env_var = 'OPENBLAS_ILP64'
- _lib_names = ['openblas64']
- _require_symbols = ['dgemm_', 'cblas_dgemm']
- notfounderror = BlasILP64NotFoundError
- def _calc_info(self):
- info = super()._calc_info()
- if info is not None:
- info['define_macros'] += [('HAVE_BLAS_ILP64', None)]
- return info
- class openblas_ilp64_lapack_info(openblas_ilp64_info):
- _require_symbols = ['dgemm_', 'cblas_dgemm', 'zungqr_', 'LAPACKE_zungqr']
- def _calc_info(self):
- info = super()._calc_info()
- if info:
- info['define_macros'] += [('HAVE_LAPACKE', None)]
- return info
- class openblas64__info(openblas_ilp64_info):
- # ILP64 Openblas, with default symbol suffix
- section = 'openblas64_'
- dir_env_var = 'OPENBLAS64_'
- _lib_names = ['openblas64_']
- symbol_suffix = '64_'
- symbol_prefix = ''
- class openblas64__lapack_info(openblas_ilp64_lapack_info, openblas64__info):
- pass
- 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()
- opt = self.get_option_single('blis_libs', 'libraries')
- blis_libs = self.get_libs(opt, 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 flame_info(system_info):
- """ Usage of libflame for LAPACK operations
- This requires libflame to be compiled with lapack wrappers:
- ./configure --enable-lapack2flame ...
- Be aware that libflame 5.1.0 has some missing names in the shared library, so
- if you have problems, try the static flame library.
- """
- section = 'flame'
- _lib_names = ['flame']
- notfounderror = FlameNotFoundError
- def check_embedded_lapack(self, info):
- """ libflame does not necessarily have a wrapper for fortran LAPACK, we need to check """
- c = customized_ccompiler()
- tmpdir = tempfile.mkdtemp()
- s = textwrap.dedent("""\
- 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
- extra_args = info.get('extra_link_args', [])
- 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)
- return True
- except distutils.ccompiler.LinkError:
- return False
- finally:
- shutil.rmtree(tmpdir)
- def calc_info(self):
- lib_dirs = self.get_lib_dirs()
- flame_libs = self.get_libs('libraries', self._lib_names)
- info = self.check_libs2(lib_dirs, flame_libs, [])
- if info is None:
- return
- if self.check_embedded_lapack(info):
- # check if the user has supplied all information required
- self.set_info(**info)
- else:
- # Try and get the BLAS lib to see if we can get it to work
- blas_info = get_info('blas_opt')
- if not blas_info:
- # since we already failed once, this ain't going to work either
- return
- # Now we need to merge the two dictionaries
- for key in blas_info:
- if isinstance(blas_info[key], list):
- info[key] = info.get(key, []) + blas_info[key]
- elif isinstance(blas_info[key], tuple):
- info[key] = info.get(key, ()) + blas_info[key]
- else:
- info[key] = info.get(key, '') + blas_info[key]
- # Now check again
- if self.check_embedded_lapack(info):
- self.set_info(**info)
- class accelerate_info(system_info):
- section = 'accelerate'
- _lib_names = ['accelerate', 'veclib']
- 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', self._lib_names)
- 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'])
- 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'])
- 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
- _lib_names = ['X11']
- 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()
- opt = self.get_option_single('x11_libs', 'libraries')
- x11_libs = self.get_libs(opt, self._lib_names)
- 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(sysconfig.get_path('include'))
- except ImportError:
- pass
- py_incl_dir = sysconfig.get_path('include')
- include_dirs.append(py_incl_dir)
- py_pincl_dir = sysconfig.get_path('platinclude')
- 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 as e:
- msg1 = str(e)
- try:
- import Numeric # noqa: F401
- which = "numeric", "defaulted"
- except ImportError as e:
- msg2 = str(e)
- try:
- import numarray # noqa: F401
- which = "numarray", "defaulted"
- except ImportError as e:
- msg3 = str(e)
- 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 = [sysconfig.get_path('include')]
- py_pincl_dir = sysconfig.get_path('platinclude')
- 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()
- opt = self.get_option_single('amd_libs', 'libraries')
- amd_libs = self.get_libs(opt, 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()
- opt = self.get_option_single('umfpack_libs', 'libraries')
- umfpack_libs = self.get_libs(opt, 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()
|