-
-
Notifications
You must be signed in to change notification settings - Fork 13.7k
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: if isPower64, add --with-long-double-64 --without-long-double-128 #170857
Conversation
As explained in the comment, this ensures that stage4-coreutils does not leak a reference to the bootstrap-files by way of libgmp. This will allow the next patch in this series to build stage4-coreutils using a dynamically-linked (rather than statically-linked) libgmp.
The usage of `makeStaticLibraries` in stdenv/linux/default.nix is prefaced by this comment: # Link GCC statically against GMP etc. This makes sense because # these builds of the libraries are only used by GCC, so it # reduces the size of the stdenv closure. However "these builds of the libraries are only used by GCC" is not actually true. As currently written, the stage4 coreutils links against these customized, static-ified libraries. Beside the fact that the code doesn't actually do what it says, this causes other problems as well. One example is #168983, which arises because have a dynamically-linked binary (coreutils) which is built from statically-linked libraries (libgmp.a); doing this causes mayhem on platforms where `-fstack-protector` needs an auxiliary `libssp.{so,a}` library; we end up with link failures because some parts of the resulting binary want `libssp.so` and other parts want `libssp_nonshared.a`. Let's make the code actually do what the comment says, by moving these definitions into the `gcc-unwrapped` override. This will cause the stage4-coreutils to link against libgmp dynamically, rather than statically. For this reason this commit depends on the previous commit, which allows that to be done without creating a forbidden reference from stdenv-final to the bootstrap-files.
During stdenv bootstrapping, coreutils is built twice. This makes troubleshooting very difficult, because both packages have name="coreutils", so it is a hassle to figure out "which coreutils am I using / is not building"? The first of these builds is used only in stage4, and is not part of the final stdenv. Let's label that one with a different `name` attribute to make it obvious which is which.
Co-authored-by: sternenseemann <sternenseemann@systemli.org>
A bug in libgcc which manifests when building static binaries using musl-libc was fixed in gcc 11.1.0, but the fix has not been backported to gcc 10. This commit cherry-picks the commit from upstream and applies it in the case (isPower64 && isMusl) where it matters: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=cda41ce0e8414aec59e6b9fbe645d96e6e8193e2
This commit causes powerpc*-*-gnu to be configured with 64-bit IEEE-compliant `long double` (the same as ordinary `double`) rather than the nonstandard, non-IEEE "IBM double" format from AIX. Support for using only IEEE 128-bit doubles in glibc is not yet ready. This resolves several package test failures caused by weird nonstandard floating-point semantics. It also eliminates a lot of difficulties that arise when using glibc-linked tools to compile for musl-libc and vice versa. There is a long comment included in gcc/common/platform-flags.nix explaining the situation and the reasoning.
@@ -67,6 +67,7 @@ let majorVersion = "10"; | |||
++ optional langAda ../gnat-cflags.patch | |||
++ optional langFortran ../gfortran-driving.patch | |||
++ optional (targetPlatform.libc == "musl" && targetPlatform.isPower) ../ppc-musl.patch | |||
++ optional (targetPlatform.isMusl && targetPlatform.isPower64) ./backport-libgcc-fix-PR97653.patch |
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.
Perhaps it would help to instead default the platform to gcc11? (like x86_64-linux and some others)
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.
I'll try that as soon as my current rebuild-the-world finishes.
However even in that case could we still keep the line above? At least that way if somebody needs gcc10 for some reason it will work.
PS, that line is actually from #170400, which this PR builds on top of. That PR is ready for review and possible merge; this one is still WIP but getting very close.
This is looking really promising. I have verified that with this PR, the tests for I am optimistic that this is going to save us having to scatter a ton of |
Everything rebuilt, and I'm running it now. The only catch is that Other than that, it works. It may take me a while to resolve the glibc issue. Also, I noticed that Has there been any effort put into splitting gcc's two-step bootstrap into two separate derivations? Its build machinery has support for that ( |
I'm not aware of such efforts. I wouldn't expect issues from some parts being built by a bit older compiler. There are many cycles that are hard to avoid among stdenv parts, e.g. also |
I might look into writing a PR for it.
It's only a problem when there is an ABI change without a new multiarch tuple. In theory that should never happen. But this whole IBM long double mess appears to be a possible counterexample. |
So Fedora finally managed to ship a release with IEEE long doubles after attempting six times: this bug is marked CLOSED CURRENTRELEASE. The word on the street is that this stuff simply did not work until glibc 2.35. That would definitely explain the bruise on my head and the damage to my office wall as a result of one being banged against the other. I will revisit this after nixpkgs' glibc upgrades to glibc 2.35 or later. |
This didn't sit well with me, but until now I couldn't articulate why.
I think I found two examples:
Some people will undoubtedly say "oh, 32-bit is so unmodern, nobody cares about that ancient stuff". But:
In both the 32/64-bit case and the ABI case you can always bootstrap a complete nixpkgs using the bootstrap-files you have (e.g. bootstrap a complete 32-bit nixpkgs on a 64-bit processor) and then use that to "cross-compile" your own (e.g. 64-bit) bootstrap-files. So it isn't a major problem. But it is a reason to prefer having the stage2 gcc be compiled entirely by the stage1 gcc, if it were easy to do that. Right now it probably isn't easy. Edit, 2022-Jul-20: @trofi found another one: #181943 (comment) |
Closing in favor of #170215 which is now feasible due to glibc-2.35. |
#### Immediate Benefits - Allow `gcc11` on `aarch64` - No more copying `libgcc_s` out of the bootstrap-files or other derivations - No more [static `lib{mpfr,mpc,gmp,isl}.a` hack](https://github.com/NixOS/nixpkgs/blob/2f1948af9c984ebb82dfd618e67dc949755823e2/pkgs/stdenv/linux/default.nix#L380) - *Zero* additional `gcc` builds (stage1+stage2+stageCompare) - The `gcc` derivation builds `gcc` once instead of three times. - The libraries that are linked into the final `pkgs.gcc` (`mpfr`, `mpc`, `gmp`, `isl`, `glibc`) are built by `stdenv.__bootPkgs.gcc` rather than by the `bootstrapFiles`. No more Frankenstein compiler! - stageCompare runs **concurrently** with (not in series with) with `stdenv`'s dependees. - Many other `stdenv` hacks eliminated. - `gcc` and `clang` share the same codepath for more of `cc-wrapper`. - Makes the cross and native codepaths much more similar -- another step towards "cross by default". Note that *all* the changes in this PR are controlled by flags; no old codepaths need to be removed until/if we're completely certain that this is the right way to go. #### Future Benefits - This should allow using a [foreign] `bootstrap-files` so long as `hostPlatform.canExecute bootstrapFiles`. - There will be an "avalanche of simplification" when we set `enableGccExternalBootstrap=true` and run dead code elimination. It's really quite a huge amount of code that goes away. Native-gcc has its own special codepath in so many places, while cross-gcc and clang work the same way (and are much simpler). - This should allow each of the libraries that ship with `gcc` (`lib{backtrace,atomic,cc1,decnumber,ffi,gomp,iberty,offloadatomic,quadmath,sanitizer,ssp,stdc++-v3,vtv}`) to be built in separate (one-liner) derivations which `inherit src;` from `gcc`. - Building `libstdc++-v3` in a separate derivation will eliminate a lot of accidental-reference-to-the-`bootstrapFiles` landmines. #### Incorporates - NixOS#209054 - NixOS#210004 - NixOS#36948 (unreverted) - NixOS#210325 - NixOS#210118 - NixOS#210132 - NixOS#210109 #### Closes - Closes NixOS#208412 - Closes NixOS#108111 - Closes NixOS#108305 - Closes NixOS#201254 #### Build history - First successful builds (stage1/stage2): - powerpc64le-linux at 9c7e9ef - x86_64-linux at 9c7e9ef - aarch64-linux at 4d5bc7d - First successful comparisons (stageCompare): - at 81949cf - [aarch64-linux][aarch64-compare-ofborg] - [x86\_64-linux][amd64-compare-ofborg] #### Credits This project was made possible by three important insights, none of which were mine: 1. @Ericson2314 was the first to advocate for this change, and probably the first to appreciate its advantages. External bootstrap is "cross by default". 2. @trofi has figured out a lot about how to get gcc to not mix up the copy of `libstdc++` that it depends on with the copy that it builds. Now that gcc is written in C++, it depends on `libstdc++`, builds a copy of `libstdc++`, and builds auxiliary products (like `libplugin`) which depend on `libstdc++`. @trofi developed two important techniques for keeping this straight: the use of a [nonexistent sysroot] and moving the `bootstrapFiles`' `libstdc++` into a [versioned directory]. Without these two discoveries, external bootstrap would be impossible, because the final gcc would still have references to the `bootstrapFiles`. 3. Using the undocumented variable [`user-defined-trusted-dirs`] when building glibc. When glibc `dlopen()`s `libgcc_s.so`, it uses a completely different and totally special set of rules for finding `libgcc_s.so`. This trick is the only way we can put `libgcc_s.so` in its own separate outpath without creating circular dependencies or dependencies on the bootstrapFiles. I would never have guessed to use this (or that it existed!) if it were not for a [comment in guix] which @Mic92 [mentioned]. My own role in this PR was basically: being available to go on a coding binge at an opportune moment, so we wouldn't waste a [crisis]. [aarch64-compare-ofborg]: https://github.com/NixOS/nixpkgs/pull/209870/checks?check_run_id=10662822938 [amd64-compare-ofborg]: https://github.com/NixOS/nixpkgs/pull/209870/checks?check_run_id=10662825857 [nonexistent sysroot]: NixOS#210004 [versioned directory]: NixOS#209054 [`user-defined-trusted-dirs`]: https://sourceware.org/legacy-ml/libc-help/2013-11/msg00026.html [comment in guix]: https://github.com/guix-mirror/guix/blob/5e4ec8218142eee8e6e148e787381a5ef891c5b1/gnu/packages/gcc.scm#L253 [mentioned]: NixOS#210112 (comment) [crisis]: NixOS#108305 [foreign]: NixOS#170857 (comment)
#### Summary By default, when you type `make`, GCC will compile itself three times. This PR inhibits that behavior by configuring GCC with `--disable-bootstrap`, and reimplements the triple-rebuild using Nix rather than `make`/`sh`. #### Immediate Benefits - Allow `gcc11` and `gcc12` on `aarch64` (without needing new `bootstrapFiles`) - Faster stdenv rebuilds: the third compilation of gcc (i.e. stageCompare) is no longer a `drvInput` of the final stdenv. This allows Nix to build stageCompare in parallel with the rest of nixpkgs instead of in series. - No more copying `libgcc_s` out of the bootstrap-files or other derivations - No more Frankenstein compiler: the final gcc and the libraries it links against (mpfr, mpc, isl, glibc) are all built by the same compiler (xgcc) instead of a mixture of the bootstrapFiles' compiler and xgcc. - No more [static lib{mpfr,mpc,gmp,isl}.a hack] - Many other small `stdenv` hacks eliminated - `gcc` and `clang` share the same codepath for more of `cc-wrapper`. #### Future Benefits - This should allow using a [foreign] `bootstrap-files` so long as `hostPlatform.canExecute bootstrapFiles`. - This should allow each of the libraries that ship with `gcc` (lib{backtrace, atomic, cc1, decnumber, ffi, gomp, iberty, offloadatomic, quadmath, sanitizer, ssp, stdc++-v3, vtv}) to be built in separate (one-liner) derivations which `inherit src;` from `gcc`, much like NixOS#132343 #### Incorporates - NixOS#210004 - NixOS#36948 (unreverted) - NixOS#210325 - NixOS#210118 - NixOS#210132 - NixOS#210109 - NixOS#213909 - NixOS#216136 - NixOS#216237 - NixOS#210019 - NixOS#216232 - NixOS#216016 - NixOS#217977 - NixOS#217995 #### Closes - Closes NixOS#108305 - Closes NixOS#108111 - Closes NixOS#201254 - Closes NixOS#208412 #### Credits This project was made possible by three important insights, none of which were mine: 1. @Ericson2314 was the first to advocate for this change, and probably the first to appreciate its advantages. Nix-driven (external) bootstrap is "cross by default". 2. @trofi has figured out a lot about how to get gcc to not mix up the copy of `libstdc++` that it depends on with the copy that it builds, by moving the `bootstrapFiles`' `libstdc++` into a [versioned directory]. This allows a Nix-driven bootstrap of gcc without the final gcc would still having references to the `bootstrapFiles`. 3. Using the undocumented variable [`user-defined-trusted-dirs`] when building glibc. When glibc `dlopen()`s `libgcc_s.so`, it uses a completely different and totally special set of rules for finding `libgcc_s.so`. This trick is the only way we can put `libgcc_s.so` in its own separate outpath without creating circular dependencies or dependencies on the bootstrapFiles. I would never have guessed to use this (or that it existed!) if it were not for a [comment in guix] which @Mic92 [mentioned]. My own role in this PR was basically: being available to go on a coding binge at an opportune moment, so we wouldn't waste a [crisis]. [aarch64-compare-ofborg]: https://github.com/NixOS/nixpkgs/pull/209870/checks?check_run_id=10662822938 [amd64-compare-ofborg]: https://github.com/NixOS/nixpkgs/pull/209870/checks?check_run_id=10662825857 [nonexistent sysroot]: NixOS#210004 [versioned directory]: NixOS#209054 [`user-defined-trusted-dirs`]: https://sourceware.org/legacy-ml/libc-help/2013-11/msg00026.html [comment in guix]: https://github.com/guix-mirror/guix/blob/5e4ec8218142eee8e6e148e787381a5ef891c5b1/gnu/packages/gcc.scm#L253 [mentioned]: NixOS#210112 (comment) [crisis]: NixOS#108305 [foreign]: NixOS#170857 (comment) [static lib{mpfr,mpc,gmp,isl}.a hack]: https://github.com/NixOS/nixpkgs/blob/2f1948af9c984ebb82dfd618e67dc949755823e2/pkgs/stdenv/linux/default.nix#L380
Description of changes
Only the final commit is unique to this PR.
Reviewers: pleases click "Commits" then click the last commit in order to see the diff. All the other commits are part of PRs which will (I would hope) merge before this one: #169378 (first five commits) and #170400 (second-to-last commit).
Description of changes
This commit causes
powerpc*-*-gnu
to be configured with 64-bitlong double
(the same as ordinarydouble
) rather than the nonstandard, non-IEEE "IBM double" format from AIX.This hopefully resolves a large number of package test failures caused by weird nonstandard floating-point semantics.
There is a rather long comment included in gcc/common/platform-flags.nix explaining the situation and the reasoning. I will move that into the commit message as this PR gets closer to mergeability.
Background
This is a continuation of the work in #170402, which I don't seem to be able to reopen even though I closed it (I guess you can only reopen self-closed bugs, not PRs?).
I think we have a working combination here, and
pkgsStatic
now interacts correctly with the rest of nixpkgs, the way it does on arm64 and x86, with no weird link failures. Still marked as draft while I finish rebuilding the world and use this for a while on my workstation.Notes to be integrated into final commit message
The "fat binary" scheme is called a GNU IFUNC.
Here is where glibc says that it won't let you build it without AIX 128-bit long-doubles unless you also give up IEEE 128-bit long-doubles. To have only one long-double and have it be IEEE, glibc insists you use 64-bit long-doubles. I'm starting to understand why the musl people are so insistent about not wanting anything to do with this...
Things done
nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)