Files
nixpkgs/pkgs/development/libraries/science/math/cudnn/generic.nix
2023-11-08 19:06:44 -03:00

171 lines
6.4 KiB
Nix

{ stdenv,
backendStdenv,
lib,
lndir,
zlib,
useCudatoolkitRunfile ? false,
cudaVersion,
cudaMajorVersion,
cudatoolkit, # For cuda < 11
libcublas ? null, # cuda <11 doesn't ship redist packages
autoPatchelfHook,
autoAddOpenGLRunpathHook,
fetchurl,
}: {
version,
url,
hash,
minCudaVersion,
maxCudaVersion,
}:
assert useCudatoolkitRunfile || (libcublas != null); let
inherit (lib) lists strings trivial versions;
# majorMinorPatch :: String -> String
majorMinorPatch = (trivial.flip trivial.pipe) [
(versions.splitVersion)
(lists.take 3)
(strings.concatStringsSep ".")
];
# versionTriple :: String
# Version with three components: major.minor.patch
versionTriple = majorMinorPatch version;
in
backendStdenv.mkDerivation {
pname = "cudatoolkit-${cudaMajorVersion}-cudnn";
version = versionTriple;
strictDeps = true;
outputs = ["out" "lib" "static" "dev"];
src = fetchurl {
inherit url hash;
};
# We do need some other phases, like configurePhase, so the multiple-output setup hook works.
dontBuild = true;
# Check and normalize Runpath against DT_NEEDED using autoPatchelf.
# Prepend /run/opengl-driver/lib using addOpenGLRunpath for dlopen("libcudacuda.so")
nativeBuildInputs = [
autoPatchelfHook
autoAddOpenGLRunpathHook
];
# Used by autoPatchelfHook
buildInputs = [
# Note this libstdc++ isn't from the (possibly older) nvcc-compatible
# stdenv, but from the (newer) stdenv that the rest of nixpkgs uses
stdenv.cc.cc.lib
zlib
] ++ lists.optionals useCudatoolkitRunfile [
cudatoolkit
] ++ lists.optionals (!useCudatoolkitRunfile) [
libcublas.lib
];
# We used to patch Runpath here, but now we use autoPatchelfHook
#
# Note also that version <=8.3.0 contained a subdirectory "lib64/" but in
# version 8.3.2 it seems to have been renamed to simply "lib/".
#
# doc and dev have special output handling. Other outputs need to be moved to their own
# output.
# Note that moveToOutput operates on all outputs:
# https://github.com/NixOS/nixpkgs/blob/2920b6fc16a9ed5d51429e94238b28306ceda79e/pkgs/build-support/setup-hooks/multiple-outputs.sh#L105-L107
installPhase =
''
runHook preInstall
mkdir -p "$out"
mv * "$out"
moveToOutput "lib64" "$lib"
moveToOutput "lib" "$lib"
moveToOutput "**/*.a" "$static"
runHook postInstall
'';
# Without --add-needed autoPatchelf forgets $ORIGIN on cuda>=8.0.5.
postFixup = strings.optionalString (strings.versionAtLeast versionTriple "8.0.5") ''
patchelf $lib/lib/libcudnn.so --add-needed libcudnn_cnn_infer.so
patchelf $lib/lib/libcudnn_ops_infer.so --add-needed libcublas.so --add-needed libcublasLt.so
'';
# The out output leverages the same functionality which backs the `symlinkJoin` function in
# Nixpkgs:
# https://github.com/NixOS/nixpkgs/blob/d8b2a92df48f9b08d68b0132ce7adfbdbc1fbfac/pkgs/build-support/trivial-builders/default.nix#L510
#
# That should allow us to emulate "fat" default outputs without having to actually create them.
#
# It is important that this run after the autoPatchelfHook, otherwise the symlinks in out will reference libraries in lib, creating a circular dependency.
postPhases = ["postPatchelf"];
# For each output, create a symlink to it in the out output.
# NOTE: We must recreate the out output here, because the setup hook will have deleted it
# if it was empty.
# NOTE: Do not use optionalString based on whether `outputs` contains only `out` -- phases
# which are empty strings are skipped/unset and result in errors of the form "command not
# found: <customPhaseName>".
postPatchelf = ''
mkdir -p "$out"
${lib.meta.getExe lndir} "$lib" "$out"
${lib.meta.getExe lndir} "$static" "$out"
${lib.meta.getExe lndir} "$dev" "$out"
'';
passthru = {
inherit useCudatoolkitRunfile;
cudatoolkit =
trivial.warn
''
cudnn.cudatoolkit passthru attribute is deprecated;
if your derivation uses cudnn directly, it should probably consume cudaPackages instead
''
cudatoolkit;
majorVersion = versions.major versionTriple;
};
# Setting propagatedBuildInputs to false will prevent outputs known to the multiple-outputs
# from depending on `out` by default.
# https://github.com/NixOS/nixpkgs/blob/2920b6fc16a9ed5d51429e94238b28306ceda79e/pkgs/build-support/setup-hooks/multiple-outputs.sh#L196
# Indeed, we want to do the opposite -- fat "out" outputs that contain all the other outputs.
propagatedBuildOutputs = false;
# By default, if the dev output exists it just uses that.
# However, because we disabled propagatedBuildOutputs, dev doesn't contain libraries or
# anything of the sort. To remedy this, we set outputSpecified to true, and use
# outputsToInstall, which tells Nix which outputs to use when the package name is used
# unqualified (that is, without an explicit output).
outputSpecified = true;
meta = with lib; {
# Check that the cudatoolkit version satisfies our min/max constraints (both
# inclusive). We mark the package as broken if it fails to satisfies the
# official version constraints (as recorded in default.nix). In some cases
# you _may_ be able to smudge version constraints, just know that you're
# embarking into unknown and unsupported territory when doing so.
broken =
strings.versionOlder cudaVersion minCudaVersion
|| strings.versionOlder maxCudaVersion cudaVersion;
description = "NVIDIA CUDA Deep Neural Network library (cuDNN)";
homepage = "https://developer.nvidia.com/cudnn";
sourceProvenance = with sourceTypes; [binaryNativeCode];
license = {
shortName = "cuDNN EULA";
fullName = "NVIDIA cuDNN Software License Agreement (EULA)";
url = "https://docs.nvidia.com/deeplearning/sdk/cudnn-sla/index.html#supplement";
free = false;
} // lib.optionalAttrs (!useCudatoolkitRunfile) {
redistributable = true;
};
platforms = ["x86_64-linux"];
maintainers = with maintainers; [mdaiter samuela];
# Force the use of the default, fat output by default (even though `dev` exists, which
# causes Nix to prefer that output over the others if outputSpecified isn't set).
outputsToInstall = ["out"];
};
}