diff options
Diffstat (limited to 'nixpkgs/pkgs/development/libraries/science/math/openblas/default.nix')
-rw-r--r-- | nixpkgs/pkgs/development/libraries/science/math/openblas/default.nix | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/development/libraries/science/math/openblas/default.nix b/nixpkgs/pkgs/development/libraries/science/math/openblas/default.nix new file mode 100644 index 000000000000..950402315a9b --- /dev/null +++ b/nixpkgs/pkgs/development/libraries/science/math/openblas/default.nix @@ -0,0 +1,273 @@ +{ lib, stdenv, fetchFromGitHub, fetchpatch, 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 +# Multi-threaded applications must not call a threaded OpenBLAS +# (the only exception is when an application uses OpenMP as its +# *only* form of multi-threading). See +# https://github.com/xianyi/OpenBLAS/wiki/Faq/4bded95e8dc8aadc70ce65267d1093ca7bdefc4c#multi-threaded +# https://github.com/xianyi/OpenBLAS/issues/2543 +# This flag builds a single-threaded OpenBLAS using the flags +# stated in thre. +, singleThreaded ? false +, buildPackages +# Select a specific optimization target (other than the default) +# See https://github.com/xianyi/OpenBLAS/blob/develop/TargetList.txt +, target ? null +# Select whether DYNAMIC_ARCH is enabled or not. +, dynamicArch ? null +# enable AVX512 optimized kernels. +# These kernels have been a source of trouble in the past. +# Use with caution. +, enableAVX512 ? false +, enableStatic ? stdenv.hostPlatform.isStatic +, enableShared ? !stdenv.hostPlatform.isStatic + +# for passthru.tests +, ceres-solver +, giac +, octave +, opencv +, python3 +}: + +let blas64_ = blas64; in + +let + setTarget = x: if target == null then x else target; + setDynamicArch = x: if dynamicArch == null then x else dynamicArch; + + # To add support for a new platform, add an element to this set. + configs = { + armv6l-linux = { + BINARY = 32; + TARGET = setTarget "ARMV6"; + DYNAMIC_ARCH = setDynamicArch false; + USE_OPENMP = true; + }; + + armv7l-linux = { + BINARY = 32; + TARGET = setTarget "ARMV7"; + DYNAMIC_ARCH = setDynamicArch false; + USE_OPENMP = true; + }; + + aarch64-darwin = { + BINARY = 64; + TARGET = setTarget "VORTEX"; + DYNAMIC_ARCH = setDynamicArch true; + USE_OPENMP = false; + MACOSX_DEPLOYMENT_TARGET = "11.0"; + }; + + aarch64-linux = { + BINARY = 64; + TARGET = setTarget "ARMV8"; + DYNAMIC_ARCH = setDynamicArch true; + USE_OPENMP = true; + }; + + i686-linux = { + BINARY = 32; + TARGET = setTarget "P2"; + DYNAMIC_ARCH = setDynamicArch true; + USE_OPENMP = true; + }; + + x86_64-darwin = { + BINARY = 64; + TARGET = setTarget "ATHLON"; + DYNAMIC_ARCH = setDynamicArch true; + NO_AVX512 = !enableAVX512; + USE_OPENMP = false; + MACOSX_DEPLOYMENT_TARGET = "10.7"; + }; + + x86_64-linux = { + BINARY = 64; + TARGET = setTarget "ATHLON"; + DYNAMIC_ARCH = setDynamicArch true; + NO_AVX512 = !enableAVX512; + USE_OPENMP = !stdenv.hostPlatform.isMusl; + }; + + powerpc64le-linux = { + BINARY = 64; + TARGET = setTarget "POWER5"; + DYNAMIC_ARCH = setDynamicArch true; + USE_OPENMP = !stdenv.hostPlatform.isMusl; + }; + + riscv64-linux = { + BINARY = 64; + TARGET = setTarget "RISCV64_GENERIC"; + DYNAMIC_ARCH = setDynamicArch false; + USE_OPENMP = true; + }; + + loongarch64-linux = { + BINARY = 64; + TARGET = setTarget "LOONGSONGENERIC"; + DYNAMIC_ARCH = setDynamicArch false; + 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 lib.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 = lib.mapAttrsToList (var: val: "${var}=${mkMakeFlagValue val}"); + + shlibExt = stdenv.hostPlatform.extensions.sharedLibrary; + +in +stdenv.mkDerivation rec { + pname = "openblas"; + version = "0.3.21"; + + outputs = [ "out" "dev" ]; + + src = fetchFromGitHub { + owner = "xianyi"; + repo = "OpenBLAS"; + rev = "v${version}"; + sha256 = "sha256-F6cXPqQai4kA5zrsa8E0Q7dD9zZHlwZ+B16EOGNXoXs="; + }; + + patches = lib.optionals stdenv.hostPlatform.isLoongArch64 [ + # https://github.com/xianyi/OpenBLAS/pull/3626 + (fetchpatch { + name = "openblas-0.3.21-fix-loong.patch"; + url = "https://gitweb.gentoo.org/repo/gentoo.git/plain/sci-libs/openblas/files/openblas-0.3.21-fix-loong.patch?id=37ee4c70278eb41181f69e175575b0152b941655"; + hash = "sha256-iWy11l3wEvzNV08LbhOjnSPj1SjPH8RMnb3ORz7V+gc"; + }) + ]; + + postPatch = '' + # cc1: error: invalid feature modifier 'sve2' in '-march=armv8.5-a+sve+sve2+bf16' + substituteInPlace Makefile.arm64 --replace "+sve2+bf16" "" + ''; + + 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 + ]; + + depsBuildBuild = [ + buildPackages.gfortran + buildPackages.stdenv.cc + ]; + + enableParallelBuilding = true; + + makeFlags = mkMakeFlagsFromConfig (config // { + FC = "${stdenv.cc.targetPrefix}gfortran"; + CC = "${stdenv.cc.targetPrefix}${if stdenv.cc.isClang then "clang" else "cc"}"; + PREFIX = placeholder "out"; + OPENBLAS_INCLUDE_DIR = "${placeholder "dev"}/include"; + NUM_THREADS = 64; + INTERFACE64 = blas64; + NO_STATIC = !enableStatic; + NO_SHARED = !enableShared; + 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; + # This disables automatic build job count detection (which honours neither enableParallelBuilding nor NIX_BUILD_CORES) + # and uses the main make invocation's job count, falling back to 1 if no parallelism is used. + # https://github.com/xianyi/OpenBLAS/blob/v0.3.20/getarch.c#L1781-L1792 + MAKE_NB_JOBS = 0; + } // (lib.optionalAttrs singleThreaded { + # As described on https://github.com/xianyi/OpenBLAS/wiki/Faq/4bded95e8dc8aadc70ce65267d1093ca7bdefc4c#multi-threaded + USE_THREAD = false; + USE_LOCKING = true; # available with openblas >= 0.3.7 + USE_OPENMP = false; # openblas will refuse building with both USE_OPENMP=1 and USE_THREAD=0 + })); + + 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$dev/include +Libs: -L$out/lib -lopenblas +EOF + done + + # Setup symlinks for blas / lapack + '' + lib.optionalString enableShared '' + ln -s $out/lib/libopenblas${shlibExt} $out/lib/libblas${shlibExt} + ln -s $out/lib/libopenblas${shlibExt} $out/lib/libcblas${shlibExt} + ln -s $out/lib/libopenblas${shlibExt} $out/lib/liblapack${shlibExt} + ln -s $out/lib/libopenblas${shlibExt} $out/lib/liblapacke${shlibExt} + '' + lib.optionalString (stdenv.hostPlatform.isLinux && enableShared) '' + ln -s $out/lib/libopenblas${shlibExt} $out/lib/libblas${shlibExt}.3 + ln -s $out/lib/libopenblas${shlibExt} $out/lib/libcblas${shlibExt}.3 + ln -s $out/lib/libopenblas${shlibExt} $out/lib/liblapack${shlibExt}.3 + ln -s $out/lib/libopenblas${shlibExt} $out/lib/liblapacke${shlibExt}.3 + '' + lib.optionalString enableStatic '' + ln -s $out/lib/libopenblas.a $out/lib/libblas.a + ln -s $out/lib/libopenblas.a $out/lib/libcblas.a + ln -s $out/lib/libopenblas.a $out/lib/liblapack.a + ln -s $out/lib/libopenblas.a $out/lib/liblapacke.a + ''; + + passthru.tests = { + inherit (python3.pkgs) numpy scipy; + inherit ceres-solver giac octave opencv; + }; + + meta = with lib; { + description = "Basic Linear Algebra Subprograms"; + license = licenses.bsd3; + homepage = "https://github.com/xianyi/OpenBLAS"; + platforms = attrNames configs; + maintainers = with maintainers; [ ttuegel ]; + }; +} |