-
Notifications
You must be signed in to change notification settings - Fork 15k
Description
This is responding to the conversation in #125922, but I am opening a new issue because I would like to disentangle the larger idea from that specific PR.
They way some us Nixpkgs compiler maintainers see it, the ideal bootstrap order is:
- Build "true builtins", completely self-contained
- Build libc
- Build any additional "pseudo-builtins" depending on libc, without rebuilding the "true builtins"
- Build additional goodies like sanitizers
To wit, if the builtins and libc are really cyclic, then all sorts of accidental recursion is possible (imagine emutls
eventually recurring back into emutls
). On the flip side, if no recursion is happening, then the cyclic dep is in fact spurious and the acyclic dependency order already exists and is just waiting to "break free".
Yes, the circular dep is common, but it strikes as a more a historical accident that something anyone would want on purpose.
(For reference. Another such historical accident is building all of GCC twice, once without libc, once with. That is obviously overkill, and people rigged up things like https://github.com/richfelker/musl-cross-make to avoid it. LLVM doesn't engage in such folly, making it easy to build compiler-rt and clang separately. I think if we do disentangle this circle dep, the old "use libc headers" will be looked back upon in hindsight as just as silly.)
BTW, this sort of disentangling would also be good for Rust. Their "compiler builtins" package with bits of compiler-rt when doing a freestanding or WASM (without WASI at least) build ought not to depend on any libc, not even a newlib
.
Getting down to brass tacks:
-
Stuff like
emutls
feels to be like clearly a "pseudo-builtins", it fallback logic in non-trivial software. -
The builtins that use
getauxval
are a bit trickier. Can we skip them entirely in the first "true builtins" step? Unclear. And so you want to use features depending on hardware detection in freestanding code? Not sure what the right solution is, but ideally there is some interface that is amendable to OS-leveraging and freestanding approach, and it is more defined than "whatever in libc we happen to use".