Merge pull request #247900 from amjoseph-nixpkgs/pr/stdenv/libgcc-no-more-cycles

glibcCross: use a libgcc built separately from gcc

authored by

Adam Joseph and committed by
GitHub
0dfed0d7 ea95c091

+207 -49
+6
pkgs/development/compilers/gcc/common/builder.nix
··· 3 , enableMultilib 4 }: 5 6 originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // { 7 preUnpack = '' 8 oldOpts="$(shopt -po nounset)" || true 9 set -euo pipefail
··· 3 , enableMultilib 4 }: 5 6 + let 7 + forceLibgccToBuildCrtStuff = 8 + import ./libgcc-buildstuff.nix { inherit lib stdenv; }; 9 + in 10 + 11 originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // { 12 + passthru = (originalAttrs.passthru or {}) // { inherit forceLibgccToBuildCrtStuff; }; 13 preUnpack = '' 14 oldOpts="$(shopt -po nounset)" || true 15 set -euo pipefail
+37
pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix
···
··· 1 + { lib 2 + , stdenv 3 + }: 4 + 5 + # Trick to build a gcc that is capable of emitting shared libraries *without* having the 6 + # targetPlatform libc available beforehand. Taken from: 7 + # https://web.archive.org/web/20170222224855/http://frank.harvard.edu/~coldwell/toolchain/ 8 + # https://web.archive.org/web/20170224235700/http://frank.harvard.edu/~coldwell/toolchain/t-linux.diff 9 + let 10 + # crt{i,n}.o are the first and last (respectively) object file 11 + # linked when producing an executable. Traditionally these 12 + # files are delivered as part of the C library, but on GNU 13 + # systems they are in fact built by GCC. Since libgcc needs to 14 + # build before glibc, we can't wait for them to be copied by 15 + # glibc. At this early pre-glibc stage these files sometimes 16 + # have different names. 17 + crtstuff-ofiles = 18 + if stdenv.targetPlatform.isPower 19 + then "ecrti.o ecrtn.o ncrti.o ncrtn.o" 20 + else "crti.o crtn.o"; 21 + 22 + # Normally, `SHLIB_LC` is set to `-lc`, which means that 23 + # `libgcc_s.so` cannot be built until `libc.so` is available. 24 + # The assignment below clobbers this variable, removing the 25 + # `-lc`. 26 + # 27 + # On PowerPC we add `-mnewlib`, which means "libc has not been 28 + # built yet". This causes libgcc's Makefile to use the 29 + # gcc-built `{e,n}crt{n,i}.o` instead of failing to find the 30 + # versions which have been repackaged in libc as `crt{n,i}.o` 31 + # 32 + SHLIB_LC = lib.optionalString stdenv.targetPlatform.isPower "-mnewlib"; 33 + 34 + in '' 35 + echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in 36 + echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in 37 + ''
+7 -7
pkgs/development/compilers/gcc/common/libgcc.nix
··· 44 !langJit && 45 !stdenv.hostPlatform.isDarwin && 46 enableShared 47 - ; 48 49 - # For some reason libgcc_s.so has major-version "2" on m68k but 50 - # "1" everywhere else. Might be worth changing this to "*". 51 - libgcc_s-version-major = 52 - if targetPlatform.isM68k 53 - then "2" 54 - else "1"; 55 56 in 57 (pkg: pkg.overrideAttrs (previousAttrs: lib.optionalAttrs ((!langC) || langJit || enableLibGccOutput) {
··· 44 !langJit && 45 !stdenv.hostPlatform.isDarwin && 46 enableShared 47 + ; 48 49 + # For some reason libgcc_s.so has major-version "2" on m68k but 50 + # "1" everywhere else. Might be worth changing this to "*". 51 + libgcc_s-version-major = 52 + if targetPlatform.isM68k 53 + then "2" 54 + else "1"; 55 56 in 57 (pkg: pkg.overrideAttrs (previousAttrs: lib.optionalAttrs ((!langC) || langJit || enableLibGccOutput) {
+1 -35
pkgs/development/compilers/gcc/common/pre-configure.nix
··· 112 export inhibit_libc=true 113 '' 114 115 - # Trick to build a gcc that is capable of emitting shared libraries *without* having the 116 - # targetPlatform libc available beforehand. Taken from: 117 - # https://web.archive.org/web/20170222224855/http://frank.harvard.edu/~coldwell/toolchain/ 118 - # https://web.archive.org/web/20170224235700/http://frank.harvard.edu/~coldwell/toolchain/t-linux.diff 119 + lib.optionalString (targetPlatform != hostPlatform && withoutTargetLibc && enableShared) 120 - (let 121 - 122 - # crt{i,n}.o are the first and last (respectively) object file 123 - # linked when producing an executable. Traditionally these 124 - # files are delivered as part of the C library, but on GNU 125 - # systems they are in fact built by GCC. Since libgcc needs to 126 - # build before glibc, we can't wait for them to be copied by 127 - # glibc. At this early pre-glibc stage these files sometimes 128 - # have different names. 129 - crtstuff-ofiles = 130 - if targetPlatform.isPower 131 - then "ecrti.o ecrtn.o ncrti.o ncrtn.o" 132 - else "crti.o crtn.o"; 133 - 134 - # Normally, `SHLIB_LC` is set to `-lc`, which means that 135 - # `libgcc_s.so` cannot be built until `libc.so` is available. 136 - # The assignment below clobbers this variable, removing the 137 - # `-lc`. 138 - # 139 - # On PowerPC we add `-mnewlib`, which means "libc has not been 140 - # built yet". This causes libgcc's Makefile to use the 141 - # gcc-built `{e,n}crt{n,i}.o` instead of failing to find the 142 - # versions which have been repackaged in libc as `crt{n,i}.o` 143 - # 144 - SHLIB_LC = lib.optionalString targetPlatform.isPower "-mnewlib"; 145 - 146 - in '' 147 - echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in 148 - echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in 149 - '') 150 -
··· 112 export inhibit_libc=true 113 '' 114 115 + lib.optionalString (targetPlatform != hostPlatform && withoutTargetLibc && enableShared) 116 + (import ./libgcc-buildstuff.nix { inherit lib stdenv; })
+140
pkgs/development/libraries/gcc/libgcc/default.nix
···
··· 1 + { lib, stdenvNoLibs, buildPackages 2 + , gcc, glibc 3 + , libiberty 4 + }: 5 + 6 + let 7 + stdenv = stdenvNoLibs; 8 + gccConfigureFlags = gcc.cc.configureFlags ++ [ 9 + "--disable-fixincludes" 10 + "--disable-intl" 11 + "--enable-threads=posix" 12 + "--with-glibc-version=${glibc.version}" 13 + 14 + # these are required in order to prevent inhibit_libc=true, 15 + # which will cripple libgcc's unwinder; see: 16 + # https://github.com/NixOS/nixpkgs/issues/213453#issuecomment-1616346163 17 + "--with-headers=${lib.getDev glibc}/include" 18 + "--with-native-system-header-dir=${lib.getDev glibc}${glibc.incdir or "/include"}" 19 + "--with-build-sysroot=/" 20 + ]; 21 + 22 + in stdenv.mkDerivation (finalAttrs: { 23 + pname = "libgcc"; 24 + inherit (gcc.cc) src version; 25 + 26 + outputs = [ "out" "dev" ]; 27 + 28 + strictDeps = true; 29 + depsBuildBuild = [ buildPackages.stdenv.cc ]; 30 + nativeBuildInputs = [ libiberty ]; 31 + buildInputs = [ glibc ]; 32 + 33 + postUnpack = '' 34 + mkdir -p ./build 35 + buildRoot=$(readlink -e "./build") 36 + ''; 37 + 38 + postPatch = 39 + gcc.cc.passthru.forceLibgccToBuildCrtStuff 40 + + '' 41 + sourceRoot=$(readlink -e "./libgcc") 42 + ''; 43 + 44 + hardeningDisable = [ "pie" ]; 45 + 46 + preConfigure = 47 + '' 48 + # Drop in libiberty, as external builds are not expected 49 + cd "$buildRoot" 50 + ( 51 + mkdir -p build-${stdenv.buildPlatform.config}/libiberty/ 52 + cd build-${stdenv.buildPlatform.config}/libiberty/ 53 + ln -s ${buildPackages.libiberty}/lib/libiberty.a ./ 54 + ) 55 + mkdir -p "$buildRoot/gcc" 56 + cd "$buildRoot/gcc" 57 + ( 58 + # We "shift" the tools over to fake platforms perspective from the previous stage. 59 + export AS_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$AS_FOR_BUILD 60 + export CC_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CC_FOR_BUILD 61 + export CPP_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CPP_FOR_BUILD 62 + export CXX_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CXX_FOR_BUILD 63 + export LD_FOR_BUILD=${buildPackages.stdenv.cc.bintools}/bin/$LD_FOR_BUILD 64 + 65 + export AS=$AS_FOR_BUILD 66 + export CC=$CC_FOR_BUILD 67 + export CPP=$CPP_FOR_BUILD 68 + export CXX=$CXX_FOR_BUILD 69 + export LD=$LD_FOR_BUILD 70 + 71 + export AS_FOR_TARGET=${stdenv.cc}/bin/$AS 72 + export CC_FOR_TARGET=${stdenv.cc}/bin/$CC 73 + export CPP_FOR_TARGET=${stdenv.cc}/bin/$CPP 74 + export LD_FOR_TARGET=${stdenv.cc.bintools}/bin/$LD 75 + 76 + # We define GENERATOR_FILE so nothing bothers looking for GNU GMP. 77 + export NIX_CFLAGS_COMPILE_FOR_BUILD+=' -DGENERATOR_FILE=1' 78 + 79 + "$sourceRoot/../gcc/configure" ${lib.concatStringsSep " " gccConfigureFlags} 80 + 81 + # We remove the `libgcc.mvar` deps so that the bootstrap xgcc isn't built. 82 + sed -e 's,libgcc.mvars:.*$,libgcc.mvars:,' -i Makefile 83 + 84 + make \ 85 + config.h \ 86 + libgcc.mvars \ 87 + tconfig.h \ 88 + tm.h \ 89 + options.h \ 90 + insn-constants.h \ 91 + '' + lib.optionalString stdenv.targetPlatform.isM68k '' 92 + sysroot-suffix.h \ 93 + '' + lib.optionalString stdenv.targetPlatform.isArmv7 '' 94 + arm-isa.h \ 95 + arm-cpu.h \ 96 + '' + '' 97 + insn-modes.h 98 + ) 99 + mkdir -p "$buildRoot/gcc/include" 100 + 101 + # Preparing to configure + build libgcc itself 102 + mkdir -p "$buildRoot/gcc/${stdenv.hostPlatform.config}/libgcc" 103 + cd "$buildRoot/gcc/${stdenv.hostPlatform.config}/libgcc" 104 + configureScript=$sourceRoot/configure 105 + chmod +x "$configureScript" 106 + 107 + export AS_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$AS_FOR_BUILD 108 + export CC_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CC_FOR_BUILD 109 + export CPP_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CPP_FOR_BUILD 110 + export CXX_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CXX_FOR_BUILD 111 + export LD_FOR_BUILD=${buildPackages.stdenv.cc.bintools}/bin/$LD_FOR_BUILD 112 + 113 + export AS=${stdenv.cc}/bin/$AS 114 + export CC=${stdenv.cc}/bin/$CC 115 + export CPP=${stdenv.cc}/bin/$CPP 116 + export CXX=${stdenv.cc}/bin/$CXX 117 + export LD=${stdenv.cc.bintools}/bin/$LD 118 + 119 + export AS_FOR_TARGET=${stdenv.cc}/bin/$AS_FOR_TARGET 120 + export CC_FOR_TARGET=${stdenv.cc}/bin/$CC_FOR_TARGET 121 + export CPP_FOR_TARGET=${stdenv.cc}/bin/$CPP_FOR_TARGET 122 + export LD_FOR_TARGET=${stdenv.cc.bintools}/bin/$LD_FOR_TARGET 123 + ''; 124 + 125 + configurePlatforms = [ "build" "host" ]; 126 + configureFlags = [ 127 + "cross_compiling=true" 128 + "--disable-gcov" 129 + "--with-glibc-version=${glibc.version}" 130 + ]; 131 + 132 + makeFlags = [ "MULTIBUILDTOP:=../" ]; 133 + 134 + postInstall = '' 135 + moveToOutput "lib/gcc/${stdenv.hostPlatform.config}/${finalAttrs.version}/include" "$dev" 136 + mkdir -p "$out/lib" "$dev/include" 137 + ln -s "$out/lib/gcc/${stdenv.hostPlatform.config}/${finalAttrs.version}"/* "$out/lib" 138 + ln -s "$dev/lib/gcc/${stdenv.hostPlatform.config}/${finalAttrs.version}/include"/* "$dev/include/" 139 + ''; 140 + })
+6 -5
pkgs/development/libraries/glibc/default.nix
··· 4 , withGd ? false 5 , withLibcrypt? false 6 , buildPackages 7 }: 8 9 let ··· 16 17 (callPackage ./common.nix { inherit stdenv; } { 18 inherit withLinuxHeaders withGd profilingLibraries withLibcrypt; 19 - pname = "glibc" + lib.optionalString withGd "-gd"; 20 }).overrideAttrs(previousAttrs: { 21 22 # Note: ··· 90 # 91 makeFlags = 92 (previousAttrs.makeFlags or []) 93 - ++ lib.optionals (stdenv.cc.cc?libgcc) [ 94 - "user-defined-trusted-dirs=${stdenv.cc.cc.libgcc}/lib" 95 ]; 96 97 postInstall = previousAttrs.postInstall + (if stdenv.hostPlatform == stdenv.buildPlatform then '' ··· 166 167 passthru = 168 (previousAttrs.passthru or {}) 169 - // lib.optionalAttrs (stdenv.cc.cc?libgcc) { 170 - inherit (stdenv.cc.cc) libgcc; 171 }; 172 173 meta = (previousAttrs.meta or {}) // { description = "The GNU C Library"; };
··· 4 , withGd ? false 5 , withLibcrypt? false 6 , buildPackages 7 + , libgcc 8 }: 9 10 let ··· 17 18 (callPackage ./common.nix { inherit stdenv; } { 19 inherit withLinuxHeaders withGd profilingLibraries withLibcrypt; 20 + pname = "glibc" + lib.optionalString withGd "-gd" + lib.optionalString (stdenv.cc.isGNU && libgcc==null) "-nolibgcc"; 21 }).overrideAttrs(previousAttrs: { 22 23 # Note: ··· 91 # 92 makeFlags = 93 (previousAttrs.makeFlags or []) 94 + ++ lib.optionals (libgcc != null) [ 95 + "user-defined-trusted-dirs=${libgcc}/lib" 96 ]; 97 98 postInstall = previousAttrs.postInstall + (if stdenv.hostPlatform == stdenv.buildPlatform then '' ··· 167 168 passthru = 169 (previousAttrs.passthru or {}) 170 + // lib.optionalAttrs (libgcc != null) { 171 + inherit libgcc; 172 }; 173 174 meta = (previousAttrs.meta or {}) // { description = "The GNU C Library"; };
+3 -1
pkgs/test/cross/default.nix
··· 115 in 116 pkgs.runCommand "test-mbuffer" {} '' 117 echo hello | ${emulator} ${mbuffer}/bin/mbuffer 118 ''; 119 120 # This is meant to be a carefully curated list of builds/packages ··· 127 # of things that often break. So, no buckshot `mapTestOnCross` 128 # calls here. 129 sanity = [ 130 - #pkgs.mbuffer # https://github.com/NixOS/nixpkgs/issues/213453 131 #pkgs.pkgsCross.gnu64.bash # https://github.com/NixOS/nixpkgs/issues/243164 132 pkgs.gcc_multi.cc 133 pkgs.pkgsMusl.stdenv 134 pkgs.pkgsLLVM.stdenv 135 pkgs.pkgsStatic.bash 136 pkgs.pkgsCross.arm-embedded.stdenv 137 pkgs.pkgsCross.m68k.stdenv 138 pkgs.pkgsCross.aarch64-multiplatform.pkgsBuildTarget.gcc 139 pkgs.pkgsCross.powernv.pkgsBuildTarget.gcc
··· 115 in 116 pkgs.runCommand "test-mbuffer" {} '' 117 echo hello | ${emulator} ${mbuffer}/bin/mbuffer 118 + touch $out 119 ''; 120 121 # This is meant to be a carefully curated list of builds/packages ··· 128 # of things that often break. So, no buckshot `mapTestOnCross` 129 # calls here. 130 sanity = [ 131 + mbuffer 132 #pkgs.pkgsCross.gnu64.bash # https://github.com/NixOS/nixpkgs/issues/243164 133 pkgs.gcc_multi.cc 134 pkgs.pkgsMusl.stdenv 135 pkgs.pkgsLLVM.stdenv 136 pkgs.pkgsStatic.bash 137 pkgs.pkgsCross.arm-embedded.stdenv 138 + pkgs.pkgsCross.armv7l-hf-multiplatform.stdenv 139 pkgs.pkgsCross.m68k.stdenv 140 pkgs.pkgsCross.aarch64-multiplatform.pkgsBuildTarget.gcc 141 pkgs.pkgsCross.powernv.pkgsBuildTarget.gcc
-1
pkgs/top-level/aliases.nix
··· 879 liberation_ttf_v1_from_source = throw "'liberation_ttf_v1_from_source' has been renamed to/replaced by 'liberation_ttf_v1'"; # Converted to throw 2022-02-22 880 liberation_ttf_v2_from_source = throw "'liberation_ttf_v2_from_source' has been renamed to/replaced by 'liberation_ttf_v2'"; # Converted to throw 2022-02-22 881 liberationsansnarrow = throw "'liberationsansnarrow' has been renamed to/replaced by 'liberation-sans-narrow'"; # Converted to throw 2022-02-22 882 - libgcc = throw "libgcc was removed, use gcc.cc.libgcc if needed"; # added 2023-05-13 883 libgksu = throw "libgksu has been removed"; # Added 2022-01-16 884 libgme = game-music-emu; # Added 2022-07-20 885 libgnome_keyring = throw "'libgnome_keyring' has been renamed to/replaced by 'libgnome-keyring'"; # Converted to throw 2022-02-22
··· 879 liberation_ttf_v1_from_source = throw "'liberation_ttf_v1_from_source' has been renamed to/replaced by 'liberation_ttf_v1'"; # Converted to throw 2022-02-22 880 liberation_ttf_v2_from_source = throw "'liberation_ttf_v2_from_source' has been renamed to/replaced by 'liberation_ttf_v2'"; # Converted to throw 2022-02-22 881 liberationsansnarrow = throw "'liberationsansnarrow' has been renamed to/replaced by 'liberation-sans-narrow'"; # Converted to throw 2022-02-22 882 libgksu = throw "libgksu has been removed"; # Added 2022-01-16 883 libgme = game-music-emu; # Added 2022-07-20 884 libgnome_keyring = throw "'libgnome_keyring' has been renamed to/replaced by 'libgnome-keyring'"; # Converted to throw 2022-02-22
+7
pkgs/top-level/all-packages.nix
··· 18918 18919 librarian-puppet-go = callPackage ../development/tools/librarian-puppet-go { }; 18920 18921 # This is for e.g. LLVM libraries on linux. 18922 gccForLibs = 18923 if stdenv.targetPlatform == stdenv.hostPlatform && targetPackages.stdenv.cc.isGNU ··· 21444 # Being redundant to avoid cycles on boot. TODO: find a better way 21445 glibcCross = callPackage ../development/libraries/glibc { 21446 stdenv = gccCrossLibcStdenv; # doesn't compile without gcc 21447 }; 21448 21449 muslCross = musl.override {
··· 18918 18919 librarian-puppet-go = callPackage ../development/tools/librarian-puppet-go { }; 18920 18921 + libgcc = stdenv.cc.cc.libgcc or null; 18922 + 18923 # This is for e.g. LLVM libraries on linux. 18924 gccForLibs = 18925 if stdenv.targetPlatform == stdenv.hostPlatform && targetPackages.stdenv.cc.isGNU ··· 21446 # Being redundant to avoid cycles on boot. TODO: find a better way 21447 glibcCross = callPackage ../development/libraries/glibc { 21448 stdenv = gccCrossLibcStdenv; # doesn't compile without gcc 21449 + libgcc = callPackage ../development/libraries/gcc/libgcc { 21450 + gcc = gccCrossLibcStdenv.cc; 21451 + glibc = glibcCross.override { libgcc = null; }; 21452 + stdenvNoLibs = gccCrossLibcStdenv; 21453 + }; 21454 }; 21455 21456 muslCross = musl.override {