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