Overhaul numpy package (#12170)

* Add numpy 1.17.0

* Overhaul numpy package

* Flake8 fixes

* Undefined reference fix

* HeaderList and LibraryList need an arg

* veclibfort has no headers

* Add patch for older versions of py-numpy

* Remove py-meep hack from py-numpy package

* libflame: always add max arg hack flag

* Fix build with GCC 4.8

* Compiler flags come from self.compiler

* Only apply -std=c99 to cflags

* Try to fix libflame package

* Fix ATLAS build on macOS

* --force-clang flag added in 3.10.3
This commit is contained in:
Adam J. Stewart 2019-08-06 18:20:23 -05:00 committed by GitHub
parent 15884a679b
commit 66e9b1279a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 537 additions and 127 deletions

View file

@ -18,17 +18,15 @@ class Atlas(Package):
"""
homepage = "http://math-atlas.sourceforge.net/"
version('3.11.39', '5f3252fa980f5f060f93edd4669321e2',
url='http://sourceforge.net/projects/math-atlas/files/Developer%20%28unstable%29/3.11.39/atlas3.11.39.tar.bz2')
# Developer (unstable)
version('3.11.41', sha256='477d567a8d683e891d786e9e8bb6ad6659daa9ba18e8dd0e2f70b7a54095f8de')
version('3.11.39', '5f3252fa980f5f060f93edd4669321e2')
version('3.11.34', '0b6c5389c095c4c8785fd0f724ec6825')
version('3.11.34', '0b6c5389c095c4c8785fd0f724ec6825',
url='http://sourceforge.net/projects/math-atlas/files/Developer%20%28unstable%29/3.11.34/atlas3.11.34.tar.bz2')
# Stable
version('3.10.3', 'd6ce4f16c2ad301837cfb3dade2f7cef', preferred=True)
version('3.10.2', 'a4e21f343dec8f22e7415e339f09f6da')
version('3.10.3', 'd6ce4f16c2ad301837cfb3dade2f7cef',
url='https://sourceforge.net/projects/math-atlas/files/Stable/3.10.3/atlas3.10.3.tar.bz2')
version('3.10.2', 'a4e21f343dec8f22e7415e339f09f6da',
url='https://sourceforge.net/projects/math-atlas/files/Stable/3.10.2/atlas3.10.2.tar.bz2', preferred=True)
# not all packages (e.g. Trilinos@12.6.3) stopped using deprecated in 3.6.0
# Lapack routines. Stick with 3.5.0 until this is fixed.
resource(name='lapack',
@ -57,6 +55,16 @@ class Atlas(Package):
parallel = False
def url_for_version(self, version):
url = 'https://sourceforge.net/projects/math-atlas/files/'
if version >= Version('3.11'):
url += 'Developer%20%28unstable%29/{0}/atlas{0}.tar.bz2'
else:
url += 'Stable/{0}/atlas{0}.tar.bz2'
return url.format(version)
def patch(self):
# Disable thread check. LLNL's environment does not allow
# disabling of CPU throttling in a way that ATLAS actually
@ -94,6 +102,11 @@ def install(self, spec, prefix):
'-C', 'if', spack_f77
])
# Workaround for macOS Clang:
# http://math-atlas.sourceforge.net/atlas_install/node66.html
if spec.satisfies('@3.10.3: %clang platform=darwin'):
options.append('--force-clang=' + spack_cc)
# Lapack resource to provide full lapack build. Note that
# ATLAS only provides a few LAPACK routines natively.
options.append('--with-netlib-lapack-tarfile=%s' %

View file

@ -51,6 +51,12 @@ class Libflame(AutotoolsPackage):
# https://groups.google.com/forum/#!topic/libflame-discuss/lQKEfjyudOY
patch('Makefile_5.1.0.patch', when='@5.1.0')
def flag_handler(self, name, flags):
# -std=gnu99 at least required, old versions of GCC default to -std=c90
if self.spec.satisfies('%gcc@:5.1') and name == 'cflags':
flags.append('-std=gnu99')
return (flags, None, None)
def configure_args(self):
config_args = []
@ -83,7 +89,6 @@ def configure_args(self):
config_args.append("--disable-supermatrix")
# https://github.com/flame/libflame/issues/21
if self.spec.satisfies('@5.1.99:'):
config_args.append("--enable-max-arg-list-hack")
return config_args

View file

@ -38,7 +38,10 @@ def setup_file(self):
def common_args(self, spec, prefix):
include_dirs = [
spec['meep'].prefix.include,
spec['py-numpy'].include
os.path.join(
spec['py-numpy'].prefix,
spec['python'].package.python_include_dir
)
]
library_dirs = [

View file

@ -0,0 +1,347 @@
Allows you to specify order of BLAS/LAPACK preference
https://github.com/numpy/numpy/pull/13132
diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py
index 806f4f7d3..0480d7b5a 100644
--- a/numpy/distutils/system_info.py
+++ b/numpy/distutils/system_info.py
@@ -474,6 +474,13 @@ class LapackSrcNotFoundError(LapackNotFoundError):
the LAPACK_SRC environment variable."""
+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.
@@ -1541,139 +1548,219 @@ Make sure that -lgfortran is used for C++ extensions.
class lapack_opt_info(system_info):
notfounderror = LapackNotFoundError
+ # Default order of LAPACK checks
+ lapack_order = ['mkl', 'openblas', 'atlas', 'accelerate', 'lapack']
- def calc_info(self):
+ def _calc_info_mkl(self):
+ info = get_info('lapack_mkl')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- lapack_mkl_info = get_info('lapack_mkl')
- if lapack_mkl_info:
- self.set_info(**lapack_mkl_info)
- return
+ 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
- openblas_info = get_info('openblas_lapack')
- if openblas_info:
- self.set_info(**openblas_info)
- return
+ 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
- openblas_info = get_info('openblas_clapack')
- if openblas_info:
- self.set_info(**openblas_info)
- return
+ def _calc_info_accelerate(self):
+ info = get_info('accelerate')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- atlas_info = get_info('atlas_3_10_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_3_10')
- if not atlas_info:
- atlas_info = get_info('atlas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas')
-
- accelerate_info = get_info('accelerate')
- if accelerate_info and not atlas_info:
- self.set_info(**accelerate_info)
- return
+ 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
- need_lapack = 0
- need_blas = 0
- info = {}
- if atlas_info:
- l = atlas_info.get('define_macros', [])
- if ('ATLAS_WITH_LAPACK_ATLAS', None) in l \
- or ('ATLAS_WITHOUT_LAPACK', None) in l:
- need_lapack = 1
- info = atlas_info
+ 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
- else:
- warnings.warn(AtlasNotFoundError.__doc__, stacklevel=2)
- need_blas = 1
- need_lapack = 1
+ 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
- if need_lapack:
- lapack_info = get_info('lapack')
- #lapack_info = {} ## uncomment for testing
- if lapack_info:
- dict_append(info, **lapack_info)
- else:
- warnings.warn(LapackNotFoundError.__doc__, stacklevel=2)
- lapack_src_info = get_info('lapack_src')
- if not lapack_src_info:
- warnings.warn(LapackSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('flapack_src', lapack_src_info)])
-
- if need_blas:
- blas_info = get_info('blas')
- if blas_info:
- dict_append(info, **blas_info)
- else:
- warnings.warn(BlasNotFoundError.__doc__, stacklevel=2)
- blas_src_info = get_info('blas_src')
- if not blas_src_info:
- warnings.warn(BlasSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('fblas_src', blas_src_info)])
+ def calc_info(self):
+ user_order = os.environ.get('NPY_LAPACK_ORDER', None)
+ if user_order is None:
+ lapack_order = self.lapack_order
+ else:
+ # the user has requested the order of the
+ # check they are all in the available list, a COMMA SEPARATED list
+ user_order = user_order.lower().split(',')
+ non_existing = []
+ lapack_order = []
+ for order in user_order:
+ if order in self.lapack_order:
+ lapack_order.append(order)
+ elif len(order) > 0:
+ non_existing.append(order)
+ if len(non_existing) > 0:
+ raise ValueError("lapack_opt_info user defined "
+ "LAPACK order has unacceptable "
+ "values: {}".format(non_existing))
+
+ for lapack in lapack_order:
+ if getattr(self, '_calc_info_{}'.format(lapack))():
+ return
- self.set_info(**info)
- 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 blas_opt_info(system_info):
notfounderror = BlasNotFoundError
+ # Default order of BLAS checks
+ blas_order = ['mkl', 'blis', 'openblas', 'atlas', 'accelerate', 'blas']
- def calc_info(self):
+ def _calc_info_mkl(self):
+ info = get_info('blas_mkl')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- blas_mkl_info = get_info('blas_mkl')
- if blas_mkl_info:
- self.set_info(**blas_mkl_info)
- return
+ def _calc_info_blis(self):
+ info = get_info('blis')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- blis_info = get_info('blis')
- if blis_info:
- self.set_info(**blis_info)
- return
+ def _calc_info_openblas(self):
+ info = get_info('openblas')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- openblas_info = get_info('openblas')
- if openblas_info:
- self.set_info(**openblas_info)
- return
+ 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
- atlas_info = get_info('atlas_3_10_blas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_3_10_blas')
- if not atlas_info:
- atlas_info = get_info('atlas_blas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_blas')
-
- accelerate_info = get_info('accelerate')
- if accelerate_info and not atlas_info:
- self.set_info(**accelerate_info)
- return
+ def _calc_info_accelerate(self):
+ info = get_info('accelerate')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- need_blas = 0
+ def _calc_info_blas(self):
+ # Warn about a non-optimized BLAS library
+ warnings.warn(BlasOptNotFoundError.__doc__ or '', stacklevel=3)
info = {}
- if atlas_info:
- info = atlas_info
+ dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
+
+ blas = get_info('blas')
+ if blas:
+ dict_append(info, **blas)
else:
- warnings.warn(AtlasNotFoundError.__doc__, stacklevel=2)
- need_blas = 1
- dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
+ # Not even BLAS was found!
+ warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=3)
- if need_blas:
- blas_info = get_info('blas')
- if blas_info:
- dict_append(info, **blas_info)
- else:
- warnings.warn(BlasNotFoundError.__doc__, stacklevel=2)
- blas_src_info = get_info('blas_src')
- if not blas_src_info:
- warnings.warn(BlasSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('fblas_src', blas_src_info)])
+ 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
+ return True
+
+ def calc_info(self):
+ user_order = os.environ.get('NPY_BLAS_ORDER', None)
+ if user_order is None:
+ blas_order = self.blas_order
+ else:
+ # the user has requested the order of the
+ # check they are all in the available list
+ user_order = user_order.lower().split(',')
+ non_existing = []
+ blas_order = []
+ for order in user_order:
+ if order in self.blas_order:
+ blas_order.append(order)
+ elif len(order) > 0:
+ non_existing.append(order)
+ if len(non_existing) > 0:
+ raise ValueError("blas_opt_info user defined BLAS order has unacceptable values: {}".format(non_existing))
+
+ for blas in blas_order:
+ if getattr(self, '_calc_info_{}'.format(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_info(system_info):

View file

@ -15,8 +15,9 @@ class PyNumpy(PythonPackage):
number capabilities"""
homepage = "http://www.numpy.org/"
url = "https://pypi.io/packages/source/n/numpy/numpy-1.16.4.zip"
url = "https://pypi.io/packages/source/n/numpy/numpy-1.17.0.zip"
maintainers = ['adamjstewart']
install_time_test_callbacks = ['install_test', 'import_module_test']
import_modules = [
@ -26,6 +27,7 @@ class PyNumpy(PythonPackage):
'numpy.distutils.command', 'numpy.distutils.fcompiler'
]
version('1.17.0', sha256='951fefe2fb73f84c620bec4e001e80a80ddaa1b84dce244ded7f1e0cbe0ed34a')
version('1.16.4', sha256='7242be12a58fec245ee9734e625964b97cf7e3f2f7d016603f9e56660ce479c7')
version('1.16.3', sha256='78a6f89da87eeb48014ec652a65c4ffde370c036d780a995edaeb121d3625621')
version('1.16.2', sha256='6c692e3879dde0b67a9dc78f9bfb6f61c666b4562fd8619632d7043fb5b691b0')
@ -62,6 +64,8 @@ class PyNumpy(PythonPackage):
variant('lapack', default=True, description='Build with LAPACK support')
depends_on('python@2.7:2.8,3.4:', type=('build', 'run'))
depends_on('python@2.7:2.8,3.5:', type=('build', 'run'), when='@1.16:')
depends_on('python@3.5:', type=('build', 'run'), when='@1.17:')
depends_on('py-setuptools', type='build')
depends_on('blas', when='+blas')
depends_on('lapack', when='+lapack')
@ -69,129 +73,175 @@ class PyNumpy(PythonPackage):
depends_on('py-nose@1.0.0:', when='@:1.14', type='test')
depends_on('py-pytest', when='@1.15:', type='test')
def setup_dependent_package(self, module, dependent_spec):
python_version = self.spec['python'].version.up_to(2)
# Allows you to specify order of BLAS/LAPACK preference
# https://github.com/numpy/numpy/pull/13132
patch('blas-lapack-order.patch', when='@1.15:1.16')
self.spec.include = join_path(
self.prefix.lib,
'python{0}'.format(python_version),
'site-packages',
'numpy/core/include')
# GCC 4.8 is the minimum version that works
conflicts('%gcc@:4.7', msg='GCC 4.8+ required')
def patch(self):
def flag_handler(self, name, flags):
# -std=c99 at least required, old versions of GCC default to -std=c90
if self.spec.satisfies('%gcc@:5.1') and name == 'cflags':
flags.append(self.compiler.c99_flag)
return (flags, None, None)
@run_before('build')
def set_blas_lapack(self):
# https://numpy.org/devdocs/user/building.html
# https://github.com/numpy/numpy/blob/master/site.cfg.example
# Skip if no BLAS/LAPACK requested
spec = self.spec
if '+blas' not in spec and '+lapack' not in spec:
return
def write_library_dirs(f, dirs):
f.write('library_dirs=%s\n' % dirs)
if not ((platform.system() == "Darwin") and
f.write('library_dirs = {0}\n'.format(dirs))
if not ((platform.system() == 'Darwin') and
(Version(platform.mac_ver()[0]).up_to(2) == Version(
'10.12'))):
f.write('rpath=%s\n' % dirs)
# for build notes see http://www.scipy.org/scipylib/building/linux.html
blas_info = []
lapack_info = []
lapackblas_info = []
if '+lapack' in spec:
lapack_info += spec['lapack'].libs
f.write('rpath = {0}\n'.format(dirs))
blas_libs = LibraryList([])
blas_headers = HeaderList([])
if '+blas' in spec:
blas_info += spec['blas'].libs
blas_libs = spec['blas'].libs
blas_headers = spec['blas'].headers
lapackblas_info = lapack_info + blas_info
lapack_libs = LibraryList([])
lapack_headers = HeaderList([])
if '+lapack' in spec:
lapack_libs = spec['lapack'].libs
lapack_headers = spec['lapack'].headers
def write_empty_libs(f, provider):
f.write('[{0}]\n'.format(provider))
f.write('libraries=\n')
write_library_dirs(f, '')
lapackblas_libs = lapack_libs + blas_libs
lapackblas_headers = lapack_headers + blas_headers
if '+blas' in spec or '+lapack' in spec:
# note that one should not use [blas_opt] and [lapack_opt], see
# https://github.com/numpy/numpy/commit/ffd4332262ee0295cb942c94ed124f043d801eb6
blas_lib_names = ','.join(blas_libs.names)
blas_lib_dirs = ':'.join(blas_libs.directories)
blas_header_dirs = ':'.join(blas_headers.directories)
lapack_lib_names = ','.join(lapack_libs.names)
lapack_lib_dirs = ':'.join(lapack_libs.directories)
lapack_header_dirs = ':'.join(lapack_headers.directories)
lapackblas_lib_names = ','.join(lapackblas_libs.names)
lapackblas_lib_dirs = ':'.join(lapackblas_libs.directories)
lapackblas_header_dirs = ':'.join(lapackblas_headers.directories)
# Tell numpy where to find BLAS/LAPACK libraries
with open('site.cfg', 'w') as f:
# Unfortunately, numpy prefers to provide each BLAS/LAPACK
# differently.
blas_names = ','.join(blas_info.names)
blas_dirs = ':'.join(blas_info.directories)
lapack_names = ','.join(lapack_info.names)
lapack_dirs = ':'.join(lapack_info.directories)
lapackblas_names = ','.join(lapackblas_info.names)
lapackblas_dirs = ':'.join(lapackblas_info.directories)
if '^intel-mkl' in spec or '^intel-parallel-studio+mkl' in spec:
f.write('[mkl]\n')
# FIXME: as of @1.11.2, numpy does not work with separately
# specified threading and interface layers. A workaround is a
# terribly bad idea to use mkl_rt. In this case Spack will no
# longer be able to guarantee that one and the same variant of
# Blas/Lapack (32/64bit, threaded/serial) is used within the
# DAG. This may lead to a lot of hard-to-debug segmentation
# faults on user's side. Users may also break working
# installation by (unconsciously) setting environment variable
# to switch between different interface and threading layers
# dynamically. From this perspective it is no different from
# throwing away RPATH's and using LD_LIBRARY_PATH throughout
# Spack.
f.write('libraries = {0}\n'.format('mkl_rt'))
write_library_dirs(f, lapackblas_lib_dirs)
f.write('include_dirs = {0}\n'.format(lapackblas_header_dirs))
handled_blas_and_lapack = False
if '^blis' in spec:
f.write('[blis]\n')
f.write('libraries = {0}\n'.format(blas_lib_names))
write_library_dirs(f, blas_lib_dirs)
f.write('include_dirs = {0}\n'.format(blas_header_dirs))
# Special treatment for some (!) BLAS/LAPACK. Note that
# in this case library_dirs can not be specified within [ALL].
if '^openblas' in spec:
f.write('[openblas]\n')
f.write('libraries=%s\n' % lapackblas_names)
write_library_dirs(f, lapackblas_dirs)
handled_blas_and_lapack = True
else:
write_empty_libs(f, 'openblas')
f.write('libraries = {0}\n'.format(lapackblas_lib_names))
write_library_dirs(f, lapackblas_lib_dirs)
f.write('include_dirs = {0}\n'.format(lapackblas_header_dirs))
if '^mkl' in spec:
# numpy does not expect system libraries needed for MKL
# here.
# names = [x for x in names if x.startswith('mkl')]
# FIXME: as of @1.11.2, numpy does not work with separately
# specified threading and interface layers. A workaround is
# a terribly bad idea to use mkl_rt. In this case Spack
# will no longer be able to guarantee that one and the
# same variant of Blas/Lapack (32/64bit, threaded/serial)
# is used within the DAG. This may lead to a lot of
# hard-to-debug segmentation faults on user's side. Users
# may also break working installation by (unconsciously)
# setting environment variable to switch between different
# interface and threading layers dynamically. From this
# perspective it is no different from throwing away RPATH's
# and using LD_LIBRARY_PATH throughout Spack.
f.write('[mkl]\n')
f.write('mkl_libs=%s\n' % 'mkl_rt')
write_library_dirs(f, lapackblas_dirs)
handled_blas_and_lapack = True
else:
# Without explicitly setting the search directories to be
# an empty list, numpy may retrieve and use mkl libs from
# the system.
write_empty_libs(f, 'mkl')
if '^libflame' in spec:
f.write('[flame]\n')
f.write('libraries = {0}\n'.format(lapack_lib_names))
write_library_dirs(f, lapack_lib_dirs)
f.write('include_dirs = {0}\n'.format(lapack_header_dirs))
if '^atlas' in spec:
f.write('[atlas]\n')
f.write('atlas_libs=%s\n' % lapackblas_names)
write_library_dirs(f, lapackblas_dirs)
handled_blas_and_lapack = True
else:
write_empty_libs(f, 'atlas')
f.write('libraries = {0}\n'.format(lapackblas_lib_names))
write_library_dirs(f, lapackblas_lib_dirs)
f.write('include_dirs = {0}\n'.format(lapackblas_header_dirs))
if '^veclibfort' in spec:
f.write('[accelerate]\n')
f.write('libraries = {0}\n'.format(lapackblas_lib_names))
write_library_dirs(f, lapackblas_lib_dirs)
if '^netlib-lapack' in spec:
# netlib requires blas and lapack listed
# separately so that scipy can find them
if spec.satisfies('+blas'):
f.write('[blas]\n')
f.write('blas_libs=%s\n' % blas_names)
write_library_dirs(f, blas_dirs)
f.write('libraries = {0}\n'.format(blas_lib_names))
write_library_dirs(f, blas_lib_dirs)
f.write('include_dirs = {0}\n'.format(blas_header_dirs))
if spec.satisfies('+lapack'):
f.write('[lapack]\n')
f.write('lapack_libs=%s\n' % lapack_names)
write_library_dirs(f, lapack_dirs)
handled_blas_and_lapack = True
f.write('libraries = {0}\n'.format(lapack_lib_names))
write_library_dirs(f, lapack_lib_dirs)
f.write('include_dirs = {0}\n'.format(lapack_header_dirs))
if not handled_blas_and_lapack:
# The section title for the defaults changed in @1.10, see
# https://github.com/numpy/numpy/blob/master/site.cfg.example
if spec.satisfies('@:1.9.2'):
f.write('[DEFAULT]\n')
def setup_environment(self, spack_env, run_env):
# Tell numpy which BLAS/LAPACK libraries we want to use.
# https://github.com/numpy/numpy/pull/13132
# https://numpy.org/devdocs/user/building.html#accelerated-blas-lapack-libraries
spec = self.spec
# https://numpy.org/devdocs/user/building.html#blas
if '~blas' in spec:
blas = ''
elif spec['blas'].name == 'intel-mkl' or \
spec['blas'].name == 'intel-parallel-studio':
blas = 'mkl'
elif spec['blas'].name == 'blis':
blas = 'blis'
elif spec['blas'].name == 'openblas':
blas = 'openblas'
elif spec['blas'].name == 'atlas':
blas = 'atlas'
elif spec['blas'].name == 'veclibfort':
blas = 'accelerate'
else:
f.write('[ALL]\n')
f.write('libraries=%s\n' % lapackblas_names)
write_library_dirs(f, lapackblas_dirs)
blas = 'blas'
spack_env.set('NPY_BLAS_ORDER', blas)
# https://numpy.org/devdocs/user/building.html#lapack
if '~lapack' in spec:
lapack = ''
elif spec['lapack'].name == 'intel-mkl' or \
spec['lapack'].name == 'intel-parallel-studio':
lapack = 'mkl'
elif spec['lapack'].name == 'openblas':
lapack = 'openblas'
elif spec['lapack'].name == 'libflame':
lapack = 'flame'
elif spec['lapack'].name == 'atlas':
lapack = 'atlas'
elif spec['lapack'].name == 'veclibfort':
lapack = 'accelerate'
else:
lapack = 'lapack'
spack_env.set('NPY_LAPACK_ORDER', lapack)
def build_args(self, spec, prefix):
args = []
# From NumPy 1.10.0 on it's possible to do a parallel build.
# https://numpy.org/devdocs/user/building.html#parallel-builds
if self.version >= Version('1.10.0'):
# But Parallel build in Python 3.5+ is broken. See:
# https://github.com/spack/spack/issues/7927
@ -201,20 +251,6 @@ def build_args(self, spec, prefix):
return args
def setup_environment(self, spack_env, run_env):
# If py-numpy is installed as an external package, python won't
# be available in the spec. See #9149 for details.
if 'python' in self.spec:
python_version = self.spec['python'].version.up_to(2)
include_path = join_path(
self.prefix.lib,
'python{0}'.format(python_version),
'site-packages',
'numpy/core/include')
run_env.prepend_path('CPATH', include_path)
def test(self):
# `setup.py test` is not supported. Use one of the following
# instead:

View file

@ -33,6 +33,12 @@ def libs(self):
'libvecLibFort', root=self.prefix, shared=shared, recursive=True
)
@property
def headers(self):
# veclibfort does not come with any headers. Return an empty list
# to avoid `spec['blas'].headers` from crashing.
return HeaderList([])
def install(self, spec, prefix):
if sys.platform != 'darwin':
raise InstallError('vecLibFort can be installed on macOS only')