1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
{ stdenv, fetchFromGitHub, perl, which
# Most packages depending on openblas expect integer width to match
# pointer width, but some expect to use 32-bit integers always
# (for compatibility with reference BLAS).
, blas64 ? null
, buildPackages
# Select a specific optimization target (other than the default)
# See https://github.com/xianyi/OpenBLAS/blob/develop/TargetList.txt
, target ? null
, enableStatic ? false
}:
with stdenv.lib;
let blas64_ = blas64; in
let
setTarget = x: if target == null then x else target;
# To add support for a new platform, add an element to this set.
configs = {
armv6l-linux = {
BINARY = 32;
TARGET = setTarget "ARMV6";
DYNAMIC_ARCH = false;
USE_OPENMP = true;
};
armv7l-linux = {
BINARY = 32;
TARGET = setTarget "ARMV7";
DYNAMIC_ARCH = false;
USE_OPENMP = true;
};
aarch64-linux = {
BINARY = 64;
TARGET = setTarget "ARMV8";
DYNAMIC_ARCH = true;
USE_OPENMP = true;
};
i686-linux = {
BINARY = 32;
TARGET = setTarget "P2";
DYNAMIC_ARCH = true;
USE_OPENMP = true;
};
x86_64-darwin = {
BINARY = 64;
TARGET = setTarget "ATHLON";
DYNAMIC_ARCH = true;
USE_OPENMP = false;
MACOSX_DEPLOYMENT_TARGET = "10.7";
};
x86_64-linux = {
BINARY = 64;
TARGET = setTarget "ATHLON";
DYNAMIC_ARCH = true;
NO_AVX512 = true;
USE_OPENMP = true;
};
};
in
let
config =
configs.${stdenv.hostPlatform.system}
or (throw "unsupported system: ${stdenv.hostPlatform.system}");
in
let
blas64 =
if blas64_ != null
then blas64_
else hasPrefix "x86_64" stdenv.hostPlatform.system;
# Convert flag values to format OpenBLAS's build expects.
# `toString` is almost what we need other than bools,
# which we need to map {true -> 1, false -> 0}
# (`toString` produces empty string `""` for false instead of `0`)
mkMakeFlagValue = val:
if !builtins.isBool val then toString val
else if val then "1" else "0";
mkMakeFlagsFromConfig = mapAttrsToList (var: val: "${var}=${mkMakeFlagValue val}");
in
stdenv.mkDerivation rec {
name = "openblas-${version}";
version = "0.3.6";
src = fetchFromGitHub {
owner = "xianyi";
repo = "OpenBLAS";
rev = "v${version}";
sha256 = "12vg0g3s4m49fr8z04j15yrgscqnaaflnkckjbffqxnrf90fcav1";
};
inherit blas64;
# Some hardening features are disabled due to sporadic failures in
# OpenBLAS-based programs. The problem may not be with OpenBLAS itself, but
# with how these flags interact with hardening measures used downstream.
# In either case, OpenBLAS must only be used by trusted code--it is
# inherently unsuitable for security-conscious applications--so there should
# be no objection to disabling these hardening measures.
hardeningDisable = [
# don't modify or move the stack
"stackprotector" "pic"
# don't alter index arithmetic
"strictoverflow"
# don't interfere with dynamic target detection
"relro" "bindnow"
];
nativeBuildInputs = [
perl
which
buildPackages.gfortran
buildPackages.stdenv.cc
];
makeFlags = mkMakeFlagsFromConfig (config // {
FC = "${stdenv.cc.targetPrefix}gfortran";
CC = "${stdenv.cc.targetPrefix}${if stdenv.cc.isClang then "clang" else "cc"}";
PREFIX = placeholder "out";
NUM_THREADS = 64;
INTERFACE64 = blas64;
NO_STATIC = !enableStatic;
CROSS = stdenv.hostPlatform != stdenv.buildPlatform;
HOSTCC = "cc";
# Makefile.system only checks defined status
# This seems to be a bug in the openblas Makefile:
# on x86_64 it expects NO_BINARY_MODE=
# but on aarch64 it expects NO_BINARY_MODE=0
NO_BINARY_MODE = if stdenv.isx86_64
then toString (stdenv.hostPlatform != stdenv.buildPlatform)
else stdenv.hostPlatform != stdenv.buildPlatform;
});
doCheck = true;
checkTarget = "tests";
postInstall = ''
# Write pkgconfig aliases. Upstream report:
# https://github.com/xianyi/OpenBLAS/issues/1740
for alias in blas cblas lapack; do
cat <<EOF > $out/lib/pkgconfig/$alias.pc
Name: $alias
Version: ${version}
Description: $alias provided by the OpenBLAS package.
Cflags: -I$out/include
Libs: -L$out/lib -lopenblas
EOF
done
'';
meta = with stdenv.lib; {
description = "Basic Linear Algebra Subprograms";
license = licenses.bsd3;
homepage = https://github.com/xianyi/OpenBLAS;
platforms = platforms.unix;
maintainers = with maintainers; [ ttuegel ];
};
# We use linkName to pass a different name to --with-blas-libs for
# fflas-ffpack and linbox, because we use blas on darwin but openblas
# elsewhere.
# See see https://github.com/NixOS/nixpkgs/pull/45013.
passthru.linkName = "openblas";
}
|