Files
RedBear-OS/local/docs/TOOLCHAIN-GCC16.md
T
vasilito a287fe20b9
redbear-ci / check (push) Has been cancelled
toolchain: remove the GCC 13 path; document the GCC 16 transition
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>
2026-08-05 10:11:06 +03:00

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:

  1. prefix/<target>/gcc-install/ — the GCC half of the prefix
  2. prefix/<target>/sysroot/ — the merged prefix (gcc + rust + clang)
  3. ~/.redoxer/<target>/toolchain/highest priority; src/cook/script.rs prepends it to PATH last, 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 hardcoding gcc13.pkgar (mk/prefix.mk:224). static.redox-os.org publishes no gcc16 package, 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.sh refuses to build on anything but GCC 16. This is the one that matters 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 — the GCC 16 compiler arrives only via install-gcc16-toolchain.sh. Before the guard, a fresh make prefix left 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.