312 lines
16 KiB
Python
312 lines
16 KiB
Python
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
|
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
#
|
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
from spack import *
|
|
import platform
|
|
import subprocess
|
|
|
|
|
|
class PyNumpy(PythonPackage):
|
|
"""NumPy is the fundamental package for scientific computing with Python.
|
|
It contains among other things: a powerful N-dimensional array object,
|
|
sophisticated (broadcasting) functions, tools for integrating C/C++ and
|
|
Fortran code, and useful linear algebra, Fourier transform, and random
|
|
number capabilities"""
|
|
|
|
homepage = "https://numpy.org/"
|
|
url = "https://pypi.io/packages/source/n/numpy/numpy-1.18.4.zip"
|
|
git = "https://github.com/numpy/numpy.git"
|
|
|
|
maintainers = ['adamjstewart']
|
|
install_time_test_callbacks = ['install_test', 'import_module_test']
|
|
|
|
import_modules = [
|
|
'numpy', 'numpy.compat', 'numpy.core', 'numpy.distutils', 'numpy.doc',
|
|
'numpy.f2py', 'numpy.fft', 'numpy.lib', 'numpy.linalg', 'numpy.ma',
|
|
'numpy.matrixlib', 'numpy.polynomial', 'numpy.random', 'numpy.testing',
|
|
'numpy.distutils.command', 'numpy.distutils.fcompiler'
|
|
]
|
|
|
|
version('master', branch='master')
|
|
version('1.18.4', sha256='bbcc85aaf4cd84ba057decaead058f43191cc0e30d6bc5d44fe336dc3d3f4509')
|
|
version('1.18.3', sha256='e46e2384209c91996d5ec16744234d1c906ab79a701ce1a26155c9ec890b8dc8')
|
|
version('1.18.2', sha256='e7894793e6e8540dbeac77c87b489e331947813511108ae097f1715c018b8f3d')
|
|
version('1.18.1', sha256='b6ff59cee96b454516e47e7721098e6ceebef435e3e21ac2d6c3b8b02628eb77')
|
|
version('1.18.0', sha256='a9d72d9abaf65628f0f31bbb573b7d9304e43b1e6bbae43149c17737a42764c4')
|
|
version('1.17.5', sha256='16507ba6617f62ae3c6ab1725ae6f550331025d4d9a369b83f6d5a470446c342')
|
|
version('1.17.4', sha256='f58913e9227400f1395c7b800503ebfdb0772f1c33ff8cb4d6451c06cabdf316')
|
|
version('1.17.3', sha256='a0678793096205a4d784bd99f32803ba8100f639cf3b932dc63b21621390ea7e')
|
|
version('1.17.2', sha256='73615d3edc84dd7c4aeb212fa3748fb83217e00d201875a47327f55363cef2df')
|
|
version('1.17.1', sha256='f11331530f0eff69a758d62c2461cd98cdc2eae0147279d8fc86e0464eb7e8ca')
|
|
version('1.17.0', sha256='951fefe2fb73f84c620bec4e001e80a80ddaa1b84dce244ded7f1e0cbe0ed34a')
|
|
version('1.16.6', sha256='e5cf3fdf13401885e8eea8170624ec96225e2174eb0c611c6f26dd33b489e3ff')
|
|
version('1.16.5', sha256='8bb452d94e964b312205b0de1238dd7209da452343653ab214b5d681780e7a0c')
|
|
version('1.16.4', sha256='7242be12a58fec245ee9734e625964b97cf7e3f2f7d016603f9e56660ce479c7')
|
|
version('1.16.3', sha256='78a6f89da87eeb48014ec652a65c4ffde370c036d780a995edaeb121d3625621')
|
|
version('1.16.2', sha256='6c692e3879dde0b67a9dc78f9bfb6f61c666b4562fd8619632d7043fb5b691b0')
|
|
version('1.16.1', sha256='31d3fe5b673e99d33d70cfee2ea8fe8dccd60f265c3ed990873a88647e3dd288')
|
|
version('1.16.0', sha256='cb189bd98b2e7ac02df389b6212846ab20661f4bafe16b5a70a6f1728c1cc7cb')
|
|
version('1.15.4', sha256='3d734559db35aa3697dadcea492a423118c5c55d176da2f3be9c98d4803fc2a7')
|
|
version('1.15.3', sha256='1c0c80e74759fa4942298044274f2c11b08c86230b25b8b819e55e644f5ff2b6')
|
|
version('1.15.2', sha256='27a0d018f608a3fe34ac5e2b876f4c23c47e38295c47dd0775cc294cd2614bc1')
|
|
version('1.15.2', sha256='27a0d018f608a3fe34ac5e2b876f4c23c47e38295c47dd0775cc294cd2614bc1')
|
|
version('1.15.1', sha256='7b9e37f194f8bcdca8e9e6af92e2cbad79e360542effc2dd6b98d63955d8d8a3')
|
|
version('1.15.0', sha256='f28e73cf18d37a413f7d5de35d024e6b98f14566a10d82100f9dc491a7d449f9')
|
|
version('1.14.6', sha256='1250edf6f6c43e1d7823f0967416bc18258bb271dc536298eb0ea00a9e45b80a')
|
|
version('1.14.5', sha256='a4a433b3a264dbc9aa9c7c241e87c0358a503ea6394f8737df1683c7c9a102ac')
|
|
version('1.14.4', sha256='2185a0f31ecaa0792264fa968c8e0ba6d96acf144b26e2e1d1cd5b77fc11a691')
|
|
version('1.14.3', sha256='9016692c7d390f9d378fc88b7a799dc9caa7eb938163dda5276d3f3d6f75debf')
|
|
version('1.14.2', sha256='facc6f925c3099ac01a1f03758100772560a0b020fb9d70f210404be08006bcb')
|
|
version('1.14.1', sha256='fa0944650d5d3fb95869eaacd8eedbd2d83610c85e271bd9d3495ffa9bc4dc9c')
|
|
version('1.14.0', sha256='3de643935b212307b420248018323a44ec51987a336d1d747c1322afc3c099fb')
|
|
version('1.13.3', sha256='36ee86d5adbabc4fa2643a073f93d5504bdfed37a149a3a49f4dde259f35a750')
|
|
version('1.13.1', sha256='c9b0283776085cb2804efff73e9955ca279ba4edafd58d3ead70b61d209c4fbb')
|
|
version('1.13.0', sha256='dcff367b725586830ff0e20b805c7654c876c2d4585c0834a6049502b9d6cf7e')
|
|
version('1.12.1', sha256='a65266a4ad6ec8936a1bc85ce51f8600634a31a258b722c9274a80ff189d9542')
|
|
version('1.12.0', sha256='ff320ecfe41c6581c8981dce892fe6d7e69806459a899e294e4bf8229737b154')
|
|
version('1.11.3', sha256='2e0fc5248246a64628656fe14fcab0a959741a2820e003bd15538226501b82f7')
|
|
version('1.11.2', sha256='c1ed4d1d2a795409c7df1eb4bfee65c0e3326cfc7c57875fa39e5c7414116d9a')
|
|
version('1.11.1', sha256='4e9c289b9d764d10353a224a5286dda3e0425b13b112719bdc3e9864ae648d79')
|
|
version('1.11.0', sha256='9109f260850627e4b83a3c4bcef4f2f99357eb4a5eaae75dec51c32f3c197aa3')
|
|
version('1.10.4', sha256='8ce443dc79656a9fc97a7837f1444d324aef2c9b53f31f83441f57ad1f1f3659')
|
|
version('1.9.3', sha256='baa074bb1c7f9c822122fb81459b7caa5fc49267ca94cca69465c8dcfd63ac79')
|
|
version('1.9.2', sha256='e37805754f4ebb575c434d134f6bebb8b857d9843c393f6943c7be71ef57311c')
|
|
version('1.9.1', sha256='2a545c0d096d86035b12160fcba5e4c0a08dcabbf902b4f867eb64deb31a2b7a')
|
|
|
|
variant('blas', default=True, description='Build with BLAS support')
|
|
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')
|
|
# Check pyproject.toml for updates to the required cython version
|
|
depends_on('py-cython@0.29.13:', when='@1.18.0:', type='build')
|
|
depends_on('py-cython@0.29.14:', when='@1.18.1:', type='build')
|
|
depends_on('blas', when='+blas')
|
|
depends_on('lapack', when='+lapack')
|
|
|
|
depends_on('py-nose@1.0.0:', when='@:1.14', type='test')
|
|
depends_on('py-pytest', when='@1.15:', type='test')
|
|
|
|
# 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')
|
|
|
|
# GCC 4.8 is the minimum version that works
|
|
conflicts('%gcc@:4.7', msg='GCC 4.8+ required')
|
|
|
|
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)
|
|
# Check gcc version in use by intel compiler
|
|
# This will essentially check the system gcc compiler unless a gcc
|
|
# module is already loaded.
|
|
if self.spec.satisfies('%intel') and name == 'cflags':
|
|
p1 = subprocess.Popen(
|
|
[self.compiler.cc, '-v'],
|
|
stderr=subprocess.PIPE
|
|
)
|
|
p2 = subprocess.Popen(
|
|
['grep', 'compatibility'],
|
|
stdin=p1.stderr,
|
|
stdout=subprocess.PIPE
|
|
)
|
|
p1.stderr.close()
|
|
out, err = p2.communicate()
|
|
gcc_version = Version(out.split()[5].decode('utf-8'))
|
|
if gcc_version < Version('4.8'):
|
|
raise InstallError('The GCC version that the Intel compiler '
|
|
'uses must be >= 4.8. The GCC in use is '
|
|
'{0}'.format(gcc_version))
|
|
if gcc_version <= Version('5.1'):
|
|
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 = {0}\n'.format(dirs))
|
|
if not ((platform.system() == 'Darwin') and
|
|
(Version(platform.mac_ver()[0]).up_to(2) == Version(
|
|
'10.12'))):
|
|
f.write('rpath = {0}\n'.format(dirs))
|
|
|
|
blas_libs = LibraryList([])
|
|
blas_headers = HeaderList([])
|
|
if '+blas' in spec:
|
|
blas_libs = spec['blas'].libs
|
|
blas_headers = spec['blas'].headers
|
|
|
|
lapack_libs = LibraryList([])
|
|
lapack_headers = HeaderList([])
|
|
if '+lapack' in spec:
|
|
lapack_libs = spec['lapack'].libs
|
|
lapack_headers = spec['lapack'].headers
|
|
|
|
lapackblas_libs = lapack_libs + blas_libs
|
|
lapackblas_headers = lapack_headers + blas_headers
|
|
|
|
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:
|
|
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))
|
|
|
|
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))
|
|
|
|
if '^openblas' in spec:
|
|
f.write('[openblas]\n')
|
|
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 '^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('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('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('libraries = {0}\n'.format(lapack_lib_names))
|
|
write_library_dirs(f, lapack_lib_dirs)
|
|
f.write('include_dirs = {0}\n'.format(lapack_header_dirs))
|
|
|
|
def setup_build_environment(self, 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' not 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:
|
|
blas = 'blas'
|
|
|
|
env.set('NPY_BLAS_ORDER', blas)
|
|
|
|
# https://numpy.org/devdocs/user/building.html#lapack
|
|
if 'lapack' not 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'
|
|
|
|
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
|
|
# https://github.com/scipy/scipy/issues/7112
|
|
if spec['python'].version < Version('3.5'):
|
|
args = ['-j', str(make_jobs)]
|
|
|
|
return args
|
|
|
|
def test(self):
|
|
# `setup.py test` is not supported. Use one of the following
|
|
# instead:
|
|
#
|
|
# - `python runtests.py` (to build and test)
|
|
# - `python runtests.py --no-build` (to test installed numpy)
|
|
# - `>>> numpy.test()` (run tests for installed numpy
|
|
# from within an interpreter)
|
|
pass
|
|
|
|
def install_test(self):
|
|
# Change directories due to the following error:
|
|
#
|
|
# ImportError: Error importing numpy: you should not try to import
|
|
# numpy from its source directory; please exit the numpy
|
|
# source tree, and relaunch your python interpreter from there.
|
|
with working_dir('spack-test', create=True):
|
|
python('-c', 'import numpy; numpy.test("full", verbose=2)')
|