Operator decision 2026-08-05: "we will not have gcc 13." The cross toolchain has been GCC 16.1.0 since the port landed, but the build system still defaulted to GCC 13 in three places and nothing recorded the move. Build system: - mk/prefix.mk: GCC_RECIPE?=gcc13 -> gcc16. - mk/prefix.mk: the HOSTED_REDOX package rule derives its names from $(GCC_RECIPE) instead of hardcoding gcc13.pkgar / gcc13.cxx.pkgar. static.redox-os.org publishes no gcc16 package, so that path now fails at download. Deliberate: a loud failure beats a wrong compiler. - build-redbear.sh: refuse to build on a non-GCC-16 toolchain. This is the one that mattered on a Linux host. `make prefix` unpacks upstream's gcc-install.tar.gz, which IS GCC 13.2.0, and no make rule replaces it -- GCC 16 arrives only via install-gcc16-toolchain.sh. A fresh prefix therefore put you silently back on GCC 13, surfacing ~40 minutes later as a kwin C++23 failure. The guard checks all three locations (gcc-install, sysroot, ~/.redoxer/<target>/toolchain -- the last has highest priority) and names the two scripts to run. Docs: - New local/docs/TOOLCHAIN-GCC16.md: why the move (kwin/plasma-workspace need std::ranges::to), build/install/rollback procedure, the three locations that must agree, the tree-wide -std=gnu17 and -fno-hardened consequences, and the open libstdc++ float16-formatter gap that currently blocks the kwin link. - CHANGELOG, docs/README.md index and state summary, and the stale claim in NATIVE-TOOLCHAIN-WORKSTREAM.md that gcc13 "still builds the GCC 13 cross toolchain". Also corrects stale references found while auditing: - AGENTS.md described prefix/ as "Clang/LLVM"; it is GCC 16.1.0 + LLVM + Rust. - AGENTS.md cited local/reference/linux-7.0/ (tree is linux-7.1). - AGENTS.md's durable-patching example cited a mesa patch that does not exist; replaced with one wired in recipe.toml. (The first replacement used patch 03, which the changelog records as orphaned -- it targets a file removed from Mesa 26.1.4 upstream.) native_bootstrap.sh still installs gcc13/gcc13.cxx packages inside a Redox VM. Left alone: that is the deferred gcc-native workstream and no gcc16 package is published for Redox to point it at. Verified: bash -n clean; make -n prefix parses; guard accepts the current 16.1.0 toolchain in all three locations and rejects a stubbed 13.2.0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.1 KiB
Cross Toolchain — GCC 13.2.0 → GCC 16.1.0
Status: DONE. The cross toolchain in prefix/ is GCC 16.1.0 and is what
compiled every package in the current tree.
Scope: the cross toolchain (runs on the Linux host, targets
x86_64-unknown-redox). The native toolchain — a compiler that runs on
Redox — is a separate, explicitly deferred workstream; see
NATIVE-TOOLCHAIN-WORKSTREAM.md.
Related: local/patches/gcc-redox-port/README.md (the Redox target port
itself), FORK-BUMP-PATCHING-POLICY.md (a bump is a rebase, never a
replacement), BUILD-SYSTEM-INVARIANTS.md.
Why the move happened
kwin and plasma-workspace both declare CMAKE_CXX_STANDARD 23 and both use
std::ranges::to. GCC 13.2.0 — the prebuilt compiler Redox upstream ships from
static.redox-os.org — does not have it ('to' is not a member of 'std::ranges'). There is no way to reach a KDE Plasma desktop on GCC 13, so
the compiler had to move. Upstream Redox has only ever shipped GCC 8.2.0 and
13.2.0; GCC 16 for this target is Red Bear's own port.
What the toolchain is now
| Version | GCC 16.1.0 (local/recipes/dev/gcc16/source/gcc/BASE-VER) |
| Target | x86_64-unknown-redox, built on x86_64-pc-linux-gnu |
| Languages | c, c++, lto |
| libstdc++ | libstdc++.so.6.0.35 |
| Source | local/recipes/dev/gcc16/source + local/patches/gcc-redox-port/ |
| Replaces | GCC 13.2.0 (prebuilt, downloaded from static.redox-os.org) |
Verify:
prefix/x86_64-unknown-redox/gcc-install/bin/x86_64-unknown-redox-gcc --version
# x86_64-unknown-redox-gcc (GCC) 16.1.0
How it is built and installed
Two scripts, run in order. Neither goes through the cookbook — see "What is still on GCC 13" below for why.
# 1. Build (~40 min). Configure flags mirror the cross arm of
# recipes/dev/gcc13/recipe.toml, so the result is configured like the
# compiler it replaces. Output: build/gcc16-install/
local/scripts/build-gcc16-cross.sh
# 2. Install over GCC 13 in all three locations the build reads from.
local/scripts/install-gcc16-toolchain.sh
The build script refuses to start unless the Redox port is actually applied to
the source — it greps for a redox arm in both gcc/config.gcc and
libstdc++-v3/configure. Without that guard a missing port surfaces only at
the end of a 40-minute build, as a compiler with no Redox target.
To apply the port to a fresh GCC 16 source tree:
python3 local/patches/gcc-redox-port/apply-redox-port.py local/recipes/dev/gcc16/source
# then regenerate libstdc++-v3/configure with autoconf 2.69
The three locations must agree
This is the part that bites. A compiler is read from three places, and the last one wins:
prefix/<target>/gcc-install/— the GCC half of the prefixprefix/<target>/sysroot/— the merged prefix (gcc + rust + clang)~/.redoxer/<target>/toolchain/— highest priority;src/cook/script.rsprepends it toPATHlast, so it wins over both prefix paths for every recipe
Updating only the prefix leaves every recipe silently on GCC 13. Check all three:
for d in prefix/x86_64-unknown-redox/gcc-install \
prefix/x86_64-unknown-redox/sysroot \
~/.redoxer/x86_64-unknown-redox/toolchain; do
"$d/bin/x86_64-unknown-redox-gcc" --version | head -1
done
# all three must print 16.1.0
Rollback
install-gcc16-toolchain.sh moves the GCC 13 components aside to
build/gcc13-backup/ rather than deleting them. --restore puts them back.
Tree-wide consequences
Three changes in src/cook/script.rs were required by the version jump. All
three are deliberate and documented at the point of use.
C dialect pinned to gnu17. GCC 13.2.0 defaulted to gnu17
(__STDC_VERSION__ 201710L); GCC 16.1.0 defaults to gnu23 (202311L). The
recipe tree is C17-era code, and C23 turns previously-legal constructs into
hard errors — most notably an empty parameter list, which used to mean
"unspecified arguments" and now means "no arguments". libiconv's
lib/loop_wchar.h has extern size_t mbrtowc ();, which under C23 conflicts
with relibc's real four-argument prototype. The pin states the dialect these
sources were written against; it suppresses no diagnostic, and it is what the
distributions did for the same GCC 14/15 transition. Per-recipe -std= still
wins, being appended after. Packages migrate to C23 as they are touched; when
the tree is clean the pin can go.
C++ is deliberately NOT pinned — kwin and plasma-workspace need C++23, which is the whole reason for the upgrade.
-fno-hardened forced. -fhardened is a host-glibc hardening bundle that
x86_64-unknown-redox cannot implement. GCC still accepts it on the command
line, so a meson cc.has_argument('-fhardened') probe answers YES, meson adds
it to every compile, and GCC then refuses it for real:
cc1: error: '-fhardened' not supported for this target [-Werror]
The diagnostic is tagged [-Werror], not [-Werror=hardened] — it is an
unconditional warning, so -Wno-hardened does not silence it. The flag has to
be cancelled outright. seatd died on this 24 times. This weakens nothing:
the flag is inert on this target by construction.
Implicit declarations are now fatal (GCC 14+), which is why the cookbook
defines HAVE_ALLOCA_H — C sources with no configure step otherwise skip
<alloca.h> and fail on an implicit alloca.
There is no GCC 13 fallback
Operator decision, 2026-08-05: "we will not have gcc 13." The build system was migrated to match, so nothing defaults to, downloads, or silently seeds the old compiler:
GCC_RECIPE?=gcc16(mk/prefix.mk:13) — the from-source path targets the GCC 16 recipe.- The Redox-hosted (
HOSTED_REDOX=1) package path derives its package names from$(GCC_RECIPE)instead of hardcodinggcc13.pkgar(mk/prefix.mk:224).static.redox-os.orgpublishes nogcc16package, so that path now fails at download until Red Bear hosts its own. This is deliberate: a loud failure beats a wrong compiler. build-redbear.shrefuses to build on anything but GCC 16. This is the one that matters on a Linux host.make prefixunpacks upstream'sgcc-install.tar.gz, which is GCC 13.2.0, and no make rule replaces it — the GCC 16 compiler arrives only viainstall-gcc16-toolchain.sh. Before the guard, a freshmake prefixleft you on GCC 13 and the mistake surfaced ~40 minutes later as a kwin C++23 failure. The guard checks all three locations and prints the two commands to run.
The cookbook's from-source path is dead in this fork regardless: it copies
$(GCC_TARGET)/stage.cxx/usr/ and nothing in src/ ever produces a
stage.cxx directory, so it cannot have run. Repairing it is separate work and
was not required to obtain a newer compiler — hence the two standalone scripts
above.
recipes/dev/gcc13/ still exists on disk as an upstream-inherited recipe. It
builds nothing in this fork and is not on any path the build takes.
Known open gap
libstdc++ 16.1.0 as built here is missing the float16 std::formatter
specializations. <format> sees __FLT16_MAX__ from the cross compiler and
emits extern template declarations promising specializations the library does
not contain:
undefined reference to std::formatter<_Float16, char>::format<...>
undefined reference to std::formatter<std::bfloat16_t, char>::format<...>
Measured against the shipped library:
nm -D --defined-only prefix/x86_64-unknown-redox/sysroot/x86_64-unknown-redox/lib/libstdc++.so.6.0.35 \
| grep -c formatterIDF16 # 0 defined
nm -D -u prefix/x86_64-unknown-redox/sysroot/x86_64-unknown-redox/lib/libstdc++.so.6.0.35 \
| grep -c formatterIDF16 # 0 undefined
Zero either way — they are absent entirely, not merely unresolved. This blocks
the kwin link. The fix belongs on the libstdc++ side of the GCC 16 build
(enabling the float16 specializations when the target compiler advertises
_Float16), not in kwin: patching the consumer would mask a toolchain gap that
resurfaces for every C++23 package that formats a _Float16.
Itanium mangling reference, for grepping build logs: DF16_ is _Float16,
DF16b is std::bfloat16_t.