mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-12-18 11:44:07 +00:00
64046f0191
### Summary
This PR completely and finally solves the gcc<->glibc circular
`buildInputs` problem, for cross compilation. The same technique
can be applied to native builds in the future.
Closes #213453
### Motivation
Prior to this PR, we had the following circular `buildInputs` problem:
1. gcc has glibc in its `buildInputs`
- a compiled copy of glibc must be present before building gcc;
if it isn't, gcc cripples itself (`inhibit_libc`) and refuses
to build libgcc_s.so
2. glibc has libgcc_s.so in its `buildInputs`
- glibc `dlopen()`s libgcc_s.so in order to implement POSIX
thread cancellation. For security reasons `glibc` requires
that the path to `libgcc_s.so` is [hardwired] into `glibc` at
compile time, so it's technically not a true dynamic link -- it
just pretends to be one.
3. libgcc_s.so is built in the same derivation as gcc
- libgcc_s.so is built as part of the gcc build process
We must cut one of these three links in the loop.
### Previous Attempts
Previously https://github.com/NixOS/nixpkgs/pull/238154 had
attempted to cut link (1) by building `gcc` without `glibc`, and
using the `libgcc_s` which emerges from that build. Unfortunately
this just doesn't work. GCC's configure script extracts quite a lot
of information from the glibc headers (which are a build artifact --
you can't just copy them out of the source tarball) and various
`./configure`-driven linking attempts. If `glibc` isn't around at
build time you wind up with a `libgcc_s.so` that is missing various
unwinder features (see https://github.com/NixOS/nixpkgs/issues/213453
for the most problematic one).
Musl "cuts" link (2), or rather never creates it in the first place.
["Cancellation cleanup handling in musl has no relationship to C++
exceptions and unwinding... glibc implements cancellation as an
exception"](https://wiki.musl-libc.org/functional-differences-from-glibc.html#Thread-cancellation).
IMHO Musl made the smarter decision here. It is incredibly rare to
find a codebase that uses both POSIX thread cancellation *and* C++
exceptions. I have never seen a codebase that uses both *and*
expects them to be aware of each other, and I would be astonished if
one existed. Glibc paid an immense cost in complexity for something
nobody has ever used.
### Changes Made
This PR cuts link (3): instead of building libgcc_s.so as part of
gcc, we build it separately from gcc. Now there is a strict acyclic
graph of `buildInputs`:
```
gccWithoutTargetLibc
|
+--->glibc-nolibgcc
| |
| v
+--->libgcc
| |
| v
+--->glibc
| |
| v
+--->gcc
```
In other words, there's a simple linear `buildInputs` chain
`glibc-nolibgcc` `->` `libgcc` `->` `glibc` `->` `gcc` where all
four packages are compiled by (and therefore have as a
`(native)BuildInput`) `gccWithoutTargetLibc`.
`gccWithoutTargetLibc` and `glibc-nolibgcc` are strictly
bootstrapping artifacts; nothing else has them as a `buildInput` and
they shouldn't appear in the closure of any final deployment
packages. `glibc-nolibgcc` lacks `libgcc_s.so`, so it will segfault
if you try to use it with POSIX thread cancellation. Fortunately
all we need from it is (a) its headers (`lib.getDev`) and (b) to use
it in the `./configure` script for `libgcc`.
When translated over to the native bootstrap, `xgcc` takes the place
of `gccWithoutTargetLibc`, and the "first `glibc`" (we build two of
them) takes the place of `glibc-nolibgcc`. At that point our native
and cross bootstrap have the same overall architecture, and it
becomes possible to merge them (at last!)
[213453]: https://github.com/NixOS/nixpkgs/issues/213453
[238154]: https://github.com/NixOS/nixpkgs/pull/238154
[hardwired]:
|
||
---|---|---|
.. | ||
2.37-master.patch.gz | ||
0001-Revert-Remove-all-usage-of-BASH-or-BASH-in-installed.patch | ||
common.nix | ||
darwin-cross-build.patch | ||
default.nix | ||
dont-use-system-ld-so-cache.patch | ||
dont-use-system-ld-so-preload.patch | ||
fix_path_attribute_in_getconf.patch | ||
fix-rpc-types-musl-conflicts.patch | ||
fix-x64-abi.patch | ||
info.nix | ||
locales-builder.sh | ||
locales.nix | ||
mtrace.nix | ||
multi.nix | ||
nix-locale-archive.patch | ||
nix-nss-open-files.patch | ||
reenable_DT_HASH.patch | ||
rpcgen-path.patch |