lol
1# This file constructs the standard build environment for the
2# Linux/i686 platform. It's completely pure; that is, it relies on no
3# external (non-Nix) tools, such as /usr/bin/gcc, and it contains a C
4# compiler and linker that do not search in default locations,
5# ensuring purity of components produced by it.
6{ lib
7, localSystem, crossSystem, config, overlays
8
9, bootstrapFiles ?
10 let table = {
11 "glibc" = {
12 "i686-linux" = import ./bootstrap-files/i686.nix;
13 "x86_64-linux" = import ./bootstrap-files/x86_64.nix;
14 "armv5tel-linux" = import ./bootstrap-files/armv5tel.nix;
15 "armv6l-linux" = import ./bootstrap-files/armv6l.nix;
16 "armv7l-linux" = import ./bootstrap-files/armv7l.nix;
17 "aarch64-linux" = import ./bootstrap-files/aarch64.nix;
18 "mipsel-linux" = import ./bootstrap-files/loongson2f.nix;
19 };
20 "musl" = {
21 "aarch64-linux" = import ./bootstrap-files/aarch64-musl.nix;
22 "armv6l-linux" = import ./bootstrap-files/armv6l-musl.nix;
23 "x86_64-linux" = import ./bootstrap-files/x86_64-musl.nix;
24 };
25 };
26 archLookupTable = table.${localSystem.libc}
27 or (abort "unsupported libc for the pure Linux stdenv");
28 files = archLookupTable.${localSystem.system}
29 or (abort "unsupported platform for the pure Linux stdenv");
30 in files
31}:
32
33assert crossSystem == null;
34
35let
36 inherit (localSystem) system platform;
37
38 commonPreHook =
39 ''
40 export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}"
41 export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}"
42 ${if system == "x86_64-linux" then "NIX_LIB64_IN_SELF_RPATH=1" else ""}
43 ${if system == "mipsel-linux" then "NIX_LIB32_IN_SELF_RPATH=1" else ""}
44 '';
45
46
47 # The bootstrap process proceeds in several steps.
48
49
50 # Create a standard environment by downloading pre-built binaries of
51 # coreutils, GCC, etc.
52
53
54 # Download and unpack the bootstrap tools (coreutils, GCC, Glibc, ...).
55 bootstrapTools = import (if localSystem.libc == "musl" then ./bootstrap-tools-musl else ./bootstrap-tools) { inherit system bootstrapFiles; };
56
57 getLibc = stage: stage.${localSystem.libc};
58
59
60 # This function builds the various standard environments used during
61 # the bootstrap. In all stages, we build an stdenv and the package
62 # set that can be built with that stdenv.
63 stageFun = prevStage:
64 { name, overrides ? (self: super: {}), extraNativeBuildInputs ? [] }:
65
66 let
67
68 thisStdenv = import ../generic {
69 name = "stdenv-linux-boot";
70 buildPlatform = localSystem;
71 hostPlatform = localSystem;
72 targetPlatform = localSystem;
73 inherit config extraNativeBuildInputs;
74 preHook =
75 ''
76 # Don't patch #!/interpreter because it leads to retained
77 # dependencies on the bootstrapTools in the final stdenv.
78 dontPatchShebangs=1
79 ${commonPreHook}
80 '';
81 shell = "${bootstrapTools}/bin/bash";
82 initialPath = [bootstrapTools];
83
84 fetchurlBoot = import ../../build-support/fetchurl/boot.nix {
85 inherit system;
86 };
87
88 cc = if isNull prevStage.gcc-unwrapped
89 then null
90 else lib.makeOverridable (import ../../build-support/cc-wrapper) {
91 nativeTools = false;
92 nativeLibc = false;
93 buildPackages = lib.optionalAttrs (prevStage ? stdenv) {
94 inherit (prevStage) stdenv;
95 };
96 cc = prevStage.gcc-unwrapped;
97 bintools = prevStage.binutils;
98 isGNU = true;
99 libc = getLibc prevStage;
100 inherit (prevStage) coreutils gnugrep;
101 name = name;
102 stdenvNoCC = prevStage.ccWrapperStdenv;
103 };
104
105 extraAttrs = {
106 # Having the proper 'platform' in all the stdenvs allows getting proper
107 # linuxHeaders for example.
108 inherit platform;
109
110 # stdenv.glibc is used by GCC build to figure out the system-level
111 # /usr/include directory.
112 # TODO: Remove this!
113 inherit (prevStage) glibc;
114 };
115 overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; };
116 };
117
118 in {
119 inherit config overlays;
120 stdenv = thisStdenv;
121 };
122
123in
124
125[
126
127 ({}: {
128 __raw = true;
129
130 gcc-unwrapped = null;
131 glibc = assert false; null;
132 musl = assert false; null;
133 binutils = null;
134 coreutils = null;
135 gnugrep = null;
136 })
137
138 # Build a dummy stdenv with no GCC or working fetchurl. This is
139 # because we need a stdenv to build the GCC wrapper and fetchurl.
140 (prevStage: stageFun prevStage {
141 name = null;
142
143 overrides = self: super: {
144 # We thread stage0's stdenv through under this name so downstream stages
145 # can use it for wrapping gcc too. This way, downstream stages don't need
146 # to refer to this stage directly, which violates the principle that each
147 # stage should only access the stage that came before it.
148 ccWrapperStdenv = self.stdenv;
149 # The Glibc include directory cannot have the same prefix as the
150 # GCC include directory, since GCC gets confused otherwise (it
151 # will search the Glibc headers before the GCC headers). So
152 # create a dummy Glibc here, which will be used in the stdenv of
153 # stage1.
154 ${localSystem.libc} = self.stdenv.mkDerivation {
155 name = "bootstrap-${localSystem.libc}";
156 buildCommand = ''
157 mkdir -p $out
158 ln -s ${bootstrapTools}/lib $out/lib
159 '' + lib.optionalString (localSystem.libc == "glibc") ''
160 ln -s ${bootstrapTools}/include-glibc $out/include
161 '' + lib.optionalString (localSystem.libc == "musl") ''
162 ln -s ${bootstrapTools}/include-libc $out/include
163 '';
164 };
165 gcc-unwrapped = bootstrapTools;
166 binutils = import ../../build-support/bintools-wrapper {
167 nativeTools = false;
168 nativeLibc = false;
169 buildPackages = { };
170 libc = getLibc self;
171 inherit (self) stdenvNoCC coreutils gnugrep;
172 bintools = bootstrapTools;
173 name = "bootstrap-binutils-wrapper";
174 };
175 coreutils = bootstrapTools;
176 gnugrep = bootstrapTools;
177 };
178 })
179
180
181 # Create the first "real" standard environment. This one consists
182 # of bootstrap tools only, and a minimal Glibc to keep the GCC
183 # configure script happy.
184 #
185 # For clarity, we only use the previous stage when specifying these
186 # stages. So stageN should only ever have references for stage{N-1}.
187 #
188 # If we ever need to use a package from more than one stage back, we
189 # simply re-export those packages in the middle stage(s) using the
190 # overrides attribute and the inherit syntax.
191 (prevStage: stageFun prevStage {
192 name = "bootstrap-gcc-wrapper";
193
194 # Rebuild binutils to use from stage2 onwards.
195 overrides = self: super: {
196 binutils = super.binutils_nogold;
197 inherit (prevStage)
198 ccWrapperStdenv
199 gcc-unwrapped coreutils gnugrep;
200
201 ${localSystem.libc} = getLibc prevStage;
202
203 # A threaded perl build needs glibc/libpthread_nonshared.a,
204 # which is not included in bootstrapTools, so disable threading.
205 # This is not an issue for the final stdenv, because this perl
206 # won't be included in the final stdenv and won't be exported to
207 # top-level pkgs as an override either.
208 perl = super.perl.override { enableThreading = false; };
209 };
210 })
211
212
213 # 2nd stdenv that contains our own rebuilt binutils and is used for
214 # compiling our own Glibc.
215 (prevStage: stageFun prevStage {
216 name = "bootstrap-gcc-wrapper";
217
218 overrides = self: super: {
219 inherit (prevStage)
220 ccWrapperStdenv
221 gcc-unwrapped coreutils gnugrep
222 perl paxctl gnum4 bison;
223 # This also contains the full, dynamically linked, final Glibc.
224 binutils = prevStage.binutils.override {
225 # Rewrap the binutils with the new glibc, so both the next
226 # stage's wrappers use it.
227 libc = getLibc self;
228 };
229 };
230 })
231
232
233 # Construct a third stdenv identical to the 2nd, except that this
234 # one uses the rebuilt Glibc from stage2. It still uses the recent
235 # binutils and rest of the bootstrap tools, including GCC.
236 (prevStage: stageFun prevStage {
237 name = "bootstrap-gcc-wrapper";
238
239 overrides = self: super: rec {
240 inherit (prevStage)
241 ccWrapperStdenv
242 binutils coreutils gnugrep
243 perl patchelf linuxHeaders gnum4 bison;
244 ${localSystem.libc} = getLibc prevStage;
245 # Link GCC statically against GMP etc. This makes sense because
246 # these builds of the libraries are only used by GCC, so it
247 # reduces the size of the stdenv closure.
248 gmp = super.gmp.override { stdenv = self.makeStaticLibraries self.stdenv; };
249 mpfr = super.mpfr.override { stdenv = self.makeStaticLibraries self.stdenv; };
250 libmpc = super.libmpc.override { stdenv = self.makeStaticLibraries self.stdenv; };
251 isl_0_17 = super.isl_0_17.override { stdenv = self.makeStaticLibraries self.stdenv; };
252 gcc-unwrapped = super.gcc-unwrapped.override {
253 isl = isl_0_17;
254 };
255 };
256 extraNativeBuildInputs = [ prevStage.patchelf prevStage.paxctl ] ++
257 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
258 lib.optional localSystem.isAarch64 prevStage.updateAutotoolsGnuConfigScriptsHook;
259 })
260
261
262 # Construct a fourth stdenv that uses the new GCC. But coreutils is
263 # still from the bootstrap tools.
264 (prevStage: stageFun prevStage {
265 name = "";
266
267 overrides = self: super: {
268 # Zlib has to be inherited and not rebuilt in this stage,
269 # because gcc (since JAR support) already depends on zlib, and
270 # then if we already have a zlib we want to use that for the
271 # other purposes (binutils and top-level pkgs) too.
272 inherit (prevStage) gettext gnum4 bison gmp perl zlib linuxHeaders;
273 ${localSystem.libc} = getLibc prevStage;
274 binutils = super.binutils.override {
275 # Don't use stdenv's shell but our own
276 shell = self.bash + "/bin/bash";
277 # Build expand-response-params with last stage like below
278 buildPackages = {
279 inherit (prevStage) stdenv;
280 };
281 };
282
283 gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) {
284 nativeTools = false;
285 nativeLibc = false;
286 isGNU = true;
287 buildPackages = {
288 inherit (prevStage) stdenv;
289 };
290 cc = prevStage.gcc-unwrapped;
291 bintools = self.binutils;
292 libc = getLibc self;
293 inherit (self) stdenvNoCC coreutils gnugrep;
294 name = "";
295 shell = self.bash + "/bin/bash";
296 };
297 };
298 extraNativeBuildInputs = [ prevStage.patchelf prevStage.xz ] ++
299 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
300 lib.optional localSystem.isAarch64 prevStage.updateAutotoolsGnuConfigScriptsHook;
301 })
302
303 # Construct the final stdenv. It uses the Glibc and GCC, and adds
304 # in a new binutils that doesn't depend on bootstrap-tools, as well
305 # as dynamically linked versions of all other tools.
306 #
307 # When updating stdenvLinux, make sure that the result has no
308 # dependency (`nix-store -qR') on bootstrapTools or the first
309 # binutils built.
310 (prevStage: {
311 inherit config overlays;
312 stdenv = import ../generic rec {
313 buildPlatform = localSystem;
314 hostPlatform = localSystem;
315 targetPlatform = localSystem;
316 inherit config;
317
318 preHook = ''
319 # Make "strip" produce deterministic output, by setting
320 # timestamps etc. to a fixed value.
321 commonStripFlags="--enable-deterministic-archives"
322 ${commonPreHook}
323 '';
324
325 initialPath =
326 ((import ../common-path.nix) {pkgs = prevStage;});
327
328 extraNativeBuildInputs = [ prevStage.patchelf prevStage.paxctl ] ++
329 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
330 lib.optional localSystem.isAarch64 prevStage.updateAutotoolsGnuConfigScriptsHook;
331
332 cc = prevStage.gcc;
333
334 shell = cc.shell;
335
336 inherit (prevStage.stdenv) fetchurlBoot;
337
338 extraAttrs = {
339 # TODO: remove this!
340 inherit (prevStage) glibc;
341
342 inherit platform bootstrapTools;
343 shellPackage = prevStage.bash;
344 };
345
346 # Mainly avoid reference to bootstrap tools
347 allowedRequisites = with prevStage; with lib;
348 # Simple executable tools
349 concatMap (p: [ (getBin p) (getLib p) ])
350 [ gzip bzip2 xz bash binutils.bintools coreutils diffutils findutils
351 gawk gnumake gnused gnutar gnugrep gnupatch patchelf ed paxctl
352 ]
353 # Library dependencies
354 ++ map getLib (
355 [ attr acl zlib pcre ]
356 ++ lib.optional (gawk.libsigsegv != null) gawk.libsigsegv
357 )
358 # More complicated cases
359 ++ (map (x: getOutput x (getLibc prevStage)) [ "out" "dev" "bin" ] )
360 ++ [ /*propagated from .dev*/ linuxHeaders
361 binutils gcc gcc.cc gcc.cc.lib gcc.expand-response-params
362 ]
363 ++ lib.optional (localSystem.libc == "musl") libiconv
364 ++ lib.optionals localSystem.isAarch64
365 [ prevStage.updateAutotoolsGnuConfigScriptsHook prevStage.gnu-config ];
366
367 overrides = self: super: {
368 inherit (prevStage)
369 gzip bzip2 xz bash coreutils diffutils findutils gawk
370 gnumake gnused gnutar gnugrep gnupatch patchelf
371 attr acl paxctl zlib pcre;
372 ${localSystem.libc} = getLibc prevStage;
373 } // lib.optionalAttrs (super.targetPlatform == localSystem) {
374 # Need to get rid of these when cross-compiling.
375 inherit (prevStage) binutils binutils-raw;
376 gcc = cc;
377 };
378 };
379 })
380
381]