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