at v206 356 lines 12 kB view raw
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}