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