-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
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: do not allow version skew when cross-building gcc #352821
Conversation
Tested builds successfully on:
|
Rebuild counts are low:
|
|
# | ||
# Let's fix both problems by requiring the same compiler version for | ||
# cross-case. | ||
stdenv = if (stdenv.targetPlatform != stdenv.buildPlatform) && stdenv.cc.isGNU then pkgs."gcc${majorVersion}Stdenv" else stdenv; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think there’s a way to make it viable to do this as an assertion on the version instead, and wire things up so that the correct stdenv
is used by default in all-packages.nix
or similar? It seems like this would silently eat overridden stdenv
s for cross‐compilers, which seems a little sad.
(And: We seem to build cross GCCs with Clang without issue on Darwin, is that just us getting lucky?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think there’s a way to make it viable to do this as an assertion on the version instead, and wire things up so that the correct stdenv is used by default in all-packages.nix or similar? It seems like this would silently eat overridden stdenvs for cross‐compilers, which seems a little sad.
I would prefer not to fiddle with asserts (they would need to be not just version-specific, but probably target-specific as well to avoid mixing cross vs native --build
gcc
, which is so easy to get wrong when passing things explicitly in all-packages.nix
).
Note that current all-packages.nix
is this entry:
inherit (callPackage ../development/compilers/gcc/all.nix { inherit noSysDirs; })
gcc7 gcc8 gcc9 gcc10 gcc11 gcc12 gcc13 gcc14;
It's not easy to inject version-specific overrides here.
(And: We seem to build cross GCCs with Clang without issue on Darwin, is that just us getting lucky?)
My guess is that gcc
is present somewhere in the closure and it happens to work most of the time. Having said that pkgsCross.aarch64-multiplatform.gcc14
fails on x86_64-darwin
for me (just like on x86_64-linux
):
aarch64-unknown-linux-gnu-g++: error: unrecognized command-line option '-std=gnu++26'; did you mean '-std=gnu++20'?
It clearly pulls gcc13
's cross-compiler from somewhere to build gcc-14
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, makes sense to me. Wouldn’t the stdenv.cc.isGNU
case here break compiling GCC in a Clang‐based cross setting though? I’m probably just mixing up my offsets…
(BTW, I think callPackages
would be correct for this, and would allow overrides.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least by default gcc
is used for cross-compilers on darwin
.
$ nix eval --impure --expr 'with import ./. { system = "x86_64-darwin"; }; stdenv.cc.isGNU'
false
$ nix eval --impure --expr 'with import ./. { system = "x86_64-darwin"; }; pkgsCross.aarch64-multiplatform.stdenv.cc.isGNU'
true
$ nix eval --impure --expr 'with import ./. { system = "x86_64-darwin"; }; pkgsCross.aarch64-multiplatform.stdenv.cc'
«derivation /nix/store/3zr6clbyvsyi649073qlnxnjaa881xgw-aarch64-unknown-linux-gnu-gcc-wrapper-13.3.0.drv»
Looking at https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/cross/default.nix#L83 my guess is that nixpkgs
only uses clang
when it targets darwin
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Maybe pkgsLLVM
could mess things up, but it’s probably an edge case. I’m happy to trust that you’ve thought this through better than I have.
028da88
to
46401d0
Compare
Rebased past |
Sorry about that! This looks good to me and I’m happy to merge after eval. Do you know if the case where |
Yes, I think it's problematic. I'm not sure if |
Would expanding the condition to |
When `gcc` is cross-built (`build` != `target` && `host` == `target`) `gcc` assumes that it has a compatible cross-compiler in the environment that can build target libraries. Version of a cross-compiler has to match the compiler being cross-built as libraries frequently use fresh compiler features, like `-std=c++26` or target-specific types like `_Bfloat16`. Version mismatch causes build failures like: NixOS#351905 Similar problems (but on a smaller scale) happen when a `gcc` cross-compiler is built (`build` == `host` && `host` != `target`) built by a mismatching version of a native compiler (`build` == `host` && `host` == `target`). That was worked around by forcing `gcc9Stdenv` for older compiler versions. Let's fix both problems by requiring the same compiler version for cross-case. Closes: NixOS#351905
46401d0
to
9047491
Compare
Switched to --- a/pkgs/development/compilers/gcc/all.nix
+++ b/pkgs/development/compilers/gcc/all.nix
@@ -42,7 +42,7 @@ let
#
# Let's fix both problems by requiring the same compiler version for
# cross-case.
- stdenv = if (stdenv.targetPlatform != stdenv.buildPlatform) && stdenv.cc.isGNU then pkgs."gcc${majorVersion}Stdenv" else stdenv;
+ stdenv = if (stdenv.targetPlatform != stdenv.buildPlatform || stdenv.hostPlatform != stdenv.targetPlatform) && stdenv.cc.isGNU then pkgs."gcc${majorVersion}Stdenv" else stdenv;
}));
in
lib.nameValuePair attrName pkg; |
When
gcc
is cross-built (build
!=target
&&host
==target
)gcc
assumes that it has a compatible cross-compiler in the environment that can build target libraries. Version of a cross-compiler has to match the compiler being cross-built as libraries frequently use fresh compiler features, like-std=c++26
or target-specific types like_Bfloat16
.Version mismatch causes build failures like:
Similar problems (but on a smaller scale) happen when a
gcc
cross-compiler is built (build
==host
&&host
!=target
) built by a mismatching version of a native compiler (build
==host
&&host
==target
). That was worked around by forcinggcc9Stdenv
for older compiler versions.Let's fix both problems by requiring the same compiler version for cross-case.
Closes: #351905
Things done
nix.conf
? (See Nix manual)sandbox = relaxed
sandbox = true
nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)Add a 👍 reaction to pull requests you find important.