at 18.09-beta 377 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 "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]