Files
RedBear-OS/local/scripts/install-gcc16-toolchain.sh
T
vasilito f2b6c1e0ed gcc: port GCC 16.1.0 to the Redox target and install the toolchain
The Redox target port applier claimed validation on 16.1.0 but its
idempotency probe used each block's longest line, which for three blocks
is generic upstream boilerplate. Against a pristine 16.1.0 tree that
silently skipped the libgcc target arms and BOTH crossconfig.m4 arms
(libgcc/config.host and crossconfig.m4 contain zero redox references, yet
the applier reported 'already present'), producing a half-ported tree --
the exact failure the script documents itself as preventing. Probe on the
longest redox-bearing line instead, matched whole.

Two port requirements the original extraction missed, both fatal:

- gcc/config/redox.opt.urls. GCC 16 requires a .opt.urls companion for
  every .opt; s-options fails without it. Contents match what
  regenerate-opt-urls.py emits for these two options, cross-checked
  against the six upstream .opt.urls declaring the same pthread/rdynamic.

- libtool has no redox host. Upstream Redox gets shared libraries from
  recipes/dev/libtool (a Redox-patched libtool 2.5.4-redox-9510) via
  libtoolize during autoreconf, not from GCC's bundled libtool.m4. That
  route does not apply to GCC 16, which bundles 2.2.7-era macros plus its
  own ltgcc.m4. Without redox arms _LT_SYS_DYNAMIC_LINKER leaves
  dynamic_linker=no, libstdc++ builds static-only, and the desktop stack
  cannot link -- libQt6Core.so and every KF6 library carry DT_NEEDED
  libstdc++.so.6. apply-libtool-redox.py registers the four arms that
  matter, verbatim from the Redox libtool macros already in prefix/.

Result: x86_64-unknown-redox-gcc 16.1.0 with libstdc++.so.6.0.35 (SONAME
libstdc++.so.6, NEEDED libc.so.6 + libgcc_s.so.1 -- identical to the
13.2.0 library it replaces, exports a superset up to GLIBCXX_3.4.35).
std::ranges::to now compiles for the Redox target; GCC 13.2.0 fails the
same test, which is what blocked kwin's 16 affected files.

install-gcc16-toolchain.sh installs into all three locations a recipe can
resolve a compiler from -- including ~/.redoxer, which src/cook/script.rs
puts highest on PATH -- and is reversible with --restore. Its cstdlib
strtold patch is guarded; the mk/prefix.mk sed is not, and had applied
that block 17 times to the GCC 13 toolchain.
2026-08-03 12:40:15 +03:00

122 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Install the GCC 16 cross compiler over the GCC 13.2.0 one, in every
# location the build actually reads a compiler from.
#
# There are three such locations, and all three must agree or the build
# picks up a mixed toolchain:
#
# 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 this to PATH last, so it wins over both prefix paths for
# every recipe. Missing this one silently leaves recipes on GCC 13.
#
# Reversible: the GCC 13 components are moved aside to a timestamped
# backup dir rather than deleted, and --restore puts them back.
#
# Run local/scripts/build-gcc16-cross.sh first.
set -euo pipefail
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
TARGET=x86_64-unknown-redox
NEWGCC=16.1.0
OLDGCC=13.2.0
SRC="$ROOT/build/gcc16-install"
PREFIX_GCC="$ROOT/prefix/$TARGET/gcc-install"
PREFIX_SYSROOT="$ROOT/prefix/$TARGET/sysroot"
REDOXER="$HOME/.redoxer/$TARGET/toolchain"
BACKUP="$ROOT/build/gcc13-backup"
# GCC's <cstdlib> does `using ::strtold` before relibc's cbindgen trailer has
# declared it, so the C++ wrapper must pull in <stdlib.h> explicitly. mk/prefix.mk
# does this with a sed, but that sed is NOT idempotent -- the current GCC 13
# toolchain has the comment block appended 17 times from repeated `make prefix`
# runs. The guard below makes it apply exactly once.
patch_cstdlib() {
local f="$1"
[ -f "$f" ] || return 0
grep -q "Red Bear: relibc declares strtold" "$f" && return 0
sed -i '/^#include_next <stdlib.h>$/a\\n// Red Bear: relibc declares strtold via cbindgen trailer.\n// The explicit include ensures ::strtold is visible when the\n// C++ wrapper processes its using-directives below.\n#include <stdlib.h>' "$f"
echo " patched strtold: $f"
}
# Move GCC's own components out of a tree without disturbing the rust/clang/
# relibc files that share it.
evict_old() {
local dst="$1" tag="$2"
local bk="$BACKUP/$tag"
mkdir -p "$bk"
for p in "bin/$TARGET-gcc-$OLDGCC" \
"lib/gcc/$TARGET/$OLDGCC" \
"libexec/gcc/$TARGET/$OLDGCC" \
"$TARGET/include/c++/$OLDGCC"; do
if [ -e "$dst/$p" ]; then
mkdir -p "$bk/$(dirname "$p")"
mv "$dst/$p" "$bk/$p"
fi
done
for so in "$dst/$TARGET/lib/"libstdc++.so.6.0.* ; do
[ -e "$so" ] || continue
mkdir -p "$bk/$TARGET/lib"
mv "$so" "$bk/$TARGET/lib/"
done
}
install_into() {
local dst="$1" tag="$2"
[ -d "$dst" ] || { echo " skip $tag (not present)"; return 0; }
echo " -> $tag: $dst"
evict_old "$dst" "$tag"
# Driver, cc1/cc1plus, target headers and libs.
cp -a "$SRC/bin/." "$dst/bin/"
mkdir -p "$dst/lib/gcc/$TARGET" "$dst/libexec/gcc/$TARGET"
cp -a "$SRC/lib/gcc/$TARGET/$NEWGCC" "$dst/lib/gcc/$TARGET/"
cp -a "$SRC/libexec/gcc/$TARGET/$NEWGCC" "$dst/libexec/gcc/$TARGET/"
mkdir -p "$dst/$TARGET/include/c++"
cp -a "$SRC/$TARGET/include/c++/$NEWGCC" "$dst/$TARGET/include/c++/"
cp -a "$SRC/$TARGET/lib/." "$dst/$TARGET/lib/"
for c in "$dst/$TARGET/include/c++/$NEWGCC/cstdlib"; do patch_cstdlib "$c"; done
}
if [ "${1:-}" = "--restore" ]; then
[ -d "$BACKUP" ] || { echo "no backup at $BACKUP" >&2; exit 1; }
for tag in gcc-install sysroot redoxer; do
case $tag in
gcc-install) dst="$PREFIX_GCC" ;;
sysroot) dst="$PREFIX_SYSROOT" ;;
redoxer) dst="$REDOXER" ;;
esac
[ -d "$BACKUP/$tag" ] || continue
echo "restoring $tag"
cp -a "$BACKUP/$tag/." "$dst/"
done
echo "GCC $OLDGCC restored. Re-run without --restore to go back to $NEWGCC."
exit 0
fi
[ -x "$SRC/bin/$TARGET-gcc" ] || {
echo "FATAL: $SRC not built. Run local/scripts/build-gcc16-cross.sh" >&2; exit 1; }
[ -e "$SRC/$TARGET/lib/libstdc++.so.6" ] || {
echo "FATAL: $SRC has no shared libstdc++. The desktop stack links" >&2
echo " libstdc++.so.6 (readelf -d libQt6Core.so), so a static-only" >&2
echo " toolchain cannot build it." >&2; exit 1; }
echo "Installing GCC $NEWGCC (backup of $OLDGCC -> $BACKUP)"
rm -rf "$BACKUP"
install_into "$PREFIX_GCC" gcc-install
install_into "$PREFIX_SYSROOT" sysroot
install_into "$REDOXER" redoxer
echo
echo "Verifying the compiler each recipe will actually invoke:"
PATH="$REDOXER/bin:$PREFIX_SYSROOT/bin:$PATH" "$TARGET-gcc" --version | head -1
PATH="$REDOXER/bin:$PREFIX_SYSROOT/bin:$PATH" "$TARGET-g++" -std=c++23 -x c++ -c - -o /dev/null <<'EOF'
#include <version>
#ifndef __cpp_lib_ranges_to_container
#error ranges::to missing
#endif
int main(){}
EOF
echo "C++23 ranges::to: OK"
echo "Revert with: $0 --restore"