diff --git a/pkgs/development/compilers/gcc/common/builder.nix b/pkgs/development/compilers/gcc/common/builder.nix index cd8d4572a158b..6df4e32ddb765 100644 --- a/pkgs/development/compilers/gcc/common/builder.nix +++ b/pkgs/development/compilers/gcc/common/builder.nix @@ -3,7 +3,13 @@ , enableMultilib }: +let + forceLibgccToBuildCrtStuff = + import ./libgcc-buildstuff.nix { inherit lib stdenv; }; +in + originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // { + passthru = (originalAttrs.passthru or {}) // { inherit forceLibgccToBuildCrtStuff; }; preUnpack = '' oldOpts="$(shopt -po nounset)" || true set -euo pipefail diff --git a/pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix b/pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix new file mode 100644 index 0000000000000..e7dc570a560cb --- /dev/null +++ b/pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix @@ -0,0 +1,37 @@ +{ lib +, stdenv +}: + +# Trick to build a gcc that is capable of emitting shared libraries *without* having the +# targetPlatform libc available beforehand. Taken from: +# https://web.archive.org/web/20170222224855/http://frank.harvard.edu/~coldwell/toolchain/ +# https://web.archive.org/web/20170224235700/http://frank.harvard.edu/~coldwell/toolchain/t-linux.diff +let + # crt{i,n}.o are the first and last (respectively) object file + # linked when producing an executable. Traditionally these + # files are delivered as part of the C library, but on GNU + # systems they are in fact built by GCC. Since libgcc needs to + # build before glibc, we can't wait for them to be copied by + # glibc. At this early pre-glibc stage these files sometimes + # have different names. + crtstuff-ofiles = + if stdenv.targetPlatform.isPower + then "ecrti.o ecrtn.o ncrti.o ncrtn.o" + else "crti.o crtn.o"; + + # Normally, `SHLIB_LC` is set to `-lc`, which means that + # `libgcc_s.so` cannot be built until `libc.so` is available. + # The assignment below clobbers this variable, removing the + # `-lc`. + # + # On PowerPC we add `-mnewlib`, which means "libc has not been + # built yet". This causes libgcc's Makefile to use the + # gcc-built `{e,n}crt{n,i}.o` instead of failing to find the + # versions which have been repackaged in libc as `crt{n,i}.o` + # + SHLIB_LC = lib.optionalString stdenv.targetPlatform.isPower "-mnewlib"; + +in '' + echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in + echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in + '' diff --git a/pkgs/development/compilers/gcc/common/libgcc.nix b/pkgs/development/compilers/gcc/common/libgcc.nix index b14d111e361f5..4ab6eb2b3b440 100644 --- a/pkgs/development/compilers/gcc/common/libgcc.nix +++ b/pkgs/development/compilers/gcc/common/libgcc.nix @@ -44,14 +44,14 @@ lib.optional (lib.versionAtLeast version "11.0") !langJit && !stdenv.hostPlatform.isDarwin && enableShared - ; + ; - # For some reason libgcc_s.so has major-version "2" on m68k but - # "1" everywhere else. Might be worth changing this to "*". - libgcc_s-version-major = - if targetPlatform.isM68k - then "2" - else "1"; + # For some reason libgcc_s.so has major-version "2" on m68k but + # "1" everywhere else. Might be worth changing this to "*". + libgcc_s-version-major = + if targetPlatform.isM68k + then "2" + else "1"; in (pkg: pkg.overrideAttrs (previousAttrs: lib.optionalAttrs ((!langC) || langJit || enableLibGccOutput) { diff --git a/pkgs/development/compilers/gcc/common/pre-configure.nix b/pkgs/development/compilers/gcc/common/pre-configure.nix index 933a132ce4d1d..5cb2f186fd1d5 100644 --- a/pkgs/development/compilers/gcc/common/pre-configure.nix +++ b/pkgs/development/compilers/gcc/common/pre-configure.nix @@ -112,39 +112,5 @@ in lib.optionalString (hostPlatform.isSunOS && hostPlatform.is64bit) '' export inhibit_libc=true '' -# Trick to build a gcc that is capable of emitting shared libraries *without* having the -# targetPlatform libc available beforehand. Taken from: -# https://web.archive.org/web/20170222224855/http://frank.harvard.edu/~coldwell/toolchain/ -# https://web.archive.org/web/20170224235700/http://frank.harvard.edu/~coldwell/toolchain/t-linux.diff + lib.optionalString (targetPlatform != hostPlatform && withoutTargetLibc && enableShared) - (let - - # crt{i,n}.o are the first and last (respectively) object file - # linked when producing an executable. Traditionally these - # files are delivered as part of the C library, but on GNU - # systems they are in fact built by GCC. Since libgcc needs to - # build before glibc, we can't wait for them to be copied by - # glibc. At this early pre-glibc stage these files sometimes - # have different names. - crtstuff-ofiles = - if targetPlatform.isPower - then "ecrti.o ecrtn.o ncrti.o ncrtn.o" - else "crti.o crtn.o"; - - # Normally, `SHLIB_LC` is set to `-lc`, which means that - # `libgcc_s.so` cannot be built until `libc.so` is available. - # The assignment below clobbers this variable, removing the - # `-lc`. - # - # On PowerPC we add `-mnewlib`, which means "libc has not been - # built yet". This causes libgcc's Makefile to use the - # gcc-built `{e,n}crt{n,i}.o` instead of failing to find the - # versions which have been repackaged in libc as `crt{n,i}.o` - # - SHLIB_LC = lib.optionalString targetPlatform.isPower "-mnewlib"; - - in '' - echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in - echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in - '') - + (import ./libgcc-buildstuff.nix { inherit lib stdenv; }) diff --git a/pkgs/development/libraries/gcc/libgcc/default.nix b/pkgs/development/libraries/gcc/libgcc/default.nix new file mode 100644 index 0000000000000..e2fbf55876fa1 --- /dev/null +++ b/pkgs/development/libraries/gcc/libgcc/default.nix @@ -0,0 +1,140 @@ +{ lib, stdenvNoLibs, buildPackages +, gcc, glibc +, libiberty +}: + +let + stdenv = stdenvNoLibs; + gccConfigureFlags = gcc.cc.configureFlags ++ [ + "--disable-fixincludes" + "--disable-intl" + "--enable-threads=posix" + "--with-glibc-version=${glibc.version}" + + # these are required in order to prevent inhibit_libc=true, + # which will cripple libgcc's unwinder; see: + # https://github.com/NixOS/nixpkgs/issues/213453#issuecomment-1616346163 + "--with-headers=${lib.getDev glibc}/include" + "--with-native-system-header-dir=${lib.getDev glibc}${glibc.incdir or "/include"}" + "--with-build-sysroot=/" + ]; + +in stdenv.mkDerivation (finalAttrs: { + pname = "libgcc"; + inherit (gcc.cc) src version; + + outputs = [ "out" "dev" ]; + + strictDeps = true; + depsBuildBuild = [ buildPackages.stdenv.cc ]; + nativeBuildInputs = [ libiberty ]; + buildInputs = [ glibc ]; + + postUnpack = '' + mkdir -p ./build + buildRoot=$(readlink -e "./build") + ''; + + postPatch = + gcc.cc.passthru.forceLibgccToBuildCrtStuff + + '' + sourceRoot=$(readlink -e "./libgcc") + ''; + + hardeningDisable = [ "pie" ]; + + preConfigure = + '' + # Drop in libiberty, as external builds are not expected + cd "$buildRoot" + ( + mkdir -p build-${stdenv.buildPlatform.config}/libiberty/ + cd build-${stdenv.buildPlatform.config}/libiberty/ + ln -s ${buildPackages.libiberty}/lib/libiberty.a ./ + ) + mkdir -p "$buildRoot/gcc" + cd "$buildRoot/gcc" + ( + # We "shift" the tools over to fake platforms perspective from the previous stage. + export AS_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$AS_FOR_BUILD + export CC_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CC_FOR_BUILD + export CPP_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CPP_FOR_BUILD + export CXX_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CXX_FOR_BUILD + export LD_FOR_BUILD=${buildPackages.stdenv.cc.bintools}/bin/$LD_FOR_BUILD + + export AS=$AS_FOR_BUILD + export CC=$CC_FOR_BUILD + export CPP=$CPP_FOR_BUILD + export CXX=$CXX_FOR_BUILD + export LD=$LD_FOR_BUILD + + export AS_FOR_TARGET=${stdenv.cc}/bin/$AS + export CC_FOR_TARGET=${stdenv.cc}/bin/$CC + export CPP_FOR_TARGET=${stdenv.cc}/bin/$CPP + export LD_FOR_TARGET=${stdenv.cc.bintools}/bin/$LD + + # We define GENERATOR_FILE so nothing bothers looking for GNU GMP. + export NIX_CFLAGS_COMPILE_FOR_BUILD+=' -DGENERATOR_FILE=1' + + "$sourceRoot/../gcc/configure" ${lib.concatStringsSep " " gccConfigureFlags} + + # We remove the `libgcc.mvar` deps so that the bootstrap xgcc isn't built. + sed -e 's,libgcc.mvars:.*$,libgcc.mvars:,' -i Makefile + + make \ + config.h \ + libgcc.mvars \ + tconfig.h \ + tm.h \ + options.h \ + insn-constants.h \ + '' + lib.optionalString stdenv.targetPlatform.isM68k '' + sysroot-suffix.h \ + '' + lib.optionalString stdenv.targetPlatform.isArmv7 '' + arm-isa.h \ + arm-cpu.h \ + '' + '' + insn-modes.h + ) + mkdir -p "$buildRoot/gcc/include" + + # Preparing to configure + build libgcc itself + mkdir -p "$buildRoot/gcc/${stdenv.hostPlatform.config}/libgcc" + cd "$buildRoot/gcc/${stdenv.hostPlatform.config}/libgcc" + configureScript=$sourceRoot/configure + chmod +x "$configureScript" + + export AS_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$AS_FOR_BUILD + export CC_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CC_FOR_BUILD + export CPP_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CPP_FOR_BUILD + export CXX_FOR_BUILD=${buildPackages.stdenv.cc}/bin/$CXX_FOR_BUILD + export LD_FOR_BUILD=${buildPackages.stdenv.cc.bintools}/bin/$LD_FOR_BUILD + + export AS=${stdenv.cc}/bin/$AS + export CC=${stdenv.cc}/bin/$CC + export CPP=${stdenv.cc}/bin/$CPP + export CXX=${stdenv.cc}/bin/$CXX + export LD=${stdenv.cc.bintools}/bin/$LD + + export AS_FOR_TARGET=${stdenv.cc}/bin/$AS_FOR_TARGET + export CC_FOR_TARGET=${stdenv.cc}/bin/$CC_FOR_TARGET + export CPP_FOR_TARGET=${stdenv.cc}/bin/$CPP_FOR_TARGET + export LD_FOR_TARGET=${stdenv.cc.bintools}/bin/$LD_FOR_TARGET + ''; + + configurePlatforms = [ "build" "host" ]; + configureFlags = [ + "cross_compiling=true" + "--disable-gcov" + "--with-glibc-version=${glibc.version}" + ]; + + makeFlags = [ "MULTIBUILDTOP:=../" ]; + + postInstall = '' + moveToOutput "lib/gcc/${stdenv.hostPlatform.config}/${finalAttrs.version}/include" "$dev" + mkdir -p "$out/lib" "$dev/include" + ln -s "$out/lib/gcc/${stdenv.hostPlatform.config}/${finalAttrs.version}"/* "$out/lib" + ln -s "$dev/lib/gcc/${stdenv.hostPlatform.config}/${finalAttrs.version}/include"/* "$dev/include/" + ''; +}) diff --git a/pkgs/development/libraries/glibc/default.nix b/pkgs/development/libraries/glibc/default.nix index 0f6cad157bb78..1c822bf1ed019 100644 --- a/pkgs/development/libraries/glibc/default.nix +++ b/pkgs/development/libraries/glibc/default.nix @@ -4,6 +4,7 @@ , withGd ? false , withLibcrypt? false , buildPackages +, libgcc }: let @@ -16,7 +17,7 @@ in (callPackage ./common.nix { inherit stdenv; } { inherit withLinuxHeaders withGd profilingLibraries withLibcrypt; - pname = "glibc" + lib.optionalString withGd "-gd"; + pname = "glibc" + lib.optionalString withGd "-gd" + lib.optionalString (stdenv.cc.isGNU && libgcc==null) "-nolibgcc"; }).overrideAttrs(previousAttrs: { # Note: @@ -90,8 +91,8 @@ in # makeFlags = (previousAttrs.makeFlags or []) - ++ lib.optionals (stdenv.cc.cc?libgcc) [ - "user-defined-trusted-dirs=${stdenv.cc.cc.libgcc}/lib" + ++ lib.optionals (libgcc != null) [ + "user-defined-trusted-dirs=${libgcc}/lib" ]; postInstall = previousAttrs.postInstall + (if stdenv.hostPlatform == stdenv.buildPlatform then '' @@ -166,8 +167,8 @@ in passthru = (previousAttrs.passthru or {}) - // lib.optionalAttrs (stdenv.cc.cc?libgcc) { - inherit (stdenv.cc.cc) libgcc; + // lib.optionalAttrs (libgcc != null) { + inherit libgcc; }; meta = (previousAttrs.meta or {}) // { description = "The GNU C Library"; }; diff --git a/pkgs/test/cross/default.nix b/pkgs/test/cross/default.nix index 46bb3c8d522d2..d6fd8d3b1f80c 100644 --- a/pkgs/test/cross/default.nix +++ b/pkgs/test/cross/default.nix @@ -115,6 +115,7 @@ let in pkgs.runCommand "test-mbuffer" {} '' echo hello | ${emulator} ${mbuffer}/bin/mbuffer + touch $out ''; # This is meant to be a carefully curated list of builds/packages @@ -127,13 +128,14 @@ let # of things that often break. So, no buckshot `mapTestOnCross` # calls here. sanity = [ - #pkgs.mbuffer # https://github.com/NixOS/nixpkgs/issues/213453 + mbuffer #pkgs.pkgsCross.gnu64.bash # https://github.com/NixOS/nixpkgs/issues/243164 pkgs.gcc_multi.cc pkgs.pkgsMusl.stdenv pkgs.pkgsLLVM.stdenv pkgs.pkgsStatic.bash pkgs.pkgsCross.arm-embedded.stdenv + pkgs.pkgsCross.armv7l-hf-multiplatform.stdenv pkgs.pkgsCross.m68k.stdenv pkgs.pkgsCross.aarch64-multiplatform.pkgsBuildTarget.gcc pkgs.pkgsCross.powernv.pkgsBuildTarget.gcc diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index 04273984e81d4..1dc91abc19381 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -879,7 +879,6 @@ mapAliases ({ 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 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 liberationsansnarrow = throw "'liberationsansnarrow' has been renamed to/replaced by 'liberation-sans-narrow'"; # Converted to throw 2022-02-22 - libgcc = throw "libgcc was removed, use gcc.cc.libgcc if needed"; # added 2023-05-13 libgksu = throw "libgksu has been removed"; # Added 2022-01-16 libgme = game-music-emu; # Added 2022-07-20 libgnome_keyring = throw "'libgnome_keyring' has been renamed to/replaced by 'libgnome-keyring'"; # Converted to throw 2022-02-22 diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 1613c7a2f0755..44d90dd9c5759 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -18911,6 +18911,8 @@ with pkgs; librarian-puppet-go = callPackage ../development/tools/librarian-puppet-go { }; + libgcc = stdenv.cc.cc.libgcc or null; + # This is for e.g. LLVM libraries on linux. gccForLibs = if stdenv.targetPlatform == stdenv.hostPlatform && targetPackages.stdenv.cc.isGNU @@ -21437,6 +21439,11 @@ with pkgs; # Being redundant to avoid cycles on boot. TODO: find a better way glibcCross = callPackage ../development/libraries/glibc { stdenv = gccCrossLibcStdenv; # doesn't compile without gcc + libgcc = callPackage ../development/libraries/gcc/libgcc { + gcc = gccCrossLibcStdenv.cc; + glibc = glibcCross.override { libgcc = null; }; + stdenvNoLibs = gccCrossLibcStdenv; + }; }; muslCross = musl.override {