1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
{
_cuda,
config,
lib,
pkgs,
# Manually provided arguments
manifests,
}:
let
inherit (lib.customisation) callPackagesWith;
inherit (lib.filesystem) packagesFromDirectoryRecursive;
inherit (lib.fixedPoints) composeManyExtensions extends;
inherit (lib.lists) optionals;
inherit (lib.strings) versionAtLeast versionOlder;
inherit (lib.versions) major majorMinor;
inherit (_cuda.lib)
dropDots
formatCapabilities
mkVersionedName
;
# NOTE: This value is considered an implementation detail and should not be exposed in the attribute set.
cudaMajorMinorPatchVersion = manifests.cuda.release_label;
cudaMajorMinorVersion = majorMinor cudaMajorMinorPatchVersion;
cudaMajorVersion = major cudaMajorMinorPatchVersion;
# We must use an instance of Nixpkgs where the CUDA package set we're building is the default; if we do not, members
# of the versioned, non-default package sets may rely on (transitively) members of the default, unversioned CUDA
# package set.
# See `Using cudaPackages.pkgs` in doc/languages-frameworks/cuda.section.md for more information.
pkgs' =
let
cudaPackagesUnversionedName = "cudaPackages";
cudaPackagesMajorVersionedName = mkVersionedName cudaPackagesUnversionedName cudaMajorVersion;
cudaPackagesMajorMinorVersionedName = mkVersionedName cudaPackagesUnversionedName cudaMajorMinorVersion;
in
if
# If the default CUDA package set is the same as the one we're constructing, pass through pkgs unchanged.
# This is a handy speedup for cases where we're using the default CUDA package set and don't need to pay for
# a re-instantiation of Nixpkgs.
pkgs.${cudaPackagesMajorMinorVersionedName}.manifests
== pkgs.${cudaPackagesMajorVersionedName}.manifests
&&
pkgs.${cudaPackagesMajorMinorVersionedName}.manifests
== pkgs.${cudaPackagesUnversionedName}.manifests
then
pkgs
else
pkgs.extend (
final: _: {
recurseForDerivations = false;
# The CUDA package set will be available as cudaPackages_x_y, so we need only update the aliases for the
# minor-versioned and unversioned package sets.
# However, if we do not replace the major-minor-versioned CUDA package set with our own, our use of splicing
# causes the package set to be re-evaluated for each build/host/target!
# cudaPackages_x_y = <package set created in this file>
${cudaPackagesMajorMinorVersionedName} = cudaPackages;
# cudaPackages_x = cudaPackages_x_y
${cudaPackagesMajorVersionedName} = final.${cudaPackagesMajorMinorVersionedName};
# cudaPackages = cudaPackages_x
${cudaPackagesUnversionedName} = final.${cudaPackagesMajorVersionedName};
}
);
cudaPackagesFixedPoint =
finalCudaPackages:
{
# NOTE:
# It is important that _cuda is not part of the package set fixed-point. As described by
# @SomeoneSerge:
# > The layering should be: configuration -> (identifies/is part of) cudaPackages -> (is built using) cudaLib.
# > No arrows should point in the reverse directions.
# That is to say that cudaLib should only know about package sets and configurations, because it implements
# functionality for interpreting configurations, resolving them against data, and constructing package sets.
# This decision is driven both by a separation of concerns and by "NAMESET STRICTNESS" (see above).
# Also see the comment in `pkgs/top-level/all-packages.nix` about the `_cuda` attribute.
inherit
cudaMajorMinorPatchVersion
cudaMajorMinorVersion
cudaMajorVersion
;
pkgs = pkgs';
# Core
callPackages = callPackagesWith (pkgs' // finalCudaPackages);
cudaNamePrefix = "cuda${cudaMajorMinorVersion}";
cudaOlder = versionOlder cudaMajorMinorVersion;
cudaAtLeast = versionAtLeast cudaMajorMinorVersion;
# These must be modified through callPackage, not by overriding the scope, since we cannot
# depend on them recursively as they are used to add top-level attributes.
inherit manifests;
# Construct without relying on the fixed-point to allow the use of backendStdenv in creating CUDA package sets.
# For example, this allows selecting manifests by predicating on values like
# `backendStdenv.hasJetsonCudaCapability`, which would otherwise result in infinite recursion due to the reliance
# on `pkgs'`, which in turn depends on the manifests provided to this file (which can depend on `backendStdenv`).
backendStdenv = import ./backendStdenv {
inherit
_cuda
config
cudaMajorMinorVersion
lib
pkgs
;
inherit (pkgs)
stdenv
stdenvAdapters
;
};
# Create backendStdenv variants for different host compilers, since users may want to build a CUDA project with
# Clang or GCC specifically.
# TODO(@connorbaker): Because of the way our setup hooks and patching of NVCC works, the user's choice of
# backendStdenv is largely disregarded or will cause build failures; fixing this would require the setup hooks
# and patching to be made aware of the current environment (perhaps by reading certain environment variables set
# by our backendStdenv).
# backendClangStdenv = finalCudaPackages.callPackage ./packages/backendStdenv.nix {
# stdenv = pkgs'.clangStdenv;
# };
# backendGccStdenv = finalCudaPackages.callPackage ./packages/backendStdenv.nix {
# stdenv = pkgs'.gccStdenv;
# };
# Must be constructed without `callPackage` to avoid replacing the `override` attribute with that of
# `callPackage`'s.
buildRedist = import ./buildRedist {
inherit
_cuda
lib
;
inherit (pkgs)
autoAddDriverRunpath
autoPatchelfHook
fetchurl
srcOnly
stdenv
stdenvNoCC
zstd
;
inherit (finalCudaPackages)
autoAddCudaCompatRunpath
backendStdenv
cudaMajorMinorVersion
cudaMajorVersion
cudaNamePrefix
manifests
markForCudatoolkitRootHook
removeStubsFromRunpathHook
;
};
flags =
formatCapabilities {
inherit (finalCudaPackages.backendStdenv) cudaCapabilities cudaForwardCompat;
inherit (_cuda.db) cudaCapabilityToInfo;
}
# TODO(@connorbaker): Enable the corresponding warnings in `./aliases.nix` after some
# time to allow users to migrate to cudaLib and backendStdenv.
// {
inherit dropDots;
cudaComputeCapabilityToName =
cudaCapability: _cuda.db.cudaCapabilityToInfo.${cudaCapability}.archName;
dropDot = dropDots;
isJetsonBuild = finalCudaPackages.backendStdenv.hasJetsonCudaCapability;
};
}
// packagesFromDirectoryRecursive {
inherit (finalCudaPackages) callPackage;
directory = ./packages;
};
composedExtensions = composeManyExtensions (
optionals config.allowAliases [
(import ./aliases.nix { inherit lib; })
]
++ _cuda.extensions
);
# Using lib.makeScopeWithSplicing' instead of the templated one from pkgs' allows us to defer calling pkgs.extend.
cudaPackages =
lib.makeScopeWithSplicing'
{
splicePackages = pkgs'.splicePackages;
newScope = pkgs'.newScope;
}
{
# In pkgs', the default CUDA package set is always the one we've constructed here.
otherSplices = pkgs'.generateSplicesForMkScope [ "cudaPackages" ];
f = extends composedExtensions cudaPackagesFixedPoint;
};
in
cudaPackages
|