Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gcc: don't use old cross-compiler build a new native compiler #249301

Closed
wants to merge 10 commits into from
10 changes: 9 additions & 1 deletion pkgs/development/compilers/gcc/common/builder.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,15 @@ let
in

originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
passthru = (originalAttrs.passthru or {}) // { inherit forceLibgccToBuildCrtStuff; };
passthru = let
target_libc = if finalAttrs.withoutTargetLibc then null
else if finalAttrs.finalPackage.libcCross != null
then finalAttrs.finalPackage.libcCross
else finalAttrs.finalPackage.stdenv.cc.libc;
target_libgcc = target_libc.passthru.libgcc or null;
in (originalAttrs.passthru or {}) // {
inherit forceLibgccToBuildCrtStuff target_libc target_libgcc;
};
preUnpack = ''
oldOpts="$(shopt -po nounset)" || true
set -euo pipefail
Expand Down
20 changes: 20 additions & 0 deletions pkgs/development/compilers/gcc/common/libgcc.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,26 @@ drv: lib.pipe drv

([

# Check that the version of GCC exactly matches the version of
# libgcc (if any) used to build its target-glibc. For an example
# of the problems that occur if this happens, see
# https://github.com/NixOS/nixpkgs/issues/244871
(pkg: pkg.overrideAttrs (finalAttrs: previousAttrs: {

# We put the assertion on the `meta` attribute to ensure that
# we can examine `finalAttrs` without creating any infinite
# recursions. The meta checks (even the non-recursive ones)
# will force this assertion.
meta = let
inherit (finalAttrs) finalPackage;
inherit (finalPackage.passthru) target_libc target_libgcc;
in
assert (finalPackage.version != target_libgcc.version or finalPackage.version)
-> throw
"${finalPackage.name} version does not match target libgcc version ${target_libgcc.name} (from target libc ${target_libc.name})";
previousAttrs.meta;
}))

(pkg: pkg.overrideAttrs (previousAttrs:
lib.optionalAttrs (
targetPlatform != hostPlatform &&
Expand Down
6 changes: 6 additions & 0 deletions pkgs/development/libraries/gcc/libgcc/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,10 @@ in stdenv.mkDerivation (finalAttrs: {
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/"
'';

meta =
assert !stdenv.cc.cc.isGNU -> throw "you must use GCC to compile libgcc";
assert (stdenv.cc.cc.version != finalAttrs.finalPackage.version)
-> throw "you tried to use ${stdenv.cc.cc.name} (${stdenv.cc.cc}) to compile ${finalAttrs.finalPackage.name}";
{ };
})
73 changes: 55 additions & 18 deletions pkgs/top-level/all-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15597,14 +15597,15 @@ with pkgs;

gbforth = callPackage ../development/compilers/gbforth { };

inherit (let
num =
if (with stdenv.targetPlatform; isVc4 || libc == "relibc") then 6
else 12;
numS = toString num;
in {
gcc = pkgs.${"gcc${numS}"};
gccFun = callPackage (../development/compilers/gcc + "/${numS}");
default-gcc-version =
if (with stdenv.targetPlatform; isVc4 || libc == "relibc") then 6
else 12;
inherit ({
gcc = pkgs.${"gcc${toString default-gcc-version}"};
gccFun =
callPackage
({ gcc_major_version }: callPackage (../development/compilers/gcc + "/${gcc_major_version}"))
{ gcc_major_version = toString default-gcc-version; };
}) gcc gccFun;
gcc-unwrapped = gcc.cc;

Expand Down Expand Up @@ -15699,10 +15700,10 @@ with pkgs;

# The GCC used to build libc for the target platform. Normal gccs will be
# built with, and use, that cross-compiled libc.
gccWithoutTargetLibc = assert stdenv.targetPlatform != stdenv.hostPlatform; let
libcCross1 = binutilsNoLibc.libc;
in wrapCCWith {
cc = gccFun {
gccWithoutTargetLibc =
assert stdenv.targetPlatform != stdenv.buildPlatform;
callPackage ({ gcc_major_version }: wrapCCWith {
cc = (gccFun.override { inherit gcc_major_version; }) {
# copy-pasted
inherit noSysDirs;

Expand All @@ -15713,7 +15714,7 @@ with pkgs;

withoutTargetLibc = true;
langCC = false;
libcCross = libcCross1;
libcCross = binutilsNoLibc.libc;
targetPackages.stdenv.cc.bintools = binutilsNoLibc;
enableShared =
stdenv.targetPlatform.hasSharedLibraries
Expand All @@ -15725,17 +15726,17 @@ with pkgs;
;
};
bintools = binutilsNoLibc;
libc = libcCross1;
libc = binutilsNoLibc.libc;
extraPackages = [];
};
}) { gcc_major_version = toString default-gcc-version; };

# This expression will be pushed into pkgs/development/compilers/gcc/common
# once the top-level gcc/${version}/default.nix files are deduplicated.
inherit
(lib.listToAttrs (map (version:
let atLeast = lib.versionAtLeast version;
attrName = "gcc${lib.replaceStrings ["."] [""] version}";
pkg = lowPrio (wrapCC (callPackage (../development/compilers/gcc + "/${version}") ({
pkg = (callPackage (../development/compilers/gcc + "/${version}") ({
inherit noSysDirs;
reproducibleBuild = true;
profiledCompiler = false;
Expand All @@ -15760,8 +15761,44 @@ with pkgs;
} // lib.optionalAttrs (atLeast "6" && !(atLeast "9")) {
# gcc 10 is too strict to cross compile gcc <= 8
stdenv = if (stdenv.targetPlatform != stdenv.buildPlatform) && stdenv.cc.isGNU then gcc7Stdenv else stdenv;
})));
in lib.nameValuePair attrName pkg

})).override (previousArgs:
let
inherit (previousArgs) stdenv libcCross;
in lib.optionalAttrs (!stdenv.buildPlatform.canExecute stdenv.targetPlatform &&
libcCross != null &&
(lib.versionOlder libcCross.passthru.libgcc.version version ||
lib.versionOlder stdenv.cc.cc.version version))
# The conditional above checks for the following situation: we are cross-building a
# native compiler (build!=(host==target)) using a cross-compiler ((build==host)!=target)
# which is *older than* the compiler being built. We check both the cross-compiler
# itself as well as the cross-compiler which was used to build the copy of libgcc
# against which the target libc is linked.
#
# This configuration often fails (see https://github.com/NixOS/nixpkgs/issues/244871 for
# one example). If you need to cross-build a newer-than-default-gcc-version native
# compiler, you must first build a newer-than-default-gcc-version cross-compiler. The
# code below does that automatically.
(let
gcc = wrapCCWith {
cc = (pkgsHostTarget.gccWithoutTargetLibc.override {
gcc_major_version = version;
}).cc;
bintools = binutilsNoLibc;
libc = binutilsNoLibc.libc;
extraPackages = [];
};
libcCross' = libcCross.override (previousArgs: {
libgcc = previousArgs.libgcc.override (previousArgs: {
glibc = libcCross'.override { libgcc = null; };
stdenvNoLibs = overrideCC previousArgs.stdenvNoLibs gcc;
inherit gcc;
});
});
in {
libcCross = libcCross';
}));
in lib.nameValuePair attrName (lowPrio (wrapCC pkg))
) [ "4.8" "4.9" "6" "7" "8" "9" "10" "11" "12" "13" ]))
gcc48 gcc49 gcc6 gcc7 gcc8 gcc9 gcc10 gcc11 gcc12 gcc13;

Expand Down