diff options
Diffstat (limited to 'pkgs/build-support/alternatives/blas/default.nix')
-rw-r--r-- | pkgs/build-support/alternatives/blas/default.nix | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/pkgs/build-support/alternatives/blas/default.nix b/pkgs/build-support/alternatives/blas/default.nix new file mode 100644 index 00000000000..bdee6688a74 --- /dev/null +++ b/pkgs/build-support/alternatives/blas/default.nix @@ -0,0 +1,141 @@ +{ lib, stdenv +, lapack-reference, openblasCompat, openblas +, isILP64 ? false +, blasProvider ? if isILP64 then openblas else openblasCompat }: + +let + blasFortranSymbols = [ + "caxpy" "ccopy" "cdotc" "cdotu" "cgbmv" "cgemm" "cgemv" "cgerc" "cgeru" + "chbmv" "chemm" "chemv" "cher" "cher2" "cher2k" "cherk" "chpmv" "chpr" + "chpr2" "crotg" "cscal" "csrot" "csscal" "cswap" "csymm" "csyr2k" "csyrk" + "ctbmv" "ctbsv" "ctpmv" "ctpsv" "ctrmm" "ctrmv" "ctrsm" "ctrsv" "dasum" + "daxpy" "dcabs1" "dcopy" "ddot" "dgbmv" "dgemm" "dgemv" "dger" "dnrm2" + "drot" "drotg" "drotm" "drotmg" "dsbmv" "dscal" "dsdot" "dspmv" "dspr" + "dspr2" "dswap" "dsymm" "dsymv" "dsyr" "dsyr2" "dsyr2k" "dsyrk" "dtbmv" + "dtbsv" "dtpmv" "dtpsv" "dtrmm" "dtrmv" "dtrsm" "dtrsv" "dzasum" "dznrm2" + "icamax" "idamax" "isamax" "izamax" "lsame" "sasum" "saxpy" "scabs1" + "scasum" "scnrm2" "scopy" "sdot" "sdsdot" "sgbmv" "sgemm" "sgemv" + "sger" "snrm2" "srot" "srotg" "srotm" "srotmg" "ssbmv" "sscal" "sspmv" + "sspr" "sspr2" "sswap" "ssymm" "ssymv" "ssyr" "ssyr2" "ssyr2k" "ssyrk" + "stbmv" "stbsv" "stpmv" "stpsv" "strmm" "strmv" "strsm" "strsv" "xerbla" + "xerbla_array" "zaxpy" "zcopy" "zdotc" "zdotu" "zdrot" "zdscal" "zgbmv" + "zgemm" "zgemv" "zgerc" "zgeru" "zhbmv" "zhemm" "zhemv" "zher" "zher2" + "zher2k" "zherk" "zhpmv" "zhpr" "zhpr2" "zrotg" "zscal" "zswap" "zsymm" + "zsyr2k" "zsyrk" "ztbmv" "ztbsv" "ztpmv" "ztpsv" "ztrmm" "ztrmv" "ztrsm" + "ztrsv" + ]; + + version = "3"; + canonicalExtension = if stdenv.hostPlatform.isLinux + then "${stdenv.hostPlatform.extensions.sharedLibrary}.${version}" + else stdenv.hostPlatform.extensions.sharedLibrary; + + + isILP64 = blasProvider.blas64 or false; + blasImplementation = lib.getName blasProvider; + +in + +assert isILP64 -> (blasImplementation == "openblas" && blasProvider.blas64) || blasImplementation == "mkl"; + +stdenv.mkDerivation { + pname = "blas"; + inherit version; + + outputs = [ "out" "dev" ]; + + meta = (blasProvider.meta or {}) // { + description = "${lib.getName blasProvider} with just the BLAS C and FORTRAN ABI"; + }; + + passthru = { + inherit isILP64; + provider = blasProvider; + implementation = blasImplementation; + }; + + dontBuild = true; + dontConfigure = true; + unpackPhase = "src=$PWD"; + + dontPatchELF = true; + + installPhase = ('' + mkdir -p $out/lib $dev/include $dev/lib/pkgconfig + + libblas="${lib.getLib blasProvider}/lib/libblas${canonicalExtension}" + + if ! [ -e "$libblas" ]; then + echo "$libblas does not exist, ${blasProvider.name} does not provide libblas." + exit 1 + fi + + nm -an "$libblas" | cut -f3 -d' ' > symbols + for symbol in ${toString blasFortranSymbols}; do + grep "^$symbol_$" symbols || { echo "$symbol" was not found in "$libblas"; exit 1; } + done + + cp -L "$libblas" $out/lib/libblas${canonicalExtension} + chmod +w $out/lib/libblas${canonicalExtension} + +'' + (if stdenv.hostPlatform.parsed.kernel.execFormat.name == "elf" then '' + patchelf --set-soname libblas${canonicalExtension} $out/lib/libblas${canonicalExtension} + patchelf --set-rpath "$(patchelf --print-rpath $out/lib/libblas${canonicalExtension}):${lib.getLib blasProvider}/lib" $out/lib/libblas${canonicalExtension} +'' else if stdenv.hostPlatform.isDarwin then '' + install_name_tool \ + -id libblas${canonicalExtension} \ + -add_rpath ${lib.getLib blasProvider}/lib \ + $out/lib/libblas${canonicalExtension} +'' else "") + '' + + if [ "$out/lib/libblas${canonicalExtension}" != "$out/lib/libblas${stdenv.hostPlatform.extensions.sharedLibrary}" ]; then + ln -s $out/lib/libblas${canonicalExtension} "$out/lib/libblas${stdenv.hostPlatform.extensions.sharedLibrary}" + fi + + cat <<EOF > $dev/lib/pkgconfig/blas.pc +Name: blas +Version: ${version} +Description: BLAS FORTRAN implementation +Libs: -L$out/lib -lblas +Cflags: -I$dev/include +EOF + + libcblas="${lib.getLib blasProvider}/lib/libcblas${canonicalExtension}" + + if ! [ -e "$libcblas" ]; then + echo "$libcblas does not exist, ${blasProvider.name} does not provide libcblas." + exit 1 + fi + + cp -L "$libcblas" $out/lib/libcblas${canonicalExtension} + chmod +w $out/lib/libcblas${canonicalExtension} + +'' + (if stdenv.hostPlatform.parsed.kernel.execFormat.name == "elf" then '' + patchelf --set-soname libcblas${canonicalExtension} $out/lib/libcblas${canonicalExtension} + patchelf --set-rpath "$(patchelf --print-rpath $out/lib/libcblas${canonicalExtension}):${lib.getLib blasProvider}/lib" $out/lib/libcblas${canonicalExtension} +'' else if stdenv.hostPlatform.isDarwin then '' + install_name_tool \ + -id libcblas${canonicalExtension} \ + -add_rpath ${lib.getLib blasProvider}/lib \ + $out/lib/libcblas${canonicalExtension} +'' else "") + '' + if [ "$out/lib/libcblas${canonicalExtension}" != "$out/lib/libcblas${stdenv.hostPlatform.extensions.sharedLibrary}" ]; then + ln -s $out/lib/libcblas${canonicalExtension} "$out/lib/libcblas${stdenv.hostPlatform.extensions.sharedLibrary}" + fi + + cp ${lib.getDev lapack-reference}/include/cblas{,_mangling}.h $dev/include + + cat <<EOF > $dev/lib/pkgconfig/cblas.pc +Name: cblas +Version: ${version} +Description: BLAS C implementation +Cflags: -I$dev/include +Libs: -L$out/lib -lcblas +EOF +'' + stdenv.lib.optionalString (blasImplementation == "mkl") '' + mkdir -p $out/nix-support + echo 'export MKL_INTERFACE_LAYER=${lib.optionalString isILP64 "I"}LP64,GNU' > $out/nix-support/setup-hook + ln -s $out/lib/libblas${canonicalExtension} $out/lib/libmkl_rt${stdenv.hostPlatform.extensions.sharedLibrary} + ln -sf ${blasProvider}/include/* $dev/include +''); +} |