Wed Apr 7 11:57:31 2021 UTC ()
py-numpy: updated the BLAS patch for more likely upstream inclusion

This introduces a 'generic' variant for blas_opt_info() and
lapack_opt_info() that looks into BLAS_LIBS and LAPACK_LIBS. The
others stay alive, and you can choose via NPY_BLAS_ORDER and
NPY_LAPACK_ORDER.

Will post this upstream … hoping for the best.

Other projects seem just to abuse the [openblas] entry in
site.cfg, or whatever hacks to trick this into building with
a generic BLAS. One hurdle is that using openblas seems to
assume that CBLAS is present in there, which it is not in pkgsrc.

We could think about introducing some alternatives stuff that uses
stubs for all the related libs anyway, but that is not my application,
which builds things from source. For binary packages, it would be
interesting, though. See Debian and Genoot for prior art on that.


(thor)
diff -r1.76 -r1.77 pkgsrc/math/py-numpy/Makefile
diff -r1.58 -r1.59 pkgsrc/math/py-numpy/distinfo
diff -r1.5 -r1.6 pkgsrc/math/py-numpy/patches/patch-numpy_distutils_system__info.py

cvs diff -r1.76 -r1.77 pkgsrc/math/py-numpy/Makefile (expand / switch to unified diff)

--- pkgsrc/math/py-numpy/Makefile 2021/03/26 20:34:28 1.76
+++ pkgsrc/math/py-numpy/Makefile 2021/04/07 11:57:30 1.77
@@ -1,35 +1,38 @@ @@ -1,35 +1,38 @@
1# $NetBSD: Makefile,v 1.76 2021/03/26 20:34:28 thor Exp $ 1# $NetBSD: Makefile,v 1.77 2021/04/07 11:57:30 thor Exp $
2 2
3DISTNAME= numpy-1.19.5 3DISTNAME= numpy-1.19.5
4PKGREVISION= 2 4PKGREVISION= 3
5PKGNAME= ${PYPKGPREFIX}-${DISTNAME} 5PKGNAME= ${PYPKGPREFIX}-${DISTNAME}
6CATEGORIES= math python 6CATEGORIES= math python
7MASTER_SITES= ${MASTER_SITE_PYPI:=n/numpy/} 7MASTER_SITES= ${MASTER_SITE_PYPI:=n/numpy/}
8EXTRACT_SUFX= .zip 8EXTRACT_SUFX= .zip
9 9
10MAINTAINER= pkgsrc-users@NetBSD.org 10MAINTAINER= pkgsrc-users@NetBSD.org
11HOMEPAGE= http://www.numpy.org/ 11HOMEPAGE= http://www.numpy.org/
12COMMENT= Array processing for numbers, strings, records, and objects 12COMMENT= Array processing for numbers, strings, records, and objects
13LICENSE= modified-bsd 13LICENSE= modified-bsd
14 14
15TEST_DEPENDS+= ${PYPKGPREFIX}-hypothesis-[0-9]*:../../devel/py-hypothesis 15TEST_DEPENDS+= ${PYPKGPREFIX}-hypothesis-[0-9]*:../../devel/py-hypothesis
16TEST_DEPENDS+= ${PYPKGPREFIX}-nose-[0-9]*:../../devel/py-nose 16TEST_DEPENDS+= ${PYPKGPREFIX}-nose-[0-9]*:../../devel/py-nose
17TEST_DEPENDS+= ${PYPKGPREFIX}-test-[0-9]*:../../devel/py-test 17TEST_DEPENDS+= ${PYPKGPREFIX}-test-[0-9]*:../../devel/py-test
18 18
19# error: 'for' loop initial declarations are only allowed in C99 mode 19# error: 'for' loop initial declarations are only allowed in C99 mode
20USE_LANGUAGES= c99 fortran 20USE_LANGUAGES= c99 fortran
21MAKE_ENV+= ATLAS=None 21# Use our BLAS. The patch adds 'generic' as first entry anyway, but we
 22# enforce it to fail early and for the case that upstream accepts the
 23# patch, but with changed default order.
22MAKE_ENV+= BLAS_LIBS=${BLAS_LIBS:Q} LAPACK_LIBS=${LAPACK_LIBS:Q} 24MAKE_ENV+= BLAS_LIBS=${BLAS_LIBS:Q} LAPACK_LIBS=${LAPACK_LIBS:Q}
 25MAKE_ENV+= NPY_BLAS_ORDER=generic NPY_LAPACK_ORDER=generic
23 26
24REPLACE_PYTHON+= *.py */*.py */*/*.py */*/*/*.py */*/*/*/*.py 27REPLACE_PYTHON+= *.py */*.py */*/*.py */*/*/*.py */*/*/*/*.py
25 28
26PYTHON_VERSIONS_INCOMPATIBLE= 27 # since 1.17 29PYTHON_VERSIONS_INCOMPATIBLE= 27 # since 1.17
27 30
28# XXX Avoid picking up other compilers when installed 31# XXX Avoid picking up other compilers when installed
29.include "../../mk/compiler.mk" 32.include "../../mk/compiler.mk"
30 33
31.if defined(PKGSRC_FORTRAN) && ${PKGSRC_FORTRAN} == "g95" 34.if defined(PKGSRC_FORTRAN) && ${PKGSRC_FORTRAN} == "g95"
32PYSETUPBUILDARGS+= --fcompiler=g95 35PYSETUPBUILDARGS+= --fcompiler=g95
33.elif defined(PKGSRC_FORTRAN) && ${PKGSRC_FORTRAN} == "gfortran" 36.elif defined(PKGSRC_FORTRAN) && ${PKGSRC_FORTRAN} == "gfortran"
34PYSETUPBUILDARGS+= --fcompiler=gnu95 37PYSETUPBUILDARGS+= --fcompiler=gnu95
35.elif !empty(PKGSRC_COMPILER:Mgcc) 38.elif !empty(PKGSRC_COMPILER:Mgcc)

cvs diff -r1.58 -r1.59 pkgsrc/math/py-numpy/distinfo (expand / switch to unified diff)

--- pkgsrc/math/py-numpy/distinfo 2021/03/26 20:34:28 1.58
+++ pkgsrc/math/py-numpy/distinfo 2021/04/07 11:57:30 1.59
@@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
1$NetBSD: distinfo,v 1.58 2021/03/26 20:34:28 thor Exp $ 1$NetBSD: distinfo,v 1.59 2021/04/07 11:57:30 thor Exp $
2 2
3SHA1 (numpy-1.19.5.zip) = 61f0b3dad58ce97b14da9dccbee0722d36f26937 3SHA1 (numpy-1.19.5.zip) = 61f0b3dad58ce97b14da9dccbee0722d36f26937
4RMD160 (numpy-1.19.5.zip) = 3317c98790e8c2d1d9c36279b3451f09b6776935 4RMD160 (numpy-1.19.5.zip) = 3317c98790e8c2d1d9c36279b3451f09b6776935
5SHA512 (numpy-1.19.5.zip) = dfe2809b5f486624b4802ea5610822bf7ba80c46dcf8505f69b0267137b01719131f74aa366949954c66796d48ba1b4f74cf0ecc5692a9ebd49e673fb0881ff4 5SHA512 (numpy-1.19.5.zip) = dfe2809b5f486624b4802ea5610822bf7ba80c46dcf8505f69b0267137b01719131f74aa366949954c66796d48ba1b4f74cf0ecc5692a9ebd49e673fb0881ff4
6Size (numpy-1.19.5.zip) = 7318340 bytes 6Size (numpy-1.19.5.zip) = 7318340 bytes
7SHA1 (patch-numpy_distutils_fcompiler_____init____.py) = 49d070da5b48bd9818b37ac3254341fa68503c53 7SHA1 (patch-numpy_distutils_fcompiler_____init____.py) = 49d070da5b48bd9818b37ac3254341fa68503c53
8SHA1 (patch-numpy_distutils_fcompiler_g95.py) = be73b64a3e551df998b6a904d6db762bf28a98ed 8SHA1 (patch-numpy_distutils_fcompiler_g95.py) = be73b64a3e551df998b6a904d6db762bf28a98ed
9SHA1 (patch-numpy_distutils_fcompiler_gnu.py) = 1d62e1c5e35de0f2cf975de38f62df7f10c71d74 9SHA1 (patch-numpy_distutils_fcompiler_gnu.py) = 1d62e1c5e35de0f2cf975de38f62df7f10c71d74
10SHA1 (patch-numpy_distutils_system__info.py) = e01c0ca1a7151f77ac9cfbccd44da44a0d354931 10SHA1 (patch-numpy_distutils_system__info.py) = 8322a9f27f61626812509e26c80cb9f9b49ced7e
11SHA1 (patch-numpy_linalg_lapack__litemodule.c) = e97ec871c2f33c3121b3c8471a9e5a74c3c798c8 11SHA1 (patch-numpy_linalg_lapack__litemodule.c) = e97ec871c2f33c3121b3c8471a9e5a74c3c798c8

cvs diff -r1.5 -r1.6 pkgsrc/math/py-numpy/patches/Attic/patch-numpy_distutils_system__info.py (expand / switch to unified diff)

--- pkgsrc/math/py-numpy/patches/Attic/patch-numpy_distutils_system__info.py 2021/03/26 20:34:28 1.5
+++ pkgsrc/math/py-numpy/patches/Attic/patch-numpy_distutils_system__info.py 2021/04/07 11:57:30 1.6
@@ -1,102 +1,78 @@ @@ -1,102 +1,78 @@
1$NetBSD: patch-numpy_distutils_system__info.py,v 1.5 2021/03/26 20:34:28 thor Exp $ 1$NetBSD: patch-numpy_distutils_system__info.py,v 1.6 2021/04/07 11:57:30 thor Exp $
2 2
3Disable openblas detection. In pkgsrc, use mk/blas.buildlink.mk. 3Introduce new option 'generic' for BLAS and LAPACK
 4TODO: The same for 64 bit offset versions, but we'd need repspective BLAS builds
 5first in pkgsrc to test.
4 6
5--- numpy/distutils/system_info.py.orig 2020-06-02 05:24:58.000000000 +0000 7--- numpy/distutils/system_info.py.orig 2021-01-04 14:16:38.000000000 +0000
6+++ numpy/distutils/system_info.py 8+++ numpy/distutils/system_info.py
7@@ -1730,34 +1722,18 @@ class lapack_opt_info(system_info): 9@@ -114,6 +114,13 @@ Currently, the following classes are ava
 10 x11_info:x11
 11 xft_info:xft
 12
 13+Note that blas_opt_info and lapack_opt_info honor the NPY_BLAS_ORDER and NPY_LAPACK_ORDER
 14+environment variables to select a specific implementation. One possible implementation
 15+is 'generic', which relies on the environment providing BLAS_LIBS and LAPACK_LIBS to
 16+link to the customary plain f77 interface, supporting any standard-conforming BLAS
 17+and LAPACK implementation (which might be different between build-time and run-time,
 18+even).
 19+
 20 Example:
 21 ----------
 22 [DEFAULT]
 23@@ -1651,7 +1658,7 @@ def get_atlas_version(**config):
 24 class lapack_opt_info(system_info):
 25 notfounderror = LapackNotFoundError
 26 # List of all known BLAS libraries, in the default order
 27- lapack_order = ['mkl', 'openblas', 'flame', 'atlas', 'accelerate', 'lapack']
 28+ lapack_order = ['generic', 'mkl', 'openblas', 'flame', 'atlas', 'accelerate', 'lapack']
 29 order_env_var_name = 'NPY_LAPACK_ORDER'
 30
 31 def _calc_info_mkl(self):
 32@@ -1744,6 +1751,18 @@ class lapack_opt_info(system_info):
 33 return True
 34 return False
 35
 36+ def _calc_info_generic(self):
 37+ if 'LAPACK_LIBS' in os.environ:
 38+ info = {}
 39+ info['language'] = 'f77'
 40+ info['libraries'] = []
 41+ info['include_dirs'] = []
 42+ info['define_macros'] = []
 43+ info['extra_link_args'] = os.environ['LAPACK_LIBS'].split()
 44+ self.set_info(**info)
 45+ return True
 46+ return False
 47+
 48 def _calc_info(self, name):
8 return getattr(self, '_calc_info_{}'.format(name))() 49 return getattr(self, '_calc_info_{}'.format(name))()
9  50
10 def calc_info(self): 51@@ -1823,7 +1842,7 @@ class lapack64__opt_info(lapack_ilp64_op
11- user_order = os.environ.get(self.order_env_var_name, None) 52 class blas_opt_info(system_info):
12- if user_order is None: 53 notfounderror = BlasNotFoundError
13- lapack_order = self.lapack_order 54 # List of all known BLAS libraries, in the default order
14- else: 55- blas_order = ['mkl', 'blis', 'openblas', 'atlas', 'accelerate', 'blas']
15- # the user has requested the order of the 56+ blas_order = ['generic', 'mkl', 'blis', 'openblas', 'atlas', 'accelerate', 'blas']
16- # check they are all in the available list, a COMMA SEPARATED list 57 order_env_var_name = 'NPY_BLAS_ORDER'
17- user_order = user_order.lower().split(',') 58
18- non_existing = [] 59 def _calc_info_mkl(self):
19- lapack_order = [] 60@@ -1889,6 +1908,18 @@ class blas_opt_info(system_info):
20- for order in user_order: 61 self.set_info(**info)
21- if order in self.lapack_order: 62 return True
22- lapack_order.append(order) 63
23- elif len(order) > 0: 64+ def _calc_info_generic(self):
24- non_existing.append(order) 65+ if 'BLAS_LIBS' in os.environ:
25- if len(non_existing) > 0: 66+ info = {}
26- raise ValueError("lapack_opt_info user defined " 67+ info['language'] = 'f77'
27- "LAPACK order has unacceptable " 68+ info['libraries'] = []
28- "values: {}".format(non_existing)) 69+ info['include_dirs'] = []
29- 70+ info['define_macros'] = []
30- for lapack in lapack_order: 71+ info['extra_link_args'] = os.environ['BLAS_LIBS'].split()
31- if self._calc_info(lapack): 72+ self.set_info(**info)
32- return 73+ return True
33- 74+ return False
34- if 'lapack' not in lapack_order: 75+
35- # Since the user may request *not* to use any library, we still need 76 def _calc_info(self, name):
36- # to raise warnings to signal missing packages! 
37- warnings.warn(LapackNotFoundError.__doc__ or '', stacklevel=2) 
38- warnings.warn(LapackSrcNotFoundError.__doc__ or '', stacklevel=2) 
39+ # Fixing usage of LAPACK specified in LAPACK_LIBS. 
40+ # Existence of LAPACK_LIBS is mandatory. Things shall break early 
41+ # if it is not set. 
42+ info = {} 
43+ info['language'] = 'f77' 
44+ info['libraries'] = [] 
45+ info['include_dirs'] = [] 
46+ info['define_macros'] = [] 
47+ info['extra_link_args'] = os.environ['LAPACK_LIBS'].split() 
48+  
49+ self.set_info(**info) 
50+ return 
51  
52  
53 class _ilp64_opt_info_mixin: 
54@@ -1875,32 +1848,22 @@ class blas_opt_info(system_info): 
55 return getattr(self, '_calc_info_{}'.format(name))() 77 return getattr(self, '_calc_info_{}'.format(name))()
56  78
57 def calc_info(self): 
58- user_order = os.environ.get(self.order_env_var_name, None) 
59- if user_order is None: 
60- blas_order = self.blas_order 
61- else: 
62- # the user has requested the order of the 
63- # check they are all in the available list 
64- user_order = user_order.lower().split(',') 
65- non_existing = [] 
66- blas_order = [] 
67- for order in user_order: 
68- if order in self.blas_order: 
69- blas_order.append(order) 
70- elif len(order) > 0: 
71- non_existing.append(order) 
72- if len(non_existing) > 0: 
73- raise ValueError("blas_opt_info user defined BLAS order has unacceptable values: {}".format(non_existing)) 
74- 
75- for blas in blas_order: 
76- if self._calc_info(blas): 
77- return 
78- 
79- if 'blas' not in blas_order: 
80- # Since the user may request *not* to use any library, we still need 
81- # to raise warnings to signal missing packages! 
82- warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=2) 
83- warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=2) 
84+ # Fixing usage of libcblas and the BLAS specified in BLAS_LIBS. 
85+ # Existence of BLAS_LIBS is mandatory. Things shall break early 
86+ # if it is not set. 
87+ info = {} 
88+ # We assume a generic BLAS, which is a Fortran lib. 
89+ info['language'] = 'f77' 
90+ # Try to work without cblas, just link BLAS_LIBS. 
91+ #info['libraries'] = ['cblas'] 
92+ #info['define_macros'] = [('HAVE_CBLAS', None)] 
93+ info['libraries'] = [] 
94+ info['include_dirs'] = [] 
95+ info['define_macros'] = [] 
96+ info['extra_link_args'] = os.environ['BLAS_LIBS'].split() 
97+  
98+ self.set_info(**info) 
99+ return 
100  
101  
102 class blas_ilp64_opt_info(blas_opt_info, _ilp64_opt_info_mixin):