diff --git a/docs/README.md b/docs/README.md index fa6dd67a9a..eb37cdb6a5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -90,6 +90,7 @@ Do not flatten those into one “supported” claim in public summaries. - `../local/docs/SCRIPT-BEHAVIOR-MATRIX.md` — what the main sync/fetch/apply/build scripts do and do not guarantee - `../local/docs/FORK-BUMP-PATCHING-POLICY.md` — delicate patching during a version or toolchain bump (a bump is a rebase, never a replacement) +- `../local/docs/NATIVE-TOOLCHAIN-WORKSTREAM.md` — gcc-native/rust-native: deferred workstream, findings and re-enable procedure ## Current State Summary (as of 2026-07-18) diff --git a/local/docs/NATIVE-TOOLCHAIN-WORKSTREAM.md b/local/docs/NATIVE-TOOLCHAIN-WORKSTREAM.md new file mode 100644 index 0000000000..729dea9d81 --- /dev/null +++ b/local/docs/NATIVE-TOOLCHAIN-WORKSTREAM.md @@ -0,0 +1,162 @@ +# Native Toolchain Workstream — `gcc-native` / `rust-native` + +**Status:** DEFERRED. Explicit operator decision, 2026-08-03: *"Treat +gcc-native/rust-native as a separate workstream, explicitly deferred by me, for +now."* +**Scope:** `local/recipes/dev/gcc-native/`, `local/recipes/dev/rust-native/`. +**Not deferred:** `binutils-native` and `llvm-native` build and remain in +`config/redbear-full.toml`. `llvm-native` is **required**, not optional — it +supplies the host LLVM dev tree that `libclc` and Mesa's iris/radeonsi CLC path +consume. + +Related: `local/patches/gcc-redox-port/README.md`, +`VENDORED-LIBC-FORK.md`, `FORK-BUMP-PATCHING-POLICY.md`, +`LOCAL-FORK-SUPREMACY-POLICY.md`. + +--- + +## What this workstream is + +A toolchain that **runs on Redox** and targets Redox — `gcc`, `cargo`/`rustc` +executing inside the OS. Distinct from the **cross** toolchain in `prefix/`, +which runs on the Linux host and is what actually builds the distribution. + +That distinction matters for prioritisation: the cross toolchain is **done** +(GCC 16.1.0, `libstdc++.so.6.0.35`, working `std::ranges::to`) and is what +compiled every other package. Nothing in the desktop path — Mesa/virgl, +Wayland, Qt6, KF6, SDDM — depends on the native toolchain. + +## Why it is deferred, honestly + +Not because it is unimportant, and **not** for the reason the old config gave. + +The previous exclusion said *"suppressed: Redox C++/pthread header gaps; not +needed for greeter proof"*. That was wrong on both counts. `llvm-native` has no +header gap at all — it cooks clean in isolation, and only failed in parallel +builds because of a cookbook race on shared staging paths (fixed; see +`src/bin/repo.rs` `recipe_dir_lock`). A real build-system bug had been +misdiagnosed as a porting gap and used to justify excluding a required package. +Restoring these packages is how the twelve defects below were found at all — +including that `redbear-iwlwifi` had never compiled since the commit that broke +it. + +The deferral is instead a scope judgement: making GCC build *itself* for Redox +is a genuine porting project. Upstream Redox has only ever shipped GCC 8.2.0 +and 13.2.0; nobody has done GCC 16 for this target. Every fix so far has +revealed the next layer, and the remaining failures are header-model conflicts +(GCC's internal headers vs relibc's, host vs target) that want someone working +through GCC's cross-build header model as a whole rather than patching +incrementally. + +## `gcc-native` — moved to GCC 16, twelve findings + +The recipe now builds **GCC 16.1.0** from `local/recipes/dev/gcc16/source` +(upstream 16.1.0 + `local/patches/gcc-redox-port/`), not GCC 13. + +### Why the move happened + +Building GCC 13 with the GCC 16 cross compiler is three major versions of +drift and is not a supported configuration. Three fixes landed before it became +untenable: + +| # | Defect | Resolution | +|---|---|---| +| 1 | `char8_t`. GCC 16 defaults to C++20, which changed `u8""` from `const char[]` to `const char8_t[]`; libcody uses them throughout (~100 diagnostics) | pin the C++ standard | +| 2 | libcody's configure contains `#if __cplusplus > 201103` / `#error "C++11 is required"` — it rejects anything *newer* than C++11 | `-std=gnu++11`, which also fixes #1 (no `char8_t` before C++20) | +| 3 | `bit_AVX512PF` / `ER` / `4VNNIW` / `4FMAPS` / `PREFETCHWT1` undeclared — GCC 15/16 **removed** these macros for withdrawn ISA extensions, but GCC 13's `cpuinfo.h` needs them | put GCC 13's own `cpuid.h` ahead of the toolchain's include path | + +Then GCC 16 **ICEd** compiling GCC 13's own libstdc++: + +``` +libstdc++-v3/libsupc++/eh_call.cc:39:1: internal compiler error: +in gimple_build_eh_must_not_throw +``` + +An ICE is where flag-tweaking stops being a legitimate answer. Those three +fixes remain in `recipes/dev/gcc13/recipe.toml` — that recipe still builds the +GCC 13 cross toolchain and they are correct there. + +### After the move to GCC 16 + +| # | Defect | Resolution | +|---|---|---| +| 4 | The `same_as` symlink `source -> recipes/dev/gcc13/source` survived the recipe edit, so the "GCC 16" build was still compiling GCC 13 sources | removed; now `-> ../gcc16/source` | +| 5 | `gcc13` / `gcc13.cxx` dependencies build the very compiler being replaced | dropped | +| 6 | `unknown type name 'bool'` — GCC 16's sources are C23, where `bool` is a keyword, but the cookbook pins `-std=gnu17` tree-wide for the C17-era recipes | exempt this recipe from the pin | +| 7 | `cannot guess version` — `same_as` used to supply it; a `path` source gives the cookbook nothing to infer from | explicit `[package].version` | +| 8 | `'fenv_t' has not been declared in '::'` — dropping `gcc13` also removed what *transitively* staged relibc's headers, leaving the sysroot with **no libc headers at all** | explicit `relibc` dependency | +| 9 | `_getopt_internal` undeclared — libiberty needs GCC's own `include/getopt.h`, which declares that GNU-internal symbol; relibc's `getopt.h` was shadowing it | GCC's `include/` ahead of the sysroot | +| 10 | `FNM_FILE_NAME` / `FNM_LEADING_DIR` undeclared — GNU extensions genuinely absent from relibc | **implemented in the relibc fork** (see below) | + +### Correction worth preserving + +Finding #8 was **initially misdiagnosed** as "relibc's `fenv.h` is a 3-line +stub". It is not. relibc's `fenv.h` correctly delegates to `openlibm_fenv.h`, +which dispatches on `__x86_64__` to `openlibm_fenv_amd64.h` where `fenv_t` +(line 48) and `fexcept_t` (line 50) are both defined — and relibc stages all of +those headers. The header was simply never reaching this recipe's sysroot. A +commit message asserting a relibc fenv gap was wrong and is corrected in the +commit that follows it. + +The lesson generalises to most of this list: **an "undeclared identifier" +against relibc is more often a header-path problem than a missing +implementation.** Check whether the header reaches the compiler before +concluding relibc is incomplete. + +### Real relibc gap that was fixed + +`FNM_FILE_NAME` and `FNM_LEADING_DIR` are now implemented in +`local/sources/relibc/src/header/fnmatch/mod.rs` (pushed on +`submodule/relibc`). `FNM_FILE_NAME` is the GNU synonym for `FNM_PATHNAME`, so +an alias. `FNM_LEADING_DIR` is real behaviour — the pattern may match a leading +directory, so `foo` matches `foo/bar` — implemented by trying the exact match +then each prefix ending before a `/`. Declaring the flag without honouring it +would have been a stub. Its value (16) is the next free bit in **relibc's own** +numbering, not glibc's. + +### Where it stopped + +``` +/usr/include/c++/16/x86_64-pc-linux-gnu/bits/os_defines.h:44: +error: missing binary operator before token '(' +``` + +The **host's** libstdc++ headers are being pulled into a target compile — +`__GLIBC_PREREQ` evaluated where there is no glibc. A host/target header leak, +and the natural next thing to investigate. + +## `rust-native` — four findings, one open + +| # | Defect | Resolution | +|---|---|---| +| 1 | `nix 0.30.1` incompatible with libc 0.2.178: declares `SaFlags_t = c_ulong` while libc has `sa_flags`/`SA_*` as `c_int` (`E0308` both directions) | nix 0.31 fixed it; `ctrlc` 3.5 requires nix `"0.31"` | +| 2 | in-tree `miri` pinned `nix = "0.30.1"` and held the broken version in the graph | bumped; carried as `local/patches/rust/01-miri-nix-0.31.patch` | +| 3 | `CLD_EXITED` / `P_ALL` etc. not in crate `libc` — its **Redox bindings** never exposed the `waitid` surface relibc implements, still absent in 0.2.189 | vendored fork, see `VENDORED-LIBC-FORK.md` | +| 4 | `llvm/Config/llvm-config.h: No such file` — `llvm-native.dev` (which stages the headers) missing from dependencies | added | + +**Open:** five `error: unreachable 'pub' item` diagnostics, crate not yet +identified. Not investigated. + +## Re-enabling + +The recipes are **fixed and committed, not reverted**. To resume: + +1. In `config/redbear-full.toml`, change `gcc-native = "ignore"` and + `rust-native = "ignore"` back to `= {}`. +2. `./local/scripts/build-redbear.sh --upstream redbear-full`. +3. Expect to resume at the host/libstdc++ header leak above. + +Diagnose failures **in isolation** — `COOKBOOK_COOK_JOBS=1 ./target/release/repo +cook `. The aggregate build multiplexes output from parallel cooks, and +several wrong turns in this workstream came from attributing one recipe's error +to another in the interleaved log. + +## Upstream-reportable + +Two findings belong upstream rather than in Red Bear indefinitely: + +- The `libc` crate's Redox module lacks the `waitid` surface (`idtype_t`, + `P_*`, `CLD_*`, `waitid`) that relibc implements. Retirement procedure in + `VENDORED-LIBC-FORK.md`. +- relibc's missing GNU `fnmatch` extensions — now fixed in the fork, and worth + offering upstream.