1{
2 lib,
3 stdenv,
4 fetchurl,
5 writeText,
6 python,
7 buildPythonPackage,
8 fetchFromGitHub,
9 fetchpatch,
10
11 # build-system
12 cython,
13 gfortran,
14 meson-python,
15 nukeReferences,
16 pythran,
17 pkg-config,
18 setuptools,
19 xcbuild,
20
21 # buildInputs
22 # Upstream has support for using Darwin's Accelerate package. However this
23 # requires a Darwin user to work on a nice way to do that via an override.
24 # See:
25 # https://github.com/scipy/scipy/blob/v1.14.0/scipy/meson.build#L194-L211
26 blas,
27 lapack,
28 pybind11,
29 pooch,
30 xsimd,
31 boost188,
32 qhull,
33
34 # dependencies
35 numpy,
36
37 # tests
38 hypothesis,
39 pytestCheckHook,
40 pytest-xdist,
41
42 # Reverse dependency
43 sage,
44}:
45
46let
47 pname = "scipy";
48 # DON'T UPDATE THESE ATTRIBUTES MANUALLY - USE:
49 #
50 # nix-shell maintainers/scripts/update.nix --argstr package python3.pkgs.scipy
51 #
52 # The update script uses sed regexes to replace them with the updated hashes.
53 version = "1.16.1";
54 srcHash = "sha256-/LgYQUMGoQjSWMCWBgnekNGzEc0LVg2qiN2tV399rQU=";
55 datasetsHashes = {
56 ascent = "1qjp35ncrniq9rhzb14icwwykqg2208hcssznn3hz27w39615kh3";
57 ecg = "1bwbjp43b7znnwha5hv6wiz3g0bhwrpqpi75s12zidxrbwvd62pj";
58 face = "11i8x29h80y7hhyqhil1fg8mxag5f827g33lhnsf44qk116hp2wx";
59 };
60 datasets = lib.mapAttrs (
61 d: hash:
62 fetchurl {
63 url = "https://raw.githubusercontent.com/scipy/dataset-${d}/main/${d}.dat";
64 sha256 = hash;
65 }
66 ) datasetsHashes;
67 # Additional cross compilation related properties that scipy reads in scipy/meson.build
68 crossFileScipy = writeText "cross-file-scipy.conf" ''
69 [properties]
70 numpy-include-dir = '${numpy.coreIncludeDir}'
71 pythran-include-dir = '${pythran}/${python.sitePackages}/pythran'
72 host-python-path = '${python.interpreter}'
73 host-python-version = '${python.pythonVersion}'
74 '';
75in
76buildPythonPackage {
77 inherit pname version;
78 pyproject = true;
79
80 src = fetchFromGitHub {
81 owner = "scipy";
82 repo = "scipy";
83 tag = "v${version}";
84 hash = srcHash;
85 fetchSubmodules = true;
86 };
87
88 patches = [
89 # Helps with cross compilation, see https://github.com/scipy/scipy/pull/18167
90 (fetchpatch {
91 url = "https://github.com/scipy/scipy/commit/dd50ac9d98dbb70625333a23e3a90e493228e3be.patch";
92 hash = "sha256-Vf6/hhwu6X5s8KWhq8bUZKtSkdVu/GtEpGtj8Olxe7s=";
93 excludes = [ "doc/source/dev/contributor/meson_advanced.rst" ];
94 })
95 ];
96 # A NOTE regarding the Numpy version relaxing: Both Numpy versions 1.x &
97 # 2.x are supported. However upstream wants to always build with Numpy 2,
98 # and with it to still be able to run with a Numpy 1 or 2. We insist to
99 # perform this substitution even though python3.pkgs.numpy is of version 2
100 # nowadays, because our ecosystem unfortunately doesn't allow easily
101 # separating runtime and build-system dependencies. See also:
102 #
103 # https://discourse.nixos.org/t/several-comments-about-priorities-and-new-policies-in-the-python-ecosystem/51790
104 #
105 # Being able to build (& run) with Numpy 1 helps for python environments
106 # that override globally the `numpy` attribute to point to `numpy_1`.
107 postPatch = ''
108 substituteInPlace pyproject.toml \
109 --replace-fail "numpy>=2.0.0,<2.6" numpy
110 '';
111
112 build-system = [
113 cython
114 gfortran
115 meson-python
116 nukeReferences
117 pythran
118 pkg-config
119 setuptools
120 ]
121 ++ lib.optionals stdenv.hostPlatform.isDarwin [
122 # Minimal version required according to:
123 # https://github.com/scipy/scipy/blob/v1.16.0/scipy/meson.build#L238-L244
124 (xcbuild.override {
125 sdkVer = "13.3";
126 })
127 ];
128
129 buildInputs = [
130 blas
131 lapack
132 pybind11
133 pooch
134 xsimd
135 boost188
136 qhull
137 ];
138
139 dependencies = [ numpy ];
140
141 __darwinAllowLocalNetworking = true;
142
143 nativeCheckInputs = [
144 hypothesis
145 pytestCheckHook
146 pytest-xdist
147 ];
148
149 disabledTests =
150 lib.optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) [
151 # The following tests are broken on aarch64-darwin with newer compilers and library versions.
152 # See https://github.com/scipy/scipy/issues/18308
153 "test_a_b_neg_int_after_euler_hypergeometric_transformation"
154 "test_dst4_definition_ortho"
155 "test_load_mat4_le"
156 "hyp2f1_test_case47"
157 "hyp2f1_test_case3"
158 "test_uint64_max"
159 "test_large_m4" # https://github.com/scipy/scipy/issues/22466
160 ]
161 ++ lib.optionals (python.isPy311) [
162 # https://github.com/scipy/scipy/issues/22789 Observed only with Python 3.11
163 "test_funcs"
164 ];
165
166 doCheck = !(stdenv.hostPlatform.isx86_64 && stdenv.hostPlatform.isDarwin);
167
168 preConfigure = ''
169 # Helps parallelization a bit
170 export NPY_NUM_BUILD_JOBS=$NIX_BUILD_CORES
171 # We download manually the datasets and this variable tells the pooch
172 # library where these files are cached. See also:
173 # https://github.com/scipy/scipy/pull/18518#issuecomment-1562350648 And at:
174 # https://github.com/scipy/scipy/pull/17965#issuecomment-1560759962
175 export XDG_CACHE_HOME=$PWD; export HOME=$(mktemp -d); mkdir scipy-data
176 ''
177 + (lib.concatStringsSep "\n" (
178 lib.mapAttrsToList (
179 d: dpath:
180 # Actually copy the datasets
181 "cp ${dpath} scipy-data/${d}.dat"
182 ) datasets
183 ));
184
185 mesonFlags = [
186 "-Dblas=${blas.pname}"
187 "-Dlapack=${lapack.pname}"
188 # We always run what's necessary for cross compilation, which is passing to
189 # meson the proper cross compilation related arguments. See also:
190 # https://docs.scipy.org/doc/scipy/building/cross_compilation.html
191 "--cross-file=${crossFileScipy}"
192 "-Duse-system-libraries=all"
193 ];
194
195 # disable stackprotector on aarch64-darwin for now
196 #
197 # build error:
198 #
199 # /private/tmp/nix-build-python3.9-scipy-1.6.3.drv-0/ccDEsw5U.s:109:15: error: index must be an integer in range [-256, 255].
200 #
201 # ldr x0, [x0, ___stack_chk_guard];momd
202 #
203 hardeningDisable = lib.optionals (stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isDarwin) [
204 "stackprotector"
205 ];
206
207 # remove references to dev dependencies
208 postInstall = ''
209 nuke-refs $out/${python.sitePackages}/scipy/__config__.py
210 rm $out/${python.sitePackages}/scipy/__pycache__/__config__.*.opt-1.pyc
211 '';
212
213 preCheck = ''
214 export OMP_NUM_THREADS=$(( $NIX_BUILD_CORES / 4 ))
215 cd $out
216 '';
217
218 requiredSystemFeatures = [ "big-parallel" ]; # the tests need lots of CPU time
219
220 passthru = {
221 inherit blas;
222 updateScript = [
223 ./update.sh
224 # Pass it this file name as argument
225 (builtins.unsafeGetAttrPos "pname" python.pkgs.scipy).file
226 ]
227 # Pass it the names of the datasets to update their hashes
228 ++ (builtins.attrNames datasetsHashes);
229 tests = {
230 inherit sage;
231 };
232 };
233
234 SCIPY_USE_G77_ABI_WRAPPER = 1;
235
236 meta = {
237 changelog = "https://github.com/scipy/scipy/releases/tag/v${version}";
238 description = "SciPy (pronounced 'Sigh Pie') is open-source software for mathematics, science, and engineering";
239 downloadPage = "https://github.com/scipy/scipy";
240 homepage = "https://www.scipy.org/";
241 license = lib.licenses.bsd3;
242 maintainers = with lib.maintainers; [ doronbehar ];
243 };
244}