lol
at 18.03-beta 381 lines 14 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{ 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]