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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
{
defaultConfig ? null,
}@args:
let
lib = import ../../../lib;
# By taking defaultConfig early, we can cache the result of calling
# make-derivation.nix with config, which leads to more memoisation between
# bootstrapping stages. We only have to re-call the file with another config
# if stdenv-overridable is actually called with config, otherwise we stick to
# defaultConfig. No stdenvs currently specify a non-default config, but we
# leave it open as a possibility.
makeDerivationFile = import ./make-derivation.nix lib;
makeDerivationFileWithConfig =
assert args ? defaultConfig;
makeDerivationFile args.defaultConfig;
defaultNativeBuildInputs0 = [
../../build-support/setup-hooks/no-broken-symlinks.sh
../../build-support/setup-hooks/audit-tmpdir.sh
../../build-support/setup-hooks/compress-man-pages.sh
../../build-support/setup-hooks/make-symlinks-relative.sh
../../build-support/setup-hooks/move-docs.sh
../../build-support/setup-hooks/move-lib64.sh
../../build-support/setup-hooks/move-sbin.sh
../../build-support/setup-hooks/move-systemd-user-units.sh
../../build-support/setup-hooks/multiple-outputs.sh
../../build-support/setup-hooks/patch-shebangs.sh
../../build-support/setup-hooks/prune-libtool-files.sh
../../build-support/setup-hooks/reproducible-builds.sh
../../build-support/setup-hooks/set-source-date-epoch-to-latest.sh
../../build-support/setup-hooks/strip.sh
];
stdenv-overridable = lib.makeOverridable (
argsStdenv@{
name ? "stdenv",
pname ? name,
version ? "26.05pre-git",
preHook ? "",
initialPath,
# If we don't have a C compiler, we might either have `cc = null` or `cc =
# throw ...`, but if we do have a C compiler we should definitely have `cc !=
# null`.
#
# TODO(@Ericson2314): Add assert without creating infinite recursion
hasCC ? cc != null,
cc,
shell,
allowedRequisites ? null,
extraAttrs ? { },
overrides ? (self: super: { }),
config ? args.defaultConfig,
disallowedRequisites ? [ ],
# The `fetchurl' to use for downloading curl and its dependencies
# (see all-packages.nix).
fetchurlBoot,
setupScript ? ./setup.sh,
extraNativeBuildInputs ? [ ],
extraBuildInputs ? [ ],
__stdenvImpureHostDeps ? [ ],
__extraImpureHostDeps ? [ ],
stdenvSandboxProfile ? "",
extraSandboxProfile ? "",
## Platform parameters
##
## The "build" "host" "target" terminology below comes from GNU Autotools. See
## its documentation for more information on what those words mean. Note that
## each should always be defined, even when not cross compiling.
##
## For purposes of bootstrapping, think of each stage as a "sliding window"
## over a list of platforms. Specifically, the host platform of the previous
## stage becomes the build platform of the current one, and likewise the
## target platform of the previous stage becomes the host platform of the
## current one.
##
# The platform on which packages are built. Consists of `system`, a
# string (e.g.,`i686-linux') identifying the most import attributes of the
# build platform, and `platform` a set of other details.
buildPlatform,
# The platform on which packages run.
hostPlatform,
# The platform which build tools (especially compilers) build for in this stage,
targetPlatform,
# The implementation of `mkDerivation`, parameterized with the final stdenv so we can tie the knot.
# This is convenient to have as a parameter so the stdenv "adapters" work better
mkDerivationFromStdenv ?
let
makeDerivationWithConfig' =
if argsStdenv ? config then makeDerivationFile config else makeDerivationFileWithConfig;
in
stdenv: (makeDerivationWithConfig' stdenv).mkDerivation,
}:
let
defaultNativeBuildInputs =
extraNativeBuildInputs ++ defaultNativeBuildInputs0 ++ lib.optionals hasCC [ cc ];
defaultBuildInputs = extraBuildInputs;
stdenv = (stdenv-overridable argsStdenv);
in
# The stdenv that we are producing.
derivation {
${if allowedRequisites != null then "allowedRequisites" else null} =
allowedRequisites ++ defaultNativeBuildInputs ++ defaultBuildInputs;
${if config.contentAddressedByDefault then "__contentAddressed" else null} = true;
${if config.contentAddressedByDefault then "outputHashAlgo" else null} = "sha256";
${if config.contentAddressedByDefault then "outputHashMode" else null} = "recursive";
inherit name pname version;
inherit disallowedRequisites;
# Nix itself uses the `system` field of a derivation to decide where to
# build it. This is a bit confusing for cross compilation.
inherit (buildPlatform) system;
builder = shell;
args = [
"-e"
./builder.sh
];
setup = setupScript;
# We pretty much never need rpaths on Darwin, since all library path references
# are absolute unless we go out of our way to make them relative (like with CF)
# TODO: This really wants to be in stdenv/darwin but we don't have hostPlatform
# there (yet?) so it goes here until then.
preHook =
preHook
+ lib.optionalString buildPlatform.isDarwin ''
export NIX_DONT_SET_RPATH_FOR_BUILD=1
''
+ lib.optionalString (hostPlatform.isDarwin || (!hostPlatform.isElf && !hostPlatform.isMacho)) ''
export NIX_DONT_SET_RPATH=1
export NIX_NO_SELF_RPATH=1
''
+ lib.optionalString (hostPlatform.isDarwin && hostPlatform.isMacOS) ''
export MACOSX_DEPLOYMENT_TARGET=${hostPlatform.darwinMinVersion}
''
# TODO this should be uncommented, but it causes stupid mass rebuilds due to
# `pkgsCross.*.buildPackages` not being the same, resulting in cross-compiling
# for a target rebuilding all of `nativeBuildInputs` for that target.
#
# I think the best solution would just be to fixup linux RPATHs so we don't
# need to set `-rpath` anywhere.
# + lib.optionalString targetPlatform.isDarwin ''
# export NIX_DONT_SET_RPATH_FOR_TARGET=1
# ''
;
inherit
initialPath
shell
defaultNativeBuildInputs
defaultBuildInputs
;
${if buildPlatform.isDarwin then "__sandboxProfile" else null} = stdenvSandboxProfile;
${if buildPlatform.isDarwin then "__impureHostDeps" else null} = __stdenvImpureHostDeps;
}
// {
meta =
let
pos = builtins.unsafeGetAttrPos "name" argsStdenv;
in
{
description = "The default build environment for Unix packages in Nixpkgs";
platforms = lib.platforms.all;
position = "${pos.file}:${toString pos.line}";
teams = [ lib.teams.stdenv ];
license = lib.licenses.mit;
identifiers.cpeParts = {
part = "a";
vendor = "nixos";
product = argsStdenv.name;
inherit version;
};
};
inherit buildPlatform hostPlatform targetPlatform;
inherit
extraNativeBuildInputs
extraBuildInputs
__extraImpureHostDeps
extraSandboxProfile
;
}
// lib.optionalAttrs config.allowAliases (
lib.mapAttrs
(
name: value: lib.warn "stdenv.${name} is deprecated, use stdenv.hostPlatform.${name} instead" value
)
{
# Added 2026-05-09
inherit (hostPlatform)
isDarwin
isLinux
isSunOS
isCygwin
isBSD
isFreeBSD
isOpenBSD
isi686
isx86_32
isx86_64
is32bit
is64bit
isAarch32
isAarch64
isMips
isBigEndian
;
}
)
// {
# Override `system` so that packages can get the system of the host
# platform through `stdenv.system`. `system` is originally set to the
# build platform within the derivation above so that Nix directs the build
# to correct type of machine.
inherit (hostPlatform) system;
mkDerivation = mkDerivationFromStdenv stdenv;
inherit fetchurlBoot;
inherit overrides;
inherit cc hasCC;
# Convenience for doing some very basic shell syntax checking by parsing a script
# without running any commands. Because this will also skip `shopt -s extglob`
# commands and extglob affects the Bash parser, we enable extglob always.
shellDryRun = "${stdenv.shell} -n -O extglob";
tests = {
inputDerivationRequiredSystemFeatures = import ../tests/inputDerivationRequiredSystemFeatures.nix {
inherit lib stdenv;
};
succeedOnFailure = import ../tests/succeedOnFailure.nix { inherit stdenv; };
};
passthru.tests = lib.warn "Use `stdenv.tests` instead. `passthru` is a `mkDerivation` detail." stdenv.tests;
}
# Propagate any extra attributes. For instance, we use this to
# "lift" packages like curl from the final stdenv for Linux to
# all-packages.nix for that platform (meaning that it has a line
# like curl = if stdenv ? curl then stdenv.curl else ...).
// extraAttrs
);
in
stdenv-overridable
|