### 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]: 7553d0fe29/pkgs/development/libraries/glibc/default.nix (L69-L88)
This commit restores the pkgs/development/libraries/gcc/libgcc
package, which was deleted by commit 9818d120be.
We need to be able to build libgcc separately from gcc in order to
avoid a circular dependency. Nixpkgs is unusual -- unlike any other
distribution, it cannot tolerate circular dependencies between
dynamically linked libraries. Because of this, upstream is
extremely unsympathetic to the trouble that the glibc<->gcc circular
dependency causes for us; if we don't solve it ourselves it will not
be solved.
1. Set cutterPlugins to cutter.plugins rather than rizin.plugins which
it was set to by mistake
2. Remove Rizin binaries from Cutter wrapper, because they aren't
actually used by Cutter and if the user needs those binaries they
should install Rizin separately