#!/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//gcc-install/ - the GCC half of the prefix # 2. prefix//sysroot/ - the merged prefix (gcc+rust+clang) # 3. ~/.redoxer//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 does `using ::strtold` before relibc's cbindgen trailer has # declared it, so the C++ wrapper must pull in 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 $/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 ' "$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 #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"