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
7# The function defaults are for easy testing.
8{ system ? builtins.currentSystem
9, allPackages ? import ../../top-level/all-packages.nix
10, platform ? null, config ? {}, lib ? (import ../../../lib)
11, customBootstrapFiles ? null }:
12
13rec {
14
15 bootstrapFiles =
16 if customBootstrapFiles != null then customBootstrapFiles
17 else if system == "i686-linux" then import ./bootstrap/i686.nix
18 else if system == "x86_64-linux" then import ./bootstrap/x86_64.nix
19 else if system == "armv5tel-linux" then import ./bootstrap/armv5tel.nix
20 else if system == "armv6l-linux" then import ./bootstrap/armv6l.nix
21 else if system == "armv7l-linux" then import ./bootstrap/armv7l.nix
22 else if system == "mips64el-linux" then import ./bootstrap/loongson2f.nix
23 else abort "unsupported platform for the pure Linux stdenv";
24
25
26 commonPreHook =
27 ''
28 export NIX_ENFORCE_PURITY=1
29 ${if system == "x86_64-linux" then "NIX_LIB64_IN_SELF_RPATH=1" else ""}
30 ${if system == "mips64el-linux" then "NIX_LIB32_IN_SELF_RPATH=1" else ""}
31 '';
32
33
34 # The bootstrap process proceeds in several steps.
35
36
37 # Create a standard environment by downloading pre-built binaries of
38 # coreutils, GCC, etc.
39
40
41 # Download and unpack the bootstrap tools (coreutils, GCC, Glibc, ...).
42 bootstrapTools = derivation {
43 name = "bootstrap-tools";
44
45 builder = bootstrapFiles.busybox;
46
47 args = if system == "armv5tel-linux" then
48 [ "ash" "-e" ./scripts/unpack-bootstrap-tools-arm.sh ]
49 else
50 [ "ash" "-e" ./scripts/unpack-bootstrap-tools.sh ];
51
52 tarball = bootstrapFiles.bootstrapTools;
53
54 inherit system;
55
56 # Needed by the GCC wrapper.
57 langC = true;
58 langCC = true;
59 isGNU = true;
60 };
61
62
63 # This function builds the various standard environments used during
64 # the bootstrap. In all stages, we build an stdenv and the package
65 # set that can be built with that stdenv.
66 stageFun =
67 {gccPlain, glibc, binutils, coreutils, name, overrides ? (pkgs: {}), extraBuildInputs ? []}:
68
69 let
70
71 thisStdenv = import ../generic {
72 inherit system config extraBuildInputs;
73 name = "stdenv-linux-boot";
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/sh";
82 initialPath = [bootstrapTools];
83 fetchurlBoot = import ../../build-support/fetchurl {
84 stdenv = stage0.stdenv;
85 curl = bootstrapTools;
86 };
87
88 cc = if isNull gccPlain
89 then null
90 else lib.makeOverridable (import ../../build-support/cc-wrapper) {
91 nativeTools = false;
92 nativeLibc = false;
93 cc = gccPlain;
94 isGNU = true;
95 libc = glibc;
96 inherit binutils coreutils;
97 name = name;
98 stdenv = stage0.stdenv;
99 };
100
101 extraAttrs = {
102 # Having the proper 'platform' in all the stdenvs allows getting proper
103 # linuxHeaders for example.
104 inherit platform;
105
106 # stdenv.glibc is used by GCC build to figure out the system-level
107 # /usr/include directory.
108 inherit glibc;
109 };
110 overrides = pkgs: (overrides pkgs) // { fetchurl = thisStdenv.fetchurlBoot; };
111 };
112
113 thisPkgs = allPackages {
114 inherit system platform;
115 bootStdenv = thisStdenv;
116 };
117
118 in { stdenv = thisStdenv; pkgs = thisPkgs; };
119
120
121 # Build a dummy stdenv with no GCC or working fetchurl. This is
122 # because we need a stdenv to build the GCC wrapper and fetchurl.
123 stage0 = stageFun {
124 gccPlain = null;
125 glibc = null;
126 binutils = null;
127 coreutils = null;
128 name = null;
129
130 overrides = pkgs: {
131 # The Glibc include directory cannot have the same prefix as the
132 # GCC include directory, since GCC gets confused otherwise (it
133 # will search the Glibc headers before the GCC headers). So
134 # create a dummy Glibc here, which will be used in the stdenv of
135 # stage1.
136 glibc = stage0.stdenv.mkDerivation {
137 name = "bootstrap-glibc";
138 buildCommand = ''
139 mkdir -p $out
140 ln -s ${bootstrapTools}/lib $out/lib
141 ln -s ${bootstrapTools}/include-glibc $out/include
142 '';
143 };
144 };
145 };
146
147
148 # Create the first "real" standard environment. This one consists
149 # of bootstrap tools only, and a minimal Glibc to keep the GCC
150 # configure script happy.
151 #
152 # For clarity, we only use the previous stage when specifying these
153 # stages. So stageN should only ever have references for stage{N-1}.
154 #
155 # If we ever need to use a package from more than one stage back, we
156 # simply re-export those packages in the middle stage(s) using the
157 # overrides attribute and the inherit syntax.
158 stage1 = stageFun {
159 gccPlain = bootstrapTools;
160 inherit (stage0.pkgs) glibc;
161 binutils = bootstrapTools;
162 coreutils = bootstrapTools;
163 name = "bootstrap-gcc-wrapper";
164
165 # Rebuild binutils to use from stage2 onwards.
166 overrides = pkgs: {
167 binutils = pkgs.binutils.override { gold = false; };
168 inherit (stage0.pkgs) glibc;
169
170 # A threaded perl build needs glibc/libpthread_nonshared.a,
171 # which is not included in bootstrapTools, so disable threading.
172 # This is not an issue for the final stdenv, because this perl
173 # won't be included in the final stdenv and won't be exported to
174 # top-level pkgs as an override either.
175 perl = pkgs.perl.override { enableThreading = false; };
176 };
177 };
178
179
180 # 2nd stdenv that contains our own rebuilt binutils and is used for
181 # compiling our own Glibc.
182 stage2 = stageFun {
183 gccPlain = bootstrapTools;
184 inherit (stage1.pkgs) glibc;
185 binutils = stage1.pkgs.binutils;
186 coreutils = bootstrapTools;
187 name = "bootstrap-gcc-wrapper";
188
189 overrides = pkgs: {
190 inherit (stage1.pkgs) perl binutils paxctl;
191 # This also contains the full, dynamically linked, final Glibc.
192 };
193 };
194
195
196 # Construct a third stdenv identical to the 2nd, except that this
197 # one uses the rebuilt Glibc from stage2. It still uses the recent
198 # binutils and rest of the bootstrap tools, including GCC.
199 stage3 = stageFun {
200 gccPlain = bootstrapTools;
201 inherit (stage2.pkgs) glibc binutils;
202 coreutils = bootstrapTools;
203 name = "bootstrap-gcc-wrapper";
204
205 overrides = pkgs: rec {
206 inherit (stage2.pkgs) binutils glibc perl patchelf linuxHeaders;
207 # Link GCC statically against GMP etc. This makes sense because
208 # these builds of the libraries are only used by GCC, so it
209 # reduces the size of the stdenv closure.
210 gmp = pkgs.gmp.override { stdenv = pkgs.makeStaticLibraries pkgs.stdenv; };
211 mpfr = pkgs.mpfr.override { stdenv = pkgs.makeStaticLibraries pkgs.stdenv; };
212 libmpc = pkgs.libmpc.override { stdenv = pkgs.makeStaticLibraries pkgs.stdenv; };
213 isl_0_11 = pkgs.isl_0_11.override { stdenv = pkgs.makeStaticLibraries pkgs.stdenv; };
214 cloog_0_18_0 = pkgs.cloog_0_18_0.override {
215 stdenv = pkgs.makeStaticLibraries pkgs.stdenv;
216 isl = isl_0_11;
217 };
218 gccPlain = pkgs.gcc.cc.override {
219 isl = isl_0_11;
220 cloog = cloog_0_18_0;
221 };
222 };
223 extraBuildInputs = [ stage2.pkgs.patchelf stage2.pkgs.paxctl ];
224 };
225
226
227 # Construct a fourth stdenv that uses the new GCC. But coreutils is
228 # still from the bootstrap tools.
229 stage4 = stageFun {
230 inherit (stage3.pkgs) gccPlain glibc binutils;
231 coreutils = bootstrapTools;
232 name = "";
233
234 overrides = pkgs: {
235 # Zlib has to be inherited and not rebuilt in this stage,
236 # because gcc (since JAR support) already depends on zlib, and
237 # then if we already have a zlib we want to use that for the
238 # other purposes (binutils and top-level pkgs) too.
239 inherit (stage3.pkgs) gettext gnum4 gmp perl glibc zlib linuxHeaders;
240
241 gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) {
242 nativeTools = false;
243 nativeLibc = false;
244 isGNU = true;
245 cc = stage4.stdenv.cc.cc;
246 libc = stage4.pkgs.glibc;
247 inherit (stage4.pkgs) binutils coreutils;
248 name = "";
249 stdenv = stage4.stdenv;
250 shell = stage4.pkgs.bash + "/bin/bash";
251 };
252 };
253 extraBuildInputs = [ stage3.pkgs.patchelf stage3.pkgs.xz ];
254 };
255
256
257 # Construct the final stdenv. It uses the Glibc and GCC, and adds
258 # in a new binutils that doesn't depend on bootstrap-tools, as well
259 # as dynamically linked versions of all other tools.
260 #
261 # When updating stdenvLinux, make sure that the result has no
262 # dependency (`nix-store -qR') on bootstrapTools or the first
263 # binutils built.
264 stdenvLinux = import ../generic rec {
265 inherit system config;
266
267 preHook =
268 ''
269 # Make "strip" produce deterministic output, by setting
270 # timestamps etc. to a fixed value.
271 commonStripFlags="--enable-deterministic-archives"
272 ${commonPreHook}
273 '';
274
275 initialPath =
276 ((import ../common-path.nix) {pkgs = stage4.pkgs;});
277
278 extraBuildInputs = [ stage4.pkgs.patchelf stage4.pkgs.paxctl ];
279
280 cc = stage4.pkgs.gcc;
281
282 shell = cc.shell;
283
284 inherit (stage4.stdenv) fetchurlBoot;
285
286 extraAttrs = {
287 inherit (stage4.pkgs) glibc;
288 inherit platform bootstrapTools;
289 shellPackage = stage4.pkgs.bash;
290 };
291
292 allowedRequisites = with stage4.pkgs;
293 [ gzip bzip2 xz bash binutils coreutils diffutils findutils gawk
294 glibc gnumake gnused gnutar gnugrep gnupatch patchelf attr acl
295 paxctl zlib pcre linuxHeaders ed gcc gcc.cc libsigsegv
296 ];
297
298 overrides = pkgs: {
299 gcc = cc;
300
301 inherit (stage4.pkgs)
302 gzip bzip2 xz bash binutils coreutils diffutils findutils gawk
303 glibc gnumake gnused gnutar gnugrep gnupatch patchelf
304 attr acl paxctl zlib pcre;
305 };
306 };
307
308
309 testBootstrapTools = let
310 defaultPkgs = allPackages { inherit system platform; };
311 in derivation {
312 name = "test-bootstrap-tools";
313 inherit system;
314 builder = bootstrapFiles.busybox;
315 args = [ "ash" "-e" "-c" "eval \"$buildCommand\"" ];
316
317 buildCommand = ''
318 export PATH=${bootstrapTools}/bin
319
320 ls -l
321 mkdir $out
322 mkdir $out/bin
323 sed --version
324 find --version
325 diff --version
326 patch --version
327 make --version
328 awk --version
329 grep --version
330 gcc --version
331 curl --version
332
333 ldlinux=$(echo ${bootstrapTools}/lib/ld-linux*.so.?)
334 export CPP="cpp -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools}"
335 export CC="gcc -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools} -Wl,-dynamic-linker,$ldlinux -Wl,-rpath,${bootstrapTools}/lib"
336 export CXX="g++ -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools} -Wl,-dynamic-linker,$ldlinux -Wl,-rpath,${bootstrapTools}/lib"
337
338 echo '#include <stdio.h>' >> foo.c
339 echo '#include <limits.h>' >> foo.c
340 echo 'int main() { printf("Hello World\\n"); return 0; }' >> foo.c
341 $CC -o $out/bin/foo foo.c
342 $out/bin/foo
343
344 echo '#include <iostream>' >> bar.cc
345 echo 'int main() { std::cout << "Hello World\\n"; }' >> bar.cc
346 $CXX -v -o $out/bin/bar bar.cc
347 $out/bin/bar
348
349 tar xvf ${defaultPkgs.hello.src}
350 cd hello-*
351 ./configure --prefix=$out
352 make
353 make install
354 '';
355 };
356}