lol
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #209870 from amjoseph-nixpkgs/pr/stdenv/external-gcc-bootstrap

authored by

Bernardo Meurer and committed by
GitHub
f1f6ca8b 89ab0e40

+429 -114
+3 -1
nixos/release-small.nix
··· 85 85 stdenv 86 86 subversion 87 87 tarball 88 - vim; 88 + vim 89 + tests-stdenv-gcc-stageCompare; 89 90 }; 90 91 91 92 tested = let ··· 135 136 "nixos.tests.proxy" 136 137 "nixos.tests.simple" 137 138 "nixpkgs.jdk" 139 + "nixpkgs.tests-stdenv-gcc-stageCompare" 138 140 ]) 139 141 ]; 140 142 };
+12 -6
pkgs/applications/editors/emacs/generic.nix
··· 62 62 assert withTreeSitter -> tree-sitter != null; 63 63 64 64 65 + let 66 + libGccJitLibraryPaths = [ 67 + "${lib.getLib libgccjit}/lib/gcc" 68 + "${lib.getLib stdenv.cc.libc}/lib" 69 + ] ++ lib.optionals (stdenv.cc?cc.libgcc) [ 70 + "${lib.getLib stdenv.cc.cc.libgcc}/lib" 71 + ]; 72 + in 65 73 (if withMacport then llvmPackages_6.stdenv else stdenv).mkDerivation (finalAttrs: (lib.optionalAttrs nativeComp { 66 74 NATIVE_FULL_AOT = "1"; 67 - LIBRARY_PATH = "${lib.getLib stdenv.cc.libc}/lib"; 75 + LIBRARY_PATH = lib.concatStringsSep ":" libGccJitLibraryPaths; 68 76 } // { 69 77 pname = pname + lib.optionalString ( !withX && !withNS && !withMacport && !withGTK2 && !withGTK3 ) "-nox"; 70 78 inherit version; ··· 75 83 then ./native-comp-driver-options-28.patch 76 84 else ./native-comp-driver-options.patch; 77 85 backendPath = (lib.concatStringsSep " " 78 - (builtins.map (x: ''"-B${x}"'') [ 86 + (builtins.map (x: ''"-B${x}"'') ([ 79 87 # Paths necessary so the JIT compiler finds its libraries: 80 88 "${lib.getLib libgccjit}/lib" 81 - "${lib.getLib libgccjit}/lib/gcc" 82 - "${lib.getLib stdenv.cc.libc}/lib" 83 - 89 + ] ++ libGccJitLibraryPaths ++ [ 84 90 # Executable paths necessary for compilation (ld, as): 85 91 "${lib.getBin stdenv.cc.cc}/bin" 86 92 "${lib.getBin stdenv.cc.bintools}/bin" 87 93 "${lib.getBin stdenv.cc.bintools.bintools}/bin" 88 - ])); 94 + ]))); 89 95 }) 90 96 ]; 91 97
+39 -3
pkgs/build-support/cc-wrapper/default.nix
··· 17 17 , isGNU ? false, isClang ? cc.isClang or false, gnugrep ? null 18 18 , buildPackages ? {} 19 19 , libcxx ? null 20 + 21 + # Whether or not to add `-B` and `-L` to `nix-support/cc-{c,ld}flags` 22 + , useCcForLibs ? 23 + 24 + # Always add these flags for Clang, because in order to compile (most 25 + # software) it needs libraries that are shipped and compiled with gcc. 26 + if isClang then true 27 + 28 + # Never add these flags for a build!=host cross-compiler or a host!=target 29 + # ("cross-built-native") compiler; currently nixpkgs has a special build 30 + # path for these (`crossStageStatic`). Hopefully at some point that build 31 + # path will be merged with this one and this conditional will be removed. 32 + else if (with stdenvNoCC; buildPlatform != hostPlatform || hostPlatform != targetPlatform) then false 33 + 34 + # Never add these flags when wrapping the bootstrapFiles' compiler; it has a 35 + # /usr/-like layout with everything smashed into a single outpath, so it has 36 + # no trouble finding its own libraries. 37 + else if (cc.passthru.isFromBootstrapFiles or false) then false 38 + 39 + # Add these flags when wrapping `xgcc` (the first compiler that nixpkgs builds) 40 + else if (cc.passthru.isXgcc or false) then true 41 + 42 + # Add these flags when wrapping `stdenv.cc` 43 + else if (cc.stdenv.cc.cc.passthru.isXgcc or false) then true 44 + 45 + # Do not add these flags in any other situation. This is `false` mainly to 46 + # prevent these flags from being added when wrapping *old* versions of gcc 47 + # (e.g. `gcc6Stdenv`), since they will cause the old gcc to get `-B` and 48 + # `-L` flags pointing at the new gcc's libstdc++ headers. Example failure: 49 + # https://hydra.nixos.org/build/213125495 50 + else false 51 + 52 + # the derivation at which the `-B` and `-L` flags added by `useCcForLibs` will point 20 53 , gccForLibs ? if useCcForLibs then cc else null 21 - # same as `gccForLibs`, but generalized beyond clang 22 - , useCcForLibs ? isClang 23 54 }: 24 55 25 56 with lib; ··· 321 352 && targetPlatform.isLinux 322 353 && !(stdenv.targetPlatform.useAndroidPrebuilt or false) 323 354 && !(stdenv.targetPlatform.useLLVM or false) 324 - && gccForLibs != null) '' 355 + && gccForLibs != null) ('' 325 356 echo "--gcc-toolchain=${gccForLibs}" >> $out/nix-support/cc-cflags 326 357 327 358 # Pull in 'cc.out' target to get 'libstdc++fs.a'. It should be in ··· 329 360 # TODO(trofi): remove once gcc is fixed to move libraries to .lib output. 330 361 echo "-L${gccForLibs}/${optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}"}/lib" >> $out/nix-support/cc-ldflags 331 362 '' 363 + # this ensures that when clang passes -lgcc_s to lld (as it does 364 + # when building e.g. firefox), lld is able to find libgcc_s.so 365 + + lib.optionalString (gccForLibs?libgcc) '' 366 + echo "-L${gccForLibs.libgcc}/lib" >> $out/nix-support/cc-ldflags 367 + '') 332 368 333 369 ## 334 370 ## General libc support
+4 -2
pkgs/build-support/emacs/wrapper.nix
··· 67 67 # Store all paths we want to add to emacs here, so that we only need to add 68 68 # one path to the load lists 69 69 deps = runCommand "emacs-packages-deps" 70 - { 70 + ({ 71 71 inherit explicitRequires lndir emacs; 72 72 nativeBuildInputs = lib.optional nativeComp gcc; 73 - } 73 + } // lib.optionalAttrs nativeComp { 74 + inherit (emacs) LIBRARY_PATH; 75 + }) 74 76 '' 75 77 findInputsOld() { 76 78 local pkg="$1"; shift
+11 -6
pkgs/development/compilers/gcc/11/default.nix
··· 28 28 , buildPackages 29 29 , libxcrypt 30 30 , disableGdbPlugin ? !enablePlugin 31 + , nukeReferences 32 + , callPackage 31 33 }: 32 34 33 35 # Make sure we get GNU sed. ··· 49 51 50 52 let majorVersion = "11"; 51 53 version = "${majorVersion}.3.0"; 52 - disableBootstrap = !(with stdenv; targetPlatform == hostPlatform && hostPlatform == buildPlatform); 54 + disableBootstrap = true; 53 55 54 56 inherit (stdenv) buildPlatform hostPlatform targetPlatform; 55 57 ··· 159 161 160 162 in 161 163 162 - stdenv.mkDerivation ({ 164 + lib.pipe (stdenv.mkDerivation ({ 163 165 pname = "${crossNameAddon}${name}"; 164 166 inherit version; 165 167 ··· 250 252 targetConfig = if targetPlatform != hostPlatform then targetPlatform.config else null; 251 253 252 254 buildFlags = 253 - let target = 254 - lib.optionalString (profiledCompiler) "profiled" + 255 - lib.optionalString (targetPlatform == hostPlatform && hostPlatform == buildPlatform && !disableBootstrap) "bootstrap"; 255 + let target = lib.optionalString (profiledCompiler) "profiled" 256 + + lib.optionalString (targetPlatform == hostPlatform && hostPlatform == buildPlatform && !disableBootstrap) "bootstrap"; 256 257 in lib.optional (target != "") target; 257 258 258 259 inherit (callFile ../common/strip-attributes.nix { }) ··· 310 311 } 311 312 312 313 // optionalAttrs (enableMultilib) { dontMoveLib64 = true; } 313 - ) 314 + )) 315 + [ 316 + (callPackage ../common/libgcc.nix { inherit langC langCC langJit; }) 317 + (callPackage ../common/checksum.nix { inherit langC langCC; }) 318 + ]
+11 -3
pkgs/development/compilers/gcc/12/default.nix
··· 29 29 , buildPackages 30 30 , libxcrypt 31 31 , disableGdbPlugin ? !enablePlugin 32 + , nukeReferences 33 + , callPackage 32 34 }: 33 35 34 36 # Make sure we get GNU sed. ··· 54 56 55 57 let majorVersion = "12"; 56 58 version = "${majorVersion}.2.0"; 57 - disableBootstrap = !(with stdenv; targetPlatform == hostPlatform && hostPlatform == buildPlatform); 59 + disableBootstrap = true; 58 60 59 61 inherit (stdenv) buildPlatform hostPlatform targetPlatform; 60 62 ··· 177 179 mpfr 178 180 name 179 181 noSysDirs 182 + nukeReferences 180 183 patchelf 181 184 perl 182 185 profiledCompiler ··· 194 197 195 198 in 196 199 197 - stdenv.mkDerivation ({ 200 + lib.pipe (stdenv.mkDerivation ({ 198 201 pname = "${crossNameAddon}${name}"; 199 202 inherit version; 200 203 ··· 344 347 } 345 348 346 349 // optionalAttrs (enableMultilib) { dontMoveLib64 = true; } 347 - ) 350 + )) 351 + [ 352 + (callPackage ../common/libgcc.nix { inherit langC langCC langJit; }) 353 + (callPackage ../common/checksum.nix { inherit langC langCC; }) 354 + ] 355 +
+40
pkgs/development/compilers/gcc/common/checksum.nix
··· 1 + { lib 2 + , stdenv 3 + , nukeReferences 4 + , langC 5 + , langCC 6 + , runtimeShell 7 + }: 8 + 9 + let 10 + enableChecksum = (with stdenv; buildPlatform == hostPlatform && hostPlatform == targetPlatform) && langC && langCC; 11 + in 12 + (pkg: pkg.overrideAttrs (previousAttrs: lib.optionalAttrs enableChecksum { 13 + outputs = previousAttrs.outputs ++ lib.optionals enableChecksum [ "checksum" ]; 14 + # This is a separate phase because gcc assembles its phase scripts 15 + # in bash instead of nix (we should fix that). 16 + preFixupPhases = (previousAttrs.preFixupPhases or []) ++ [ "postInstallSaveChecksumPhase" ]; 17 + # 18 + # gcc uses an auxiliary utility `genchecksum` to md5-hash (most of) its 19 + # `.o` and `.a` files prior to linking (in case the linker is 20 + # nondeterministic). Since we want to compare across gccs built from two 21 + # separate derivations, we wrap `genchecksum` with a `nuke-references` 22 + # call. We also stash copies of the inputs to `genchecksum` in 23 + # `$checksum/inputs/` -- this is extremely helpful for debugging since 24 + # it's hard to get Nix to not delete the $NIX_BUILD_TOP of a successful 25 + # build. 26 + # 27 + postInstallSaveChecksumPhase = '' 28 + mv gcc/build/genchecksum gcc/build/.genchecksum-wrapped 29 + cat > gcc/build/genchecksum <<\EOF 30 + #!${runtimeShell} 31 + ${nukeReferences}/bin/nuke-refs $@ 32 + for INPUT in "$@"; do install -Dt $INPUT $checksum/inputs/; done 33 + exec build/.genchecksum-wrapped $@ 34 + EOF 35 + chmod +x gcc/build/genchecksum 36 + rm gcc/*-checksum.* 37 + make -C gcc cc1-checksum.o cc1plus-checksum.o 38 + install -Dt $checksum/checksums/ gcc/cc*-checksum.o 39 + ''; 40 + }))
+96
pkgs/development/compilers/gcc/common/libgcc.nix
··· 1 + { lib 2 + , stdenv 3 + , langC 4 + , langCC 5 + , langJit 6 + }: 7 + 8 + let 9 + enableLibGccOutput = (with stdenv; targetPlatform == hostPlatform) && !langJit; 10 + in 11 + (pkg: pkg.overrideAttrs (previousAttrs: lib.optionalAttrs ((!langC) || langJit || enableLibGccOutput) { 12 + outputs = previousAttrs.outputs ++ lib.optionals enableLibGccOutput [ "libgcc" ]; 13 + # This is a separate phase because gcc assembles its phase scripts 14 + # in bash instead of nix (we should fix that). 15 + preFixupPhases = (previousAttrs.preFixupPhases or []) ++ [ "preFixupLibGccPhase" ]; 16 + preFixupLibGccPhase = 17 + # delete extra/unused builds of libgcc_s in non-langC builds 18 + # (i.e. libgccjit, gnat, etc) to avoid potential confusion 19 + lib.optionalString (!langC) '' 20 + rm -f $out/lib/libgcc_s.so* 21 + '' 22 + 23 + # TODO(amjoseph): remove the `libgcc_s.so` symlinks below and replace them 24 + # with a `-L${gccForLibs.libgcc}/lib` in cc-wrapper's 25 + # `$out/nix-support/cc-flags`. See also: 26 + # - https://github.com/NixOS/nixpkgs/pull/209870#discussion_r1130614895 27 + # - https://github.com/NixOS/nixpkgs/pull/209870#discussion_r1130635982 28 + # - https://github.com/NixOS/nixpkgs/commit/404155c6acfa59456aebe6156b22fe385e7dec6f 29 + # 30 + # move `libgcc_s.so` into its own output, `$libgcc` 31 + + lib.optionalString enableLibGccOutput ('' 32 + # move libgcc from lib to its own output (libgcc) 33 + mkdir -p $libgcc/lib 34 + mv $lib/lib/libgcc_s.so $libgcc/lib/ 35 + mv $lib/lib/libgcc_s.so.1 $libgcc/lib/ 36 + ln -s $libgcc/lib/libgcc_s.so $lib/lib/ 37 + ln -s $libgcc/lib/libgcc_s.so.1 $lib/lib/ 38 + '' 39 + # 40 + # Nixpkgs ordinarily turns dynamic linking into pseudo-static linking: 41 + # libraries are still loaded dynamically, exactly which copy of each 42 + # library is loaded is permanently fixed at compile time (via RUNPATH). 43 + # For libgcc_s we must revert to the "impure dynamic linking" style found 44 + # in imperative software distributions. We must do this because 45 + # `libgcc_s` calls `malloc()` and therefore has a `DT_NEEDED` for `libc`, 46 + # which creates two problems: 47 + # 48 + # 1. A circular package dependency `glibc`<-`libgcc`<-`glibc` 49 + # 50 + # 2. According to the `-Wl,-rpath` flags added by Nixpkgs' `ld-wrapper`, 51 + # the two versions of `glibc` in the cycle above are actually 52 + # different packages. The later one is compiled by this `gcc`, but 53 + # the earlier one was compiled by the compiler *that compiled* this 54 + # `gcc` (usually the bootstrapFiles). In any event, the `glibc` 55 + # dynamic loader won't honor that specificity without namespaced 56 + # manual loads (`dlmopen()`). Once a `libc` is present in the address 57 + # space of a process, that `libc` will be used to satisfy all 58 + # `DT_NEEDED`s for `libc`, regardless of `RUNPATH`s. 59 + # 60 + # So we wipe the RUNPATH using `patchelf --set-rpath ""`. We can't use 61 + # `patchelf --remove-rpath`, because at least as of patchelf 0.15.0 it 62 + # will leave the old RUNPATH string in the file where the reference 63 + # scanner can still find it: 64 + # 65 + # https://github.com/NixOS/patchelf/issues/453 66 + # 67 + # Note: we might be using the bootstrapFiles' copy of patchelf, so we have 68 + # to keep doing it this way until both the issue is fixed *and* all the 69 + # bootstrapFiles are regenerated, on every platform. 70 + # 71 + # This patchelfing is *not* effectively equivalent to copying 72 + # `libgcc_s` into `glibc`'s outpath. There is one minor and one 73 + # major difference: 74 + # 75 + # 1. (Minor): multiple builds of `glibc` (say, with different 76 + # overrides or parameters) will all reference a single store 77 + # path: 78 + # 79 + # /nix/store/xxx...xxx-gcc-libgcc/lib/libgcc_s.so.1 80 + # 81 + # This many-to-one referrer relationship will be visible in the store's 82 + # dependency graph, and will be available to `nix-store -q` queries. 83 + # Copying `libgcc_s` into each of its referrers would lose that 84 + # information. 85 + # 86 + # 2. (Major): by referencing `libgcc_s.so.1`, rather than copying it, we 87 + # are still able to run `nix-store -qd` on it to find out how it got 88 + # built! Most importantly, we can see from that deriver which compiler 89 + # was used to build it (or if it is part of the unpacked 90 + # bootstrap-files). Copying `libgcc_s.so.1` from one outpath to 91 + # another eliminates the ability to make these queries. 92 + # 93 + + '' 94 + patchelf --set-rpath "" $libgcc/lib/libgcc_s.so.1 95 + ''); 96 + }))
+26 -27
pkgs/development/libraries/glibc/default.nix
··· 66 66 ]); 67 67 }; 68 68 69 - # When building glibc from bootstrap-tools, we need libgcc_s at RPATH for 70 - # any program we run, because the gcc will have been placed at a new 71 - # store path than that determined when built (as a source for the 72 - # bootstrap-tools tarball) 73 - # Building from a proper gcc staying in the path where it was installed, 74 - # libgcc_s will now be at {gcc}/lib, and gcc's libgcc will be found without 75 - # any special hack. 76 - # TODO: remove this hack. Things that rely on this hack today: 77 - # - dejagnu: during linux bootstrap tcl SIGSEGVs 78 - # - clang-wrapper in cross-compilation 79 - # Last attempt: https://github.com/NixOS/nixpkgs/pull/36948 80 - preInstall = lib.optionalString (stdenv.hostPlatform == stdenv.buildPlatform) '' 81 - if [ -f ${lib.getLib stdenv.cc.cc}/lib/libgcc_s.so.1 ]; then 82 - mkdir -p $out/lib 83 - cp ${lib.getLib stdenv.cc.cc}/lib/libgcc_s.so.1 $out/lib/libgcc_s.so.1 84 - # the .so It used to be a symlink, but now it is a script 85 - cp -a ${lib.getLib stdenv.cc.cc}/lib/libgcc_s.so $out/lib/libgcc_s.so 86 - # wipe out reference to previous libc it was built against 87 - chmod +w $out/lib/libgcc_s.so.1 88 - # rely on default RUNPATHs of the binary and other libraries 89 - # Do no force-pull wrong glibc. 90 - patchelf --remove-rpath $out/lib/libgcc_s.so.1 91 - # 'patchelf' does not remove the string itself. Wipe out 92 - # string reference to avoid possible link to bootstrapTools 93 - ${buildPackages.nukeReferences}/bin/nuke-refs $out/lib/libgcc_s.so.1 94 - fi 95 - ''; 69 + # glibc needs to `dlopen()` `libgcc_s.so` but does not link 70 + # against it. Furthermore, glibc doesn't use the ordinary 71 + # `dlopen()` call to do this; instead it uses one which ignores 72 + # most paths: 73 + # 74 + # https://sourceware.org/legacy-ml/libc-help/2013-11/msg00026.html 75 + # 76 + # In order to get it to not ignore `libgcc_s.so`, we have to add its path to 77 + # `user-defined-trusted-dirs`: 78 + # 79 + # https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/Makefile;h=b509b3eada1fb77bf81e2a0ca5740b94ad185764#l1355 80 + # 81 + # Conveniently, this will also inform Nix of the fact that glibc depends on 82 + # gcc.libgcc, since the path will be embedded in the resulting binary. 83 + # 84 + makeFlags = 85 + (previousAttrs.makeFlags or []) 86 + ++ lib.optionals (stdenv.cc.cc?libgcc) [ 87 + "user-defined-trusted-dirs=${stdenv.cc.cc.libgcc}/lib" 88 + ]; 96 89 97 90 postInstall = (if stdenv.hostPlatform == stdenv.buildPlatform then '' 98 91 echo SUPPORTED-LOCALES=C.UTF-8/UTF-8 > ../glibc-2*/localedata/SUPPORTED ··· 163 156 ''; 164 157 165 158 separateDebugInfo = true; 159 + 160 + passthru = 161 + (previousAttrs.passthru or {}) 162 + // lib.optionalAttrs (stdenv.cc.cc?libgcc) { 163 + inherit (stdenv.cc.cc) libgcc; 164 + }; 166 165 167 166 meta = (previousAttrs.meta or {}) // { description = "The GNU C Library"; }; 168 167 })
+2 -1
pkgs/development/tools/misc/ccache/default.nix
··· 74 74 # A derivation that provides gcc and g++ commands, but that 75 75 # will end up calling ccache for the given cacheDir 76 76 links = { unwrappedCC, extraConfig }: stdenv.mkDerivation { 77 - name = "ccache-links"; 77 + pname = "ccache-links"; 78 + inherit (finalAttrs) version; 78 79 passthru = { 79 80 isClang = unwrappedCC.isClang or false; 80 81 isGNU = unwrappedCC.isGNU or false;
+7
pkgs/stdenv/linux/bootstrap-tools/scripts/unpack-bootstrap-tools.sh
··· 30 30 # use a copy of patchelf. 31 31 LD_LIBRARY_PATH=$out/lib $LD_BINARY $out/bin/cp $out/bin/patchelf . 32 32 33 + # Older versions of the bootstrap-files did not compile their 34 + # patchelf with -static-libgcc, so we have to be very careful not to 35 + # run patchelf on the same copy of libgcc_s that it links against. 36 + LD_LIBRARY_PATH=$out/lib $LD_BINARY $out/bin/cp $out/lib/libgcc_s.so.1 . 37 + LD_LIBRARY_PATH=.:$out/lib:$LIBSTDCXX_SO_DIR $LD_BINARY \ 38 + ./patchelf --set-rpath $out/lib --force-rpath $out/lib/libgcc_s.so.1 39 + 33 40 for i in $out/bin/* $out/libexec/gcc/*/*/*; do 34 41 if [ -L "$i" ]; then continue; fi 35 42 if [ -z "${i##*/liblto*}" ]; then continue; fi
+137 -63
pkgs/stdenv/linux/default.nix
··· 10 10 # 11 11 # Goals of the bootstrap process: 12 12 # 1. final stdenv must not reference any of the bootstrap files. 13 - # 2. final stdenv must not contain any of the bootstrap files 14 - # (the only current violation is libgcc_s.so in glibc). 13 + # 2. final stdenv must not contain any of the bootstrap files. 15 14 # 3. final stdenv must not contain any of the files directly 16 15 # generated by the bootstrap code generators (assembler, linker, 17 - # compiler). The only current violations are: libgcc_s.so in glibc, 18 - # the lib{mpfr,mpc,gmp,isl} which are statically linked 19 - # into the final gcc). 16 + # compiler). 20 17 # 21 18 # These goals ensure that final packages and final stdenv are built 22 19 # exclusively using nixpkgs package definitions and don't depend ··· 111 108 isBuiltByBootstrapFilesCompiler = 112 109 pkg: isFromNixpkgs pkg && isFromBootstrapFiles pkg.stdenv.cc.cc; 113 110 111 + commonGccOverrides = { 112 + # Use a deterministically built compiler 113 + # see https://github.com/NixOS/nixpkgs/issues/108475 for context 114 + reproducibleBuild = true; 115 + profiledCompiler = false; 116 + 117 + # It appears that libcc1 (which is not a g++ plugin; it is a gdb plugin) gets linked against 118 + # the libstdc++ from the compiler that *built* g++, not the libstdc++ which was just built. 119 + # This causes a reference chain from stdenv to the bootstrapFiles: 120 + # 121 + # stdenv -> gcc-lib -> xgcc-lib -> bootstrapFiles 122 + # 123 + disableGdbPlugin = true; 124 + }; 125 + 114 126 commonPreHook = 115 127 '' 116 128 export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}" ··· 170 182 171 183 cc = if prevStage.gcc-unwrapped == null 172 184 then null 173 - else lib.makeOverridable (import ../../build-support/cc-wrapper) { 185 + else (lib.makeOverridable (import ../../build-support/cc-wrapper) { 174 186 name = "${name}-gcc-wrapper"; 175 187 nativeTools = false; 176 188 nativeLibc = false; ··· 184 196 inherit lib; 185 197 inherit (prevStage) coreutils gnugrep; 186 198 stdenvNoCC = prevStage.ccWrapperStdenv; 187 - }; 199 + }).overrideAttrs(a: lib.optionalAttrs (prevStage.gcc-unwrapped.passthru.isXgcc or false) { 200 + # This affects only `xgcc` (the compiler which compiles the final compiler). 201 + postFixup = (a.postFixup or "") + '' 202 + echo "--sysroot=${lib.getDev (getLibc prevStage)}" >> $out/nix-support/cc-cflags 203 + ''; 204 + }); 188 205 189 206 overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; }; 190 207 }; ··· 226 243 ${localSystem.libc} = self.stdenv.mkDerivation { 227 244 pname = "bootstrap-stage0-${localSystem.libc}"; 228 245 strictDeps = true; 229 - version = "bootstrap"; 246 + version = "bootstrapFiles"; 230 247 enableParallelBuilding = true; 231 248 buildCommand = '' 232 249 mkdir -p $out ··· 282 299 }; 283 300 inherit (prevStage) 284 301 ccWrapperStdenv 285 - gcc-unwrapped coreutils gnugrep; 302 + gcc-unwrapped coreutils gnugrep binutils; 286 303 287 304 ${localSystem.libc} = getLibc prevStage; 288 305 ··· 295 312 }; 296 313 }) 297 314 315 + # First rebuild of gcc; this is linked against all sorts of junk 316 + # from the bootstrap-files, but we only care about the code that 317 + # this compiler *emits*. The `gcc` binary produced in this stage 318 + # is not part of the final stdenv. 319 + (prevStage: 320 + assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped; 321 + assert isFromBootstrapFiles prevStage."${localSystem.libc}"; 322 + assert isFromBootstrapFiles prevStage.gcc-unwrapped; 323 + assert isFromBootstrapFiles prevStage.coreutils; 324 + assert isFromBootstrapFiles prevStage.gnugrep; 325 + stageFun prevStage { 326 + name = "bootstrap-stage-xgcc"; 327 + overrides = final: prev: { 328 + inherit (prevStage) ccWrapperStdenv coreutils gnugrep gettext bison texinfo zlib gnum4 perl; 329 + patchelf = bootstrapTools; 330 + ${localSystem.libc} = getLibc prevStage; 331 + gmp = prev.gmp.override { cxx = false; }; 332 + gcc-unwrapped = 333 + (prev.gcc-unwrapped.override (commonGccOverrides // { 334 + # The most logical name for this package would be something like 335 + # "gcc-stage1". Unfortunately "stage" is already reserved for the 336 + # layers of stdenv, so using "stage" in the name of this package 337 + # would cause massive confusion. 338 + # 339 + # Gcc calls its "stage1" compiler `xgcc` (--disable-bootstrap results 340 + # in `xgcc` being copied to $prefix/bin/gcc). So we imitate that. 341 + # 342 + name = "xgcc"; 343 + 344 + })).overrideAttrs (a: { 345 + 346 + # This signals to cc-wrapper (as overridden above in this file) to add `--sysroot` 347 + # to `$out/nix-support/cc-cflags`. 348 + passthru = a.passthru // { isXgcc = true; }; 349 + 350 + # Gcc will look for the C library headers in 351 + # 352 + # ${with_build_sysroot}${native_system_header_dir} 353 + # 354 + # The ordinary gcc expression sets `--with-build-sysroot=/` and sets 355 + # `native-system-header-dir` to `"${lib.getDev stdenv.cc.libc}/include`. 356 + # 357 + # Unfortunately the value of "--with-native-system-header-dir=" gets "burned in" to the 358 + # compiler, and it is quite difficult to get the compiler to change or ignore it 359 + # afterwards. On the other hand, the `sysroot` is very easy to change; you can just pass 360 + # a `--sysroot` flag to `gcc`. 361 + # 362 + # So we override the expression to remove the default settings for these flags, and 363 + # replace them such that the concatenated value will be the same as before, but we split 364 + # the value between the two variables differently: `--native-system-header-dir=/include`, 365 + # and `--with-build-sysroot=${lib.getDev stdenv.cc.libc}`. 366 + # 367 + configureFlags = (a.configureFlags or []) ++ [ 368 + "--with-native-system-header-dir=/include" 369 + "--with-build-sysroot=${lib.getDev final.stdenv.cc.libc}" 370 + ]; 371 + 372 + # This is a separate phase because gcc assembles its phase scripts 373 + # in bash instead of nix (we should fix that). 374 + preFixupPhases = (a.preFixupPhases or []) ++ [ "preFixupXgccPhase" ]; 375 + 376 + # This is needed to prevent "error: cycle detected in build of '...-xgcc-....drv' 377 + # in the references of output 'lib' from output 'out'" 378 + preFixupXgccPhase = '' 379 + find $lib/lib/ -name \*.so\* -exec patchelf --shrink-rpath {} \; || true 380 + ''; 381 + }); 382 + }; 383 + }) 298 384 299 385 # 2nd stdenv that contains our own rebuilt binutils and is used for 300 386 # compiling our own Glibc. ··· 303 389 # previous stage1 stdenv: 304 390 assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped; 305 391 assert isFromBootstrapFiles prevStage."${localSystem.libc}"; 306 - assert isFromBootstrapFiles prevStage.gcc-unwrapped; 392 + assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped; 307 393 assert isFromBootstrapFiles prevStage.coreutils; 308 394 assert isFromBootstrapFiles prevStage.gnugrep; 309 395 stageFun prevStage { ··· 313 399 inherit (prevStage) 314 400 ccWrapperStdenv gettext 315 401 gcc-unwrapped coreutils gnugrep 316 - perl gnum4 bison; 402 + perl gnum4 bison texinfo which; 317 403 dejagnu = super.dejagnu.overrideAttrs (a: { doCheck = false; } ); 318 404 319 405 # We need libidn2 and its dependency libunistring as glibc dependency. ··· 378 464 # binutils and rest of the bootstrap tools, including GCC. 379 465 (prevStage: 380 466 # previous stage2 stdenv: 381 - assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped; 382 - assert isBuiltByBootstrapFilesCompiler prevStage.${localSystem.libc}; 383 - assert isFromBootstrapFiles prevStage.gcc-unwrapped; 467 + assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; 468 + assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc}; 469 + assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped; 384 470 assert isFromBootstrapFiles prevStage.coreutils; 385 471 assert isFromBootstrapFiles prevStage.gnugrep; 472 + assert lib.all isBuiltByNixpkgsCompiler (with prevStage; [ gmp isl_0_20 libmpc mpfr ]); 386 473 stageFun prevStage { 387 474 name = "bootstrap-stage3"; 388 475 ··· 390 477 inherit (prevStage) 391 478 ccWrapperStdenv 392 479 binutils coreutils gnugrep gettext 393 - perl patchelf linuxHeaders gnum4 bison libidn2 libunistring; 480 + perl patchelf linuxHeaders gnum4 bison libidn2 libunistring libxcrypt; 481 + # We build a special copy of libgmp which doesn't use libstdc++, because 482 + # xgcc++'s libstdc++ references the bootstrap-files (which is what 483 + # compiles xgcc++). 484 + gmp = super.gmp.override { cxx = false; }; 485 + } // { 394 486 ${localSystem.libc} = getLibc prevStage; 395 - gcc-unwrapped = 396 - let makeStaticLibrariesAndMark = pkg: 397 - lib.makeOverridable (pkg.override { stdenv = self.makeStaticLibraries self.stdenv; }) 398 - .overrideAttrs (a: { pname = "${a.pname}-stage3"; }); 399 - in super.gcc-unwrapped.override { 400 - # Link GCC statically against GMP etc. This makes sense because 401 - # these builds of the libraries are only used by GCC, so it 402 - # reduces the size of the stdenv closure. 403 - gmp = makeStaticLibrariesAndMark super.gmp; 404 - mpfr = makeStaticLibrariesAndMark super.mpfr; 405 - libmpc = makeStaticLibrariesAndMark super.libmpc; 406 - isl = makeStaticLibrariesAndMark super.isl_0_20; 407 - # Use a deterministically built compiler 408 - # see https://github.com/NixOS/nixpkgs/issues/108475 for context 409 - reproducibleBuild = true; 410 - profiledCompiler = false; 411 - }; 487 + gcc-unwrapped = (super.gcc-unwrapped.override (commonGccOverrides // { 488 + inherit (prevStage) which; 489 + } 490 + )).overrideAttrs (a: { 491 + # so we can add them to allowedRequisites below 492 + passthru = a.passthru // { inherit (self) gmp mpfr libmpc isl; }; 493 + }); 412 494 }; 413 495 extraNativeBuildInputs = [ prevStage.patchelf ] ++ 414 496 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64. ··· 422 504 # 423 505 (prevStage: 424 506 # previous stage3 stdenv: 425 - assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped; 426 - assert isBuiltByBootstrapFilesCompiler prevStage.${localSystem.libc}; 427 - assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped; 428 - assert isFromBootstrapFiles prevStage.coreutils; 429 - assert isFromBootstrapFiles prevStage.gnugrep; 430 - # Can assume prevStage.gcc-unwrapped has almost no code from 431 - # bootstrapTools as gcc bootstraps internally. The only 432 - # exceptions are crt files from glibc built bybootstrapTools 433 - # used to link executables and libraries, and the 434 - # bootstrapTools-built, statically-linked 435 - # lib{mpfr,mpc,gmp,isl}.a which are linked into the final gcc 436 - # (see commit cfde88976ba4cddd01b1bb28b40afd12ea93a11d). 507 + assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; 508 + assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc}; 509 + assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped; 510 + assert isFromBootstrapFiles prevStage.coreutils; 511 + assert isFromBootstrapFiles prevStage.gnugrep; 437 512 stageFun prevStage { 438 513 name = "bootstrap-stage4"; 439 514 ··· 452 527 inherit (prevStage) stdenv; 453 528 }; 454 529 }; 455 - 456 - # force gmp to rebuild so we have the option of dynamically linking 457 - # libgmp without creating a reference path from: 458 - # stage5.gcc -> stage4.coreutils -> stage3.glibc -> bootstrap 459 - gmp = lib.makeOverridable (super.gmp.override { stdenv = self.stdenv; }).overrideAttrs (a: { pname = "${a.pname}-stage4"; }); 460 530 461 531 # To allow users' overrides inhibit dependencies too heavy for 462 532 # bootstrap, like guile: https://github.com/NixOS/nixpkgs/issues/181188 ··· 494 564 (prevStage: 495 565 # previous stage4 stdenv; see stage3 comment regarding gcc, 496 566 # which applies here as well. 497 - assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; 498 - assert isBuiltByBootstrapFilesCompiler prevStage.${localSystem.libc}; 499 - assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped; 500 - assert isBuiltByNixpkgsCompiler prevStage.coreutils; 501 - assert isBuiltByNixpkgsCompiler prevStage.gnugrep; 567 + assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; 568 + assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc}; 569 + assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped; 570 + assert isBuiltByNixpkgsCompiler prevStage.coreutils; 571 + assert isBuiltByNixpkgsCompiler prevStage.gnugrep; 502 572 { 503 573 inherit config overlays; 504 574 stdenv = import ../generic rec { ··· 546 616 ) 547 617 # More complicated cases 548 618 ++ (map (x: getOutput x (getLibc prevStage)) [ "out" "dev" "bin" ] ) 549 - ++ [ /*propagated from .dev*/ linuxHeaders 550 - binutils gcc gcc.cc gcc.cc.lib gcc.expand-response-params 619 + ++ [ linuxHeaders # propagated from .dev 620 + binutils gcc gcc.cc gcc.cc.lib gcc.expand-response-params gcc.cc.libgcc glibc.passthru.libgcc 551 621 ] 552 - ++ lib.optionals (!localSystem.isx86 || localSystem.libc == "musl") 553 - [ prevStage.updateAutotoolsGnuConfigScriptsHook prevStage.gnu-config ]; 622 + ++ lib.optionals (!localSystem.isx86 || localSystem.libc == "musl") 623 + [ prevStage.updateAutotoolsGnuConfigScriptsHook prevStage.gnu-config ] 624 + ++ (with gcc-unwrapped.passthru; [ 625 + gmp libmpc mpfr isl 626 + ]) 627 + ; 554 628 555 629 overrides = self: super: { 556 630 inherit (prevStage) ··· 579 653 (prevStage: 580 654 # previous stage5 stdenv; see stage3 comment regarding gcc, 581 655 # which applies here as well. 582 - assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; 583 - assert isBuiltByBootstrapFilesCompiler prevStage.${localSystem.libc}; 584 - assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped; 585 - assert isBuiltByNixpkgsCompiler prevStage.coreutils; 586 - assert isBuiltByNixpkgsCompiler prevStage.gnugrep; 656 + assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; 657 + assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc}; 658 + assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped; 659 + assert isBuiltByNixpkgsCompiler prevStage.coreutils; 660 + assert isBuiltByNixpkgsCompiler prevStage.gnugrep; 587 661 { inherit (prevStage) config overlays stdenv; }) 588 662 ]
+6 -1
pkgs/stdenv/linux/make-bootstrap-tools.nix
··· 2 2 3 3 let 4 4 libc = pkgs.stdenv.cc.libc; 5 + patchelf = pkgs.patchelf.overrideAttrs(previousAttrs: { 6 + NIX_CFLAGS_COMPILE = (previousAttrs.NIX_CFLAGS_COMPILE or []) ++ [ "-static-libgcc" "-static-libstdc++" ]; 7 + NIX_CFLAGS_LINK = (previousAttrs.NIX_CFLAGS_LINK or []) ++ [ "-static-libgcc" "-static-libstdc++" ]; 8 + }); 5 9 in with pkgs; rec { 6 10 7 11 ··· 127 131 cp -d ${bootGCC.out}/bin/gcc $out/bin 128 132 cp -d ${bootGCC.out}/bin/cpp $out/bin 129 133 cp -d ${bootGCC.out}/bin/g++ $out/bin 130 - cp -d ${bootGCC.lib}/lib/libgcc_s.so* $out/lib 134 + cp ${bootGCC.lib}/lib/libgcc_s.so* $out/lib 131 135 cp -d ${bootGCC.lib}/lib/libstdc++.so* $out/lib 132 136 cp -d ${bootGCC.out}/lib/libssp.a* $out/lib 133 137 cp -d ${bootGCC.out}/lib/libssp_nonshared.a $out/lib ··· 149 153 rm -rf $out/include/c++/*/ext/parallel 150 154 151 155 cp -d ${gmpxx.out}/lib/libgmp*.so* $out/lib 156 + cp -d ${isl.out}/lib/libisl*.so* $out/lib 152 157 cp -d ${mpfr.out}/lib/libmpfr*.so* $out/lib 153 158 cp -d ${libmpc.out}/lib/libmpc*.so* $out/lib 154 159 cp -d ${zlib.out}/lib/libz.so* $out/lib
+32
pkgs/test/stdenv/gcc-stageCompare.nix
··· 1 + # This test *must* be run prior to releasing any build of either stdenv or the 2 + # gcc that it exports! This check should also be part of CI for any PR that 3 + # causes a rebuild of `stdenv.cc`. 4 + # 5 + # When we used gcc's internal bootstrap it did this check as part of (and 6 + # serially with) the gcc derivation. Now that we bootstrap externally this 7 + # check can be done in parallel with any/all of stdenv's referrers. But we 8 + # must remember to do the check. 9 + # 10 + 11 + { stdenv 12 + , pkgs 13 + , lib 14 + }: 15 + 16 + assert stdenv.cc.isGNU; 17 + with pkgs; 18 + # rebuild gcc using the "final" stdenv 19 + let gcc-stageCompare = (gcc-unwrapped.override { 20 + reproducibleBuild = true; 21 + profiledCompiler = false; 22 + stdenv = overrideCC stdenv (wrapCCWith { 23 + cc = stdenv.cc; 24 + }); 25 + }).overrideAttrs(_: { 26 + NIX_OUTPATH_USED_AS_RANDOM_SEED = stdenv.cc.cc.out; 27 + }); 28 + in (runCommand "gcc-stageCompare" {} '' 29 + diff -sr ${pkgs.gcc-unwrapped.checksum}/checksums ${gcc-stageCompare.checksum}/checksums && touch $out 30 + '').overrideAttrs (a: { 31 + meta = (a.meta or { }) // { platforms = lib.platforms.linux; }; 32 + })
+2
pkgs/top-level/all-packages.nix
··· 34205 34205 34206 34206 testssl = callPackage ../applications/networking/testssl { }; 34207 34207 34208 + tests-stdenv-gcc-stageCompare = callPackage ../test/stdenv/gcc-stageCompare.nix { }; 34209 + 34208 34210 lavalauncher = callPackage ../applications/misc/lavalauncher { }; 34209 34211 34210 34212 t-rec = callPackage ../misc/t-rec {
+1 -1
pkgs/top-level/release-small.nix
··· 150 150 xfsprogs = linux; 151 151 xkeyboard_config = linux; 152 152 zip = all; 153 - 153 + tests-stdenv-gcc-stageCompare = all; 154 154 } ))