1# CUDA Modules
2
3> [!NOTE]
4> This document is meant to help CUDA maintainers understand the structure of
5> the CUDA packages in Nixpkgs. It is not meant to be a user-facing document.
6> For a user-facing document, see [the CUDA section of the manual](../../../doc/languages-frameworks/cuda.section.md).
7
8The files in this directory are added (in some way) to the `cudaPackages`
9package set by [cuda-packages.nix](../../top-level/cuda-packages.nix).
10
11## Top-level directories
12
13- `cuda`: CUDA redistributables! Provides extension to `cudaPackages` scope.
14- `cudatoolkit`: monolithic CUDA Toolkit run-file installer. Provides extension
15 to `cudaPackages` scope.
16- `cudnn`: NVIDIA cuDNN library.
17- `cutensor`: NVIDIA cuTENSOR library.
18- `fixups`: Each file or directory (excluding `default.nix`) should contain a
19 `callPackage`-able expression to be provided to the `overrideAttrs` attribute
20 of a package produced by the generic manifest builder.
21 These fixups are applied by `pname`, so packages with multiple versions
22 (e.g., `cudnn`, `cudnn_8_9`, etc.) all share a single fixup function
23 (i.e., `fixups/cudnn.nix`).
24- `generic-builders`:
25 - Contains a builder `manifest.nix` which operates on the `Manifest` type
26 defined in `modules/generic/manifests`. Most packages are built using this
27 builder.
28 - Contains a builder `multiplex.nix` which leverages the Manifest builder. In
29 short, the Multiplex builder adds multiple versions of a single package to
30 single instance of the CUDA Packages package set. It is used primarily for
31 packages like `cudnn` and `cutensor`.
32- `modules`: Nixpkgs modules to check the shape and content of CUDA
33 redistributable and feature manifests. These modules additionally use shims
34 provided by some CUDA packages to allow them to re-use the
35 `genericManifestBuilder`, even if they don't have manifest files of their
36 own. `cudnn` and `tensorrt` are examples of packages which provide such
37 shims. These modules are further described in the
38 [Modules](./modules/README.md) documentation.
39- `packages`: Contains packages which exist in every instance of the CUDA
40 package set. These packages are built in a `by-name` fashion.
41- `setup-hooks`: Nixpkgs setup hooks for CUDA.
42- `tensorrt`: NVIDIA TensorRT library.
43
44## Distinguished packages
45
46### CUDA Compatibility
47
48[CUDA Compatibility](https://docs.nvidia.com/deploy/cuda-compatibility/),
49available as `cudaPackages.cuda_compat`, is a component which makes it possible
50to run applications built against a newer CUDA toolkit (for example CUDA 12) on
51a machine with an older CUDA driver (for example CUDA 11), which isn't possible
52out of the box. At the time of writing, CUDA Compatibility is only available on
53the Nvidia Jetson architecture, but Nvidia might release support for more
54architectures in the future.
55
56As CUDA Compatibility strictly increases the range of supported applications, we
57try our best to enable it by default on supported platforms.
58
59#### Functioning
60
61`cuda_compat` simply provides a new `libcuda.so` (and associated variants) that
62needs to be used in place of the default CUDA driver's `libcuda.so`. However,
63the other shared libraries of the default driver must still be accessible:
64`cuda_compat` isn't a complete drop-in replacement for the driver (and that's
65the point, otherwise, it would just be a newer driver).
66
67Nvidia's recommendation is to set `LD_LIBRARY_PATH` to point to `cuda_compat`'s
68driver. This is fine for a manual, one-shot usage, but in general setting
69`LD_LIBRARY_PATH` is a red flag. This is global state which short-circuits most
70of other dynamic library resolution mechanisms and can break things in
71non-obvious ways, especially with other Nix-built software.
72
73#### CUDA Compat with Nix
74
75Since `cuda_compat` is a known derivation, the easy way to do this in Nix would
76be to add `cuda_compat` as a dependency of CUDA libraries and applications and
77let Nix do its magic by filling the `DT_RUNPATH` fields. However,
78`cuda_compat` itself depends on `libnvrm_mem` and `libnvrm_gpu` which are loaded
79dynamically at runtime from `/run/opengl-driver`. This doesn't please the Nix
80sandbox when building, which can't find those (a second minor issue is that
81`addOpenGLRunpathHook` prepends the `/run/opengl-driver` path, so that would
82still take precedence).
83
84The current solution is to do something similar to `addOpenGLRunpathHook`: the
85`addCudaCompatRunpathHook` prepends to the path to `cuda_compat`'s `libcuda.so`
86to the `DT_RUNPATH` of whichever package includes the hook as a dependency, and
87we include the hook by default for packages in `cudaPackages` (by adding it as a
88inputs in `genericManifestBuilder`). We also make sure it's included after
89`addOpenGLRunpathHook`, so that it appears _before_ in the `DT_RUNPATH` and
90takes precedence.