nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 stdenv,
4 fetchFromGitHub,
5 fetchpatch,
6 perl,
7 which,
8 # Most packages depending on openblas expect integer width to match
9 # pointer width, but some expect to use 32-bit integers always
10 # (for compatibility with reference BLAS).
11 blas64 ? null,
12 # Multi-threaded applications must not call a threaded OpenBLAS
13 # (the only exception is when an application uses OpenMP as its
14 # *only* form of multi-threading). See
15 # https://github.com/OpenMathLib/OpenBLAS/wiki/Faq/4bded95e8dc8aadc70ce65267d1093ca7bdefc4c#multi-threaded
16 # https://github.com/OpenMathLib/OpenBLAS/issues/2543
17 # This flag builds a single-threaded OpenBLAS using the flags
18 # stated in thre.
19 singleThreaded ? false,
20 buildPackages,
21 # Select a specific optimization target (other than the default)
22 # See https://github.com/OpenMathLib/OpenBLAS/blob/develop/TargetList.txt
23 target ? null,
24 # Select whether DYNAMIC_ARCH is enabled or not.
25 dynamicArch ? null,
26 # enable AVX512 optimized kernels.
27 # These kernels have been a source of trouble in the past.
28 # Use with caution.
29 enableAVX512 ? false,
30 enableStatic ? stdenv.hostPlatform.isStatic,
31 enableShared ? !stdenv.hostPlatform.isStatic,
32
33 # for passthru.tests
34 ceres-solver,
35 giac,
36 octave,
37 opencv,
38 python3,
39 openmp ? null,
40}:
41
42let
43 blas64_ = blas64;
44in
45
46let
47 setTarget = x: if target == null then x else target;
48 setDynamicArch = x: if dynamicArch == null then x else dynamicArch;
49
50 # To add support for a new platform, add an element to this set.
51 configs = {
52 armv6l-linux = {
53 BINARY = 32;
54 TARGET = setTarget "ARMV6";
55 DYNAMIC_ARCH = setDynamicArch false;
56 USE_OPENMP = true;
57 };
58
59 armv7l-linux = {
60 BINARY = 32;
61 TARGET = setTarget "ARMV7";
62 DYNAMIC_ARCH = setDynamicArch false;
63 USE_OPENMP = true;
64 };
65
66 aarch64-darwin = {
67 BINARY = 64;
68 TARGET = setTarget "VORTEX";
69 DYNAMIC_ARCH = setDynamicArch true;
70 USE_OPENMP = false;
71 MACOSX_DEPLOYMENT_TARGET = "11.0";
72 };
73
74 aarch64-linux = {
75 BINARY = 64;
76 TARGET = setTarget "ARMV8";
77 DYNAMIC_ARCH = setDynamicArch true;
78 USE_OPENMP = true;
79 };
80
81 i686-linux = {
82 BINARY = 32;
83 TARGET = setTarget "P2";
84 DYNAMIC_ARCH = setDynamicArch true;
85 USE_OPENMP = true;
86 };
87
88 x86_64-darwin = {
89 BINARY = 64;
90 TARGET = setTarget "ATHLON";
91 DYNAMIC_ARCH = setDynamicArch true;
92 NO_AVX512 = !enableAVX512;
93 USE_OPENMP = false;
94 MACOSX_DEPLOYMENT_TARGET = "10.7";
95 };
96
97 x86_64-linux = {
98 BINARY = 64;
99 TARGET = setTarget "ATHLON";
100 DYNAMIC_ARCH = setDynamicArch true;
101 NO_AVX512 = !enableAVX512;
102 USE_OPENMP = !stdenv.hostPlatform.isMusl;
103 };
104
105 x86_64-windows = {
106 BINARY = 64;
107 TARGET = setTarget "ATHLON";
108 DYNAMIC_ARCH = setDynamicArch true;
109 NO_AVX512 = !enableAVX512;
110 USE_OPENMP = false;
111 };
112
113 powerpc64-linux = {
114 BINARY = 64;
115 TARGET = setTarget "POWER4";
116 DYNAMIC_ARCH = setDynamicArch false;
117 USE_OPENMP = !stdenv.hostPlatform.isMusl;
118 };
119
120 powerpc64le-linux = {
121 BINARY = 64;
122 TARGET = setTarget "POWER5";
123 DYNAMIC_ARCH = setDynamicArch true;
124 USE_OPENMP = !stdenv.hostPlatform.isMusl;
125 };
126
127 riscv64-linux = {
128 BINARY = 64;
129 TARGET = setTarget "RISCV64_GENERIC";
130 DYNAMIC_ARCH = setDynamicArch false;
131 USE_OPENMP = true;
132 };
133
134 loongarch64-linux = {
135 TARGET = setTarget "LA64_GENERIC";
136 DYNAMIC_ARCH = setDynamicArch false;
137 USE_OPENMP = true;
138 };
139
140 s390x-linux = {
141 BINARY = 64;
142 TARGET = setTarget "ZARCH_GENERIC";
143 DYNAMIC_ARCH = setDynamicArch true;
144 USE_OPENMP = true;
145 };
146
147 x86_64-freebsd = {
148 BINARY = 64;
149 TARGET = setTarget "ATHLON";
150 DYNAMIC_ARCH = setDynamicArch true;
151 NO_AVX512 = !enableAVX512;
152 USE_OPENMP = true;
153 };
154 };
155in
156
157let
158 config =
159 configs.${stdenv.hostPlatform.system}
160 or (throw "unsupported system: ${stdenv.hostPlatform.system}");
161in
162
163let
164 blas64 = if blas64_ != null then blas64_ else lib.hasPrefix "x86_64" stdenv.hostPlatform.system;
165 # Convert flag values to format OpenBLAS's build expects.
166 # `toString` is almost what we need other than bools,
167 # which we need to map {true -> 1, false -> 0}
168 # (`toString` produces empty string `""` for false instead of `0`)
169 mkMakeFlagValue =
170 val:
171 if !builtins.isBool val then
172 toString val
173 else if val then
174 "1"
175 else
176 "0";
177 mkMakeFlagsFromConfig = lib.mapAttrsToList (var: val: "${var}=${mkMakeFlagValue val}");
178
179 shlibExt = stdenv.hostPlatform.extensions.sharedLibrary;
180
181in
182stdenv.mkDerivation rec {
183 pname = "openblas";
184 version = "0.3.30";
185
186 outputs = [
187 "out"
188 "dev"
189 ];
190
191 src = fetchFromGitHub {
192 owner = "OpenMathLib";
193 repo = "OpenBLAS";
194 rev = "v${version}";
195 hash = "sha256-foP2OXUL6ttgYvCxLsxUiVdkPoTvGiHomdNudbSUmSE=";
196 };
197
198 patches = [
199 # Remove this once https://github.com/OpenMathLib/OpenBLAS/issues/5414 is
200 # resolved.
201 ./disable-sme-sgemm-kernel.patch
202
203 # https://github.com/OpenMathLib/OpenBLAS/issues/5460
204 (fetchpatch {
205 name = "0001-openblas-Use-generic-kernels-for-SCAL-on-POWER4-5.patch";
206 url = "https://github.com/OpenMathLib/OpenBLAS/commit/14c9dcaac70d9382de00ba4418643d9587f4950e.patch";
207 hash = "sha256-mIOqRc7tE1rV/krrAu630JwApZHdeHCdVmO5j6eDC8U=";
208 })
209 ];
210
211 postPatch = ''
212 # cc1: error: invalid feature modifier 'sve2' in '-march=armv8.5-a+sve+sve2+bf16'
213 substituteInPlace Makefile.arm64 --replace "+sve2+bf16" ""
214 '';
215
216 inherit blas64;
217
218 # Some hardening features are disabled due to sporadic failures in
219 # OpenBLAS-based programs. The problem may not be with OpenBLAS itself, but
220 # with how these flags interact with hardening measures used downstream.
221 # In either case, OpenBLAS must only be used by trusted code--it is
222 # inherently unsuitable for security-conscious applications--so there should
223 # be no objection to disabling these hardening measures.
224 hardeningDisable = [
225 # don't modify or move the stack
226 "stackprotector"
227 "pic"
228 # don't alter index arithmetic
229 "strictoverflow"
230 # don't interfere with dynamic target detection
231 "relro"
232 "bindnow"
233 ]
234 ++ lib.optionals stdenv.hostPlatform.isAarch64 [
235 # "__builtin_clear_padding not supported for variable length aggregates"
236 # in aarch64-specific code
237 "trivialautovarinit"
238 ];
239
240 nativeBuildInputs = [
241 perl
242 which
243 ];
244
245 buildInputs = lib.optional (stdenv.cc.isClang && config.USE_OPENMP) openmp;
246
247 depsBuildBuild = [
248 buildPackages.gfortran
249 buildPackages.stdenv.cc
250 ];
251
252 enableParallelBuilding = true;
253
254 makeFlags = mkMakeFlagsFromConfig (
255 config
256 // {
257 FC = "${stdenv.cc.targetPrefix}gfortran";
258 CC = "${stdenv.cc.targetPrefix}${if stdenv.cc.isClang then "clang" else "cc"}";
259 PREFIX = placeholder "out";
260 OPENBLAS_INCLUDE_DIR = "${placeholder "dev"}/include";
261 NUM_THREADS = 64;
262 INTERFACE64 = blas64;
263 NO_STATIC = !enableStatic;
264 NO_SHARED = !enableShared;
265 CROSS = stdenv.hostPlatform != stdenv.buildPlatform;
266 HOSTCC = "cc";
267 # Makefile.system only checks defined status
268 # This seems to be a bug in the openblas Makefile:
269 # on x86_64 it expects NO_BINARY_MODE=
270 # but on aarch64 it expects NO_BINARY_MODE=0
271 NO_BINARY_MODE =
272 if stdenv.hostPlatform.isx86_64 then
273 toString (stdenv.hostPlatform != stdenv.buildPlatform)
274 else
275 stdenv.hostPlatform != stdenv.buildPlatform;
276 # This disables automatic build job count detection (which honours neither enableParallelBuilding nor NIX_BUILD_CORES)
277 # and uses the main make invocation's job count, falling back to 1 if no parallelism is used.
278 # https://github.com/OpenMathLib/OpenBLAS/blob/v0.3.20/getarch.c#L1781-L1792
279 MAKE_NB_JOBS = 0;
280 }
281 // (lib.optionalAttrs stdenv.cc.isClang {
282 LDFLAGS = "-L${lib.getLib buildPackages.gfortran.cc}/lib"; # contains `libgfortran.so`; building with clang needs this, gcc has it implicit
283 })
284 // (lib.optionalAttrs singleThreaded {
285 # As described on https://github.com/OpenMathLib/OpenBLAS/wiki/Faq/4bded95e8dc8aadc70ce65267d1093ca7bdefc4c#multi-threaded
286 USE_THREAD = false;
287 USE_LOCKING = true; # available with openblas >= 0.3.7
288 USE_OPENMP = false; # openblas will refuse building with both USE_OPENMP=1 and USE_THREAD=0
289 })
290 );
291
292 # The default "all" target unconditionally builds the "tests" target.
293 buildFlags = lib.optionals (!doCheck) [ "shared" ];
294
295 doCheck = true;
296 checkTarget = "tests";
297
298 postInstall = ''
299 # Write pkgconfig aliases. Upstream report:
300 # https://github.com/OpenMathLib/OpenBLAS/issues/1740
301 for alias in blas cblas lapack; do
302 cat <<EOF > $out/lib/pkgconfig/$alias.pc
303 Name: $alias
304 Version: ${version}
305 Description: $alias provided by the OpenBLAS package.
306 Cflags: -I$dev/include
307 Libs: -L$out/lib -lopenblas
308 EOF
309 done
310
311 # Setup symlinks for blas / lapack
312 ''
313 + lib.optionalString stdenv.hostPlatform.isMinGW ''
314 ln -s $out/bin/*.dll $out/lib
315 ''
316 + lib.optionalString enableShared ''
317 ln -s $out/lib/libopenblas${shlibExt} $out/lib/libblas${shlibExt}
318 ln -s $out/lib/libopenblas${shlibExt} $out/lib/libcblas${shlibExt}
319 ln -s $out/lib/libopenblas${shlibExt} $out/lib/liblapack${shlibExt}
320 ln -s $out/lib/libopenblas${shlibExt} $out/lib/liblapacke${shlibExt}
321 ''
322 + lib.optionalString (stdenv.hostPlatform.isLinux && enableShared) ''
323 ln -s $out/lib/libopenblas${shlibExt} $out/lib/libblas${shlibExt}.3
324 ln -s $out/lib/libopenblas${shlibExt} $out/lib/libcblas${shlibExt}.3
325 ln -s $out/lib/libopenblas${shlibExt} $out/lib/liblapack${shlibExt}.3
326 ln -s $out/lib/libopenblas${shlibExt} $out/lib/liblapacke${shlibExt}.3
327 ''
328 + lib.optionalString enableStatic ''
329 ln -s $out/lib/libopenblas.a $out/lib/libblas.a
330 ln -s $out/lib/libopenblas.a $out/lib/libcblas.a
331 ln -s $out/lib/libopenblas.a $out/lib/liblapack.a
332 ln -s $out/lib/libopenblas.a $out/lib/liblapacke.a
333 '';
334
335 passthru.tests = {
336 inherit (python3.pkgs) numpy scipy scikit-learn;
337 inherit
338 ceres-solver
339 giac
340 octave
341 opencv
342 ;
343 };
344
345 meta = {
346 description = "Basic Linear Algebra Subprograms";
347 license = lib.licenses.bsd3;
348 homepage = "https://github.com/OpenMathLib/OpenBLAS";
349 platforms = lib.attrNames configs;
350 maintainers = with lib.maintainers; [ ttuegel ];
351 };
352}