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.
This commit is contained in:
@@ -88,3 +88,10 @@ Packages/*.pkgar
|
||||
# from build-redbear.sh — never commit them. The toolchain is rebuilt by
|
||||
# `make prefix` after fork (relibc/kernel/base) changes.
|
||||
/prefix/**/*.tar.gz
|
||||
|
||||
# GCC 16 cross-toolchain build artifacts (reproducible via
|
||||
# local/scripts/build-gcc16-cross.sh from local/recipes/dev/gcc16/source.tar)
|
||||
/build/gcc16-build/
|
||||
/build/gcc16-install/
|
||||
/build/gcc13-backup/
|
||||
/build/host-tools/
|
||||
|
||||
@@ -97,19 +97,84 @@ offline-first build model and matches how other external recipes vendor sources
|
||||
`gitlab.redox-os.org/redox-os/gcc` carries **no** upstream release tags, so the
|
||||
pristine base must come from ftp.gnu.org or gcc-mirror, not from the Redox fork.
|
||||
|
||||
## Next steps (in order)
|
||||
## Two things the extraction missed
|
||||
|
||||
1. Vendor `gcc-16.1.0.tar.xz`, record its blake3, create
|
||||
`local/recipes/dev/gcc16/recipe.toml` (model on `recipes/dev/gcc13`).
|
||||
2. Apply `files/` + the arms in `registration-hunks.txt`; regenerate `configure`
|
||||
from `crossconfig.m4` with autoconf.
|
||||
3. Parameterize the hardcoded `13.2.0` in `mk/prefix.mk` (at minimum the
|
||||
`lib/gcc/$(GNU_TARGET)/13.2.0/include/limits.h` path).
|
||||
4. Build the cross compiler; stage into `prefix/`. Expect relibc header
|
||||
fallout (see risks above) before anything else compiles.
|
||||
5. Full C++ tree rebuild for the libstdc++ ABI change — Qt6, all KF6, Plasma,
|
||||
Mesa C++. Budget this as the dominant cost, not the port itself.
|
||||
6. Only then retry `kwin`, whose 16 `std::ranges::to` files are the reason for
|
||||
the whole exercise.
|
||||
The "13 files" count above was derived by grepping the `redox-13.2.0` fork for
|
||||
"redox". Two requirements do not show up that way and both are fatal if skipped.
|
||||
|
||||
**Not started.** Steps 1–6 are unvalidated; nothing below step 0 has been run.
|
||||
### 1. `gcc/config/redox.opt.urls` (new in GCC 16)
|
||||
|
||||
GCC 16 requires a `.opt.urls` companion for every `.opt` file; `s-options`
|
||||
fails with *"No rule to make target ... redox.opt.urls"*. GCC 13 had no such
|
||||
rule. The file is now carried in `files/` and matches what
|
||||
`gcc/regenerate-opt-urls.py` produces: `rdynamic` gets the standard
|
||||
`gcc/Link-Options.html#index-rdynamic` suffix, and `pthread` is skipped with the
|
||||
duplicate-URL comment — identical to the six other upstream `.opt.urls` that
|
||||
declare the same two options.
|
||||
|
||||
### 2. libtool has no `redox` host — `apply-libtool-redox.py`
|
||||
|
||||
Upstream Redox's GCC fork does not carry redox arms in GCC's bundled
|
||||
`libtool.m4` either. Their toolchain gets shared libraries because
|
||||
`recipes/dev/libtool` is a **Redox-patched GNU libtool (2.5.4-redox-9510)**
|
||||
whose `libtoolize` overwrites the tree's `libtool.m4` during `autoreconf -fvi`.
|
||||
That route is not usable here: GCC 16 bundles 2.2.7-era macros plus its own
|
||||
`ltgcc.m4`, and gcc13's recipe only regenerates when an `autoreconf2.69`
|
||||
happens to be on `PATH`.
|
||||
|
||||
Without the arms, `_LT_SYS_DYNAMIC_LINKER` leaves `dynamic_linker=no` for
|
||||
redox, so configure reports *"libtool supports shared libraries... no"* and
|
||||
libstdc++ builds **static only**. That is fatal: `libQt6Core.so` and every KF6
|
||||
library carry `DT_NEEDED libstdc++.so.6` (`readelf -d`), so the desktop stack
|
||||
cannot link against a static-only toolchain. `apply-libtool-redox.py` registers
|
||||
the four arms that matter, copied verbatim from the Redox libtool macros in
|
||||
`prefix/<target>/gcc-install/share/aclocal/libtool.m4`.
|
||||
|
||||
## Applying to a new GCC (validated sequence)
|
||||
|
||||
```bash
|
||||
tar xf source.tar -C local/recipes/dev/gcc16/source --strip-components=1
|
||||
python3 local/patches/gcc-redox-port/apply-redox-port.py local/recipes/dev/gcc16/source
|
||||
python3 local/patches/gcc-redox-port/apply-libtool-redox.py local/recipes/dev/gcc16/source
|
||||
# configure is GENERATED -- regenerate with autoconf 2.69 (GCC pins that exact
|
||||
# version via config/override.m4; the host's 2.73 is rejected).
|
||||
(cd local/recipes/dev/gcc16/source/libstdc++-v3 && autoconf)
|
||||
./local/scripts/build-gcc16-cross.sh # cross compiler + libgcc + libstdc++
|
||||
./local/scripts/install-gcc16-toolchain.sh # into prefix + ~/.redoxer (reversible)
|
||||
```
|
||||
|
||||
Both appliers are idempotent and report an unmatched anchor rather than
|
||||
silently producing a half-ported tree.
|
||||
|
||||
## Status — GCC 16.1.0 ported and installed
|
||||
|
||||
| Step | State |
|
||||
|---|---|
|
||||
| `gcc-16.1.0.tar.xz` vendored (`local/recipes/dev/gcc16/source.tar`) | done |
|
||||
| Redox target port applied (10 edits + 6 files) | done |
|
||||
| `libstdc++-v3/configure` regenerated with autoconf 2.69 | done — purely additive, 3240 lines, no drift |
|
||||
| Cross compiler built | done — `x86_64-unknown-redox-gcc (GCC) 16.1.0` |
|
||||
| libgcc + shared libstdc++ | done — `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) |
|
||||
| **`std::ranges::to`** | **works** — `__cpp_lib_ranges_to_container` defined; GCC 13 fails the same test with *"'to' is not a member of 'std::ranges'"* |
|
||||
| Installed into prefix + `~/.redoxer` | done, reversible via `install-gcc16-toolchain.sh --restore` |
|
||||
|
||||
ABI note: `libstdc++.so.6.0.35` exports up to `GLIBCXX_3.4.35` where 13.2.0
|
||||
reached `3.4.32`, and keeps SONAME `libstdc++.so.6` — a backward-compatible
|
||||
superset, so already-linked binaries still resolve. Recompilation is still
|
||||
required to *use* the new headers.
|
||||
|
||||
### Still open
|
||||
|
||||
- `mk/prefix.mk` hardcodes `13.2.0` (line 354, the `limits.h` removal) and
|
||||
`GCC_TARGET=recipes/dev/gcc13/...` (line 10). Neither is on the path this
|
||||
port takes, but both must be parameterized before the toolchain can be
|
||||
rebuilt through `make prefix`.
|
||||
- `local/recipes/dev/gcc16/recipe.toml` does not exist. The cross compiler is
|
||||
currently produced by `local/scripts/build-gcc16-cross.sh` instead, because
|
||||
the cookbook's from-source toolchain path is dead: `mk/prefix.mk:315` copies
|
||||
`$(GCC_TARGET)/stage.cxx/`, and nothing in `src/` produces a `stage.cxx`.
|
||||
- Full C++ tree rebuild against the new toolchain — the dominant cost, and the
|
||||
reason the whole exercise exists (`kwin`'s 16 `std::ranges::to` files).
|
||||
- `riscv64*-*-redox*` is recorded in `registration-points.txt` for
|
||||
`libgcc/config.host` but is not in the applier's block. Irrelevant for
|
||||
amd64-only Red Bear; noted so the gap is not mistaken for completeness.
|
||||
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Register the Redox host OS in GCC's bundled libtool.m4.
|
||||
|
||||
Usage: apply-libtool-redox.py <gcc-source-root> [--check]
|
||||
|
||||
Why this is separate from apply-redox-port.py
|
||||
---------------------------------------------
|
||||
The original port extraction (README.md, registration-points.txt) measured
|
||||
the Redox port by grepping redox-os/gcc for "redox" and found 13 files. It
|
||||
missed libtool: upstream Redox does not carry redox arms in GCC's bundled
|
||||
libtool.m4 either. Their toolchain gets shared-library support because
|
||||
recipes/dev/libtool is a Redox-patched GNU libtool (2.5.4-redox-9510) whose
|
||||
libtoolize overwrites the tree's libtool.m4 during `autoreconf -fvi`.
|
||||
|
||||
That path is not usable for GCC 16: GCC bundles libtool 2.2.7-era macros
|
||||
plus its own ltgcc.m4 overrides, and gcc13's recipe only regenerates when
|
||||
an autoreconf2.69 happens to be on PATH. Splicing 2.5.4 wholesale into a
|
||||
2.2.7 tree risks a macro-version mismatch across the whole GCC build.
|
||||
|
||||
Without these arms libtool's _LT_SYS_DYNAMIC_LINKER leaves dynamic_linker=no
|
||||
for redox, so "libtool supports shared libraries... no" and libstdc++ builds
|
||||
static-only. That is fatal here: libQt6Core.so and every KF6 library carry
|
||||
DT_NEEDED libstdc++.so.6, so the desktop stack cannot link without a shared
|
||||
libstdc++ matching the compiler's headers.
|
||||
|
||||
The arm contents below are copied verbatim from the Redox libtool 2.5.4
|
||||
macros already present in this repo at
|
||||
prefix/<target>/gcc-install/share/aclocal/libtool.m4
|
||||
so the behaviour matches the toolchain they replace. They are plain shell
|
||||
case arms and are version-agnostic; only the ANCHORS are GCC-version
|
||||
sensitive, and a missing anchor is reported rather than silently skipped.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
MAX_CMD_LEN = """ redox*)
|
||||
# Under Redox, this test is not required because there is
|
||||
# no limit to the length of command line arguments.
|
||||
# Libtool will interpret -1 as no limit whatsoever
|
||||
lt_cv_sys_max_cmd_len=-1;
|
||||
;;
|
||||
|
||||
"""
|
||||
|
||||
DYNAMIC_LINKER = """redox*)
|
||||
version_type=linux # correct to gnu/linux during the next big refactor
|
||||
need_lib_prefix=no
|
||||
need_version=no
|
||||
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
|
||||
soname_spec='$libname$release$shared_ext$major'
|
||||
dynamic_linker='relibc ld64.so'
|
||||
shlibpath_var=LD_LIBRARY_PATH
|
||||
shlibpath_overrides_runpath=no
|
||||
hardcode_into_libs=yes
|
||||
;;
|
||||
|
||||
"""
|
||||
|
||||
DEPLIBS = """redox*)
|
||||
lt_cv_deplibs_check_method=pass_all
|
||||
;;
|
||||
|
||||
"""
|
||||
|
||||
# C++ tag: no special PIC handling needed, -fPIC comes from the generic path.
|
||||
PIC_CXX = """ redox*)
|
||||
\t;;
|
||||
"""
|
||||
|
||||
PIC_C = """ redox*)
|
||||
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
|
||||
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
|
||||
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
|
||||
;;
|
||||
|
||||
"""
|
||||
|
||||
ARCHIVE_C = """ redox*)
|
||||
\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
|
||||
\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
|
||||
;;
|
||||
|
||||
"""
|
||||
|
||||
LD_SHLIBS_CXX = """ redox*)
|
||||
_LT_TAGVAR(ld_shlibs, $1)=yes
|
||||
\t;;
|
||||
|
||||
"""
|
||||
|
||||
# (anchor, block, description)
|
||||
EDITS = [
|
||||
(" gnu*)\n # Under GNU Hurd, this test is not required because there is",
|
||||
MAX_CMD_LEN, "max_cmd_len"),
|
||||
("newsos6)\n version_type=linux",
|
||||
DYNAMIC_LINKER, "dynamic_linker (enables shared libs)"),
|
||||
("newos6*)\n lt_cv_deplibs_check_method=",
|
||||
DEPLIBS, "deplibs_check_method"),
|
||||
(" netbsd*)\n if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then\n\t _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects",
|
||||
LD_SHLIBS_CXX, "ld_shlibs (C++ tag)"),
|
||||
]
|
||||
|
||||
|
||||
def probe_present(text: str, block: str) -> bool:
|
||||
"""A block counts as present when its longest redox-bearing line already
|
||||
exists as a complete line. Same rule as apply-redox-port.py: a plain
|
||||
longest-line probe matches generic libtool boilerplate."""
|
||||
redox_lines = [l.strip() for l in block.strip().splitlines()
|
||||
if "redox" in l.lower()]
|
||||
if not redox_lines:
|
||||
return False
|
||||
probe = max(redox_lines, key=len)
|
||||
return any(l.strip() == probe for l in text.splitlines())
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) < 2:
|
||||
print(__doc__)
|
||||
return 2
|
||||
root = Path(sys.argv[1]).resolve()
|
||||
check = "--check" in sys.argv
|
||||
p = root / "libtool.m4"
|
||||
if not p.is_file():
|
||||
print(f"ERROR: {p} not found", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
text = p.read_text(encoding="utf-8", errors="replace")
|
||||
rc = 0
|
||||
pending = []
|
||||
|
||||
for anchor, block, desc in EDITS:
|
||||
if probe_present(text, block):
|
||||
print(f"skip {desc} (already present)")
|
||||
continue
|
||||
idx = text.find(anchor)
|
||||
if idx == -1:
|
||||
print(f"ANCHOR-FAIL {desc} :: anchor not found -- re-derive for "
|
||||
f"this GCC version", file=sys.stderr)
|
||||
rc = 1
|
||||
continue
|
||||
if text.count(anchor) != 1:
|
||||
print(f"AMBIGUOUS {desc} :: anchor occurs {text.count(anchor)}x",
|
||||
file=sys.stderr)
|
||||
rc = 1
|
||||
continue
|
||||
print(f"{'would-apply' if check else 'applied '} {desc}")
|
||||
pending.append((idx, block))
|
||||
|
||||
if not check and pending:
|
||||
# Apply back-to-front so earlier offsets stay valid.
|
||||
for idx, block in sorted(pending, key=lambda t: -t[0]):
|
||||
text = text[:idx] + block + text[idx:]
|
||||
p.write_text(text, encoding="utf-8")
|
||||
|
||||
if rc:
|
||||
print("libtool.m4 is NOT fully registered for redox.", file=sys.stderr)
|
||||
else:
|
||||
print("\nNEXT: regenerate libstdc++-v3/configure with autoconf 2.69.")
|
||||
return rc
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -174,12 +174,29 @@ def apply_edit(root: Path, rel: str, anchor: str, block: str, check: bool) -> st
|
||||
# the generic block starts "*-redox*)", which occurs inside the already
|
||||
# inserted "aarch64-*-redox* | riscv64*-*-redox*)" and made the second
|
||||
# crossconfig.m4 block silently skip.
|
||||
# Probe on the block's LONGEST line, matched whole. The first line is not
|
||||
# distinctive enough: CONFIG_GCC_TARGETS starts "aarch64-*-redox*)", which
|
||||
# also appears (indented) inside CONFIG_GCC_OS, so a first-line probe made
|
||||
# the tm_file arms silently skip.
|
||||
probe = max((l.strip() for l in block.strip().splitlines()), key=len)
|
||||
if probe and any(l.strip() == probe for l in text.splitlines()):
|
||||
# Probe on the block's longest REDOX-BEARING line, matched whole. Both
|
||||
# halves of that rule are load-bearing:
|
||||
# - "redox-bearing": a plain longest-line probe picks generic upstream
|
||||
# boilerplate. On GCC 16.1.0 that made three blocks silently skip
|
||||
# against a pristine tree -- LIBGCC_TARGETS probed
|
||||
# 'tmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc"'
|
||||
# (3 upstream hits) and both crossconfig.m4 blocks probed
|
||||
# "SECTION_FLAGS='-ffunction-sections -fdata-sections'" (7 hits) and
|
||||
# "AC_CHECK_FUNCS(aligned_alloc posix_memalign memalign
|
||||
# _aligned_malloc)" (4 hits), yielding a half-ported tree with no
|
||||
# libgcc target arms and no libstdc++ redox support.
|
||||
# - "whole line": CROSSCONFIG_GENERIC's marker is "*-redox*)", a
|
||||
# substring of the already-inserted
|
||||
# "aarch64-*-redox* | riscv64*-*-redox*)".
|
||||
# Longest (not first) still matters: CONFIG_GCC_TARGETS starts
|
||||
# "aarch64-*-redox*)", which also appears indented inside CONFIG_GCC_OS.
|
||||
redox_lines = [l.strip() for l in block.strip().splitlines()
|
||||
if "redox" in l.lower()]
|
||||
if not redox_lines:
|
||||
return (f"NO-PROBE {rel} :: block has no redox-bearing line; "
|
||||
"cannot test idempotency safely")
|
||||
probe = max(redox_lines, key=len)
|
||||
if any(l.strip() == probe for l in text.splitlines()):
|
||||
return f"skip {rel} (block already present)"
|
||||
idx = text.find(anchor)
|
||||
if idx == -1:
|
||||
@@ -250,7 +267,7 @@ def main() -> int:
|
||||
for rel, anchor, block, _ in EDITS:
|
||||
msg = apply_edit(root, rel, anchor, block, check)
|
||||
print(msg)
|
||||
if "ANCHOR-FAIL" in msg or "MISSING" in msg:
|
||||
if any(k in msg for k in ("ANCHOR-FAIL", "MISSING", "NO-PROBE")):
|
||||
rc = 1
|
||||
|
||||
print()
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
; Autogenerated by regenerate-opt-urls.py from gcc/config/redox.opt and generated HTML
|
||||
|
||||
; skipping UrlSuffix for 'pthread' due to multiple URLs:
|
||||
; duplicate: 'gcc/Link-Options.html#index-pthread-1'
|
||||
; duplicate: 'gcc/Preprocessor-Options.html#index-pthread'
|
||||
|
||||
rdynamic
|
||||
UrlSuffix(gcc/Link-Options.html#index-rdynamic)
|
||||
Executable
+96
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build the GCC 16 cross-compiler (x86_64-linux -> x86_64-unknown-redox).
|
||||
#
|
||||
# Why this exists
|
||||
# ---------------
|
||||
# mk/prefix.mk has two toolchain paths:
|
||||
# PREFIX_BINARY=1 (the default, mk/config.mk:13) downloads a prebuilt
|
||||
# GCC 13.2.0 from static.redox-os.org.
|
||||
# PREFIX_BINARY=0 cooks host:gcc13 through the cookbook.
|
||||
# The second path is dead in this fork: it copies
|
||||
# "$(GCC_TARGET)/stage.cxx/usr/" (mk/prefix.mk:315) and nothing in src/
|
||||
# ever produces a stage.cxx directory, so it cannot have run. Repairing
|
||||
# the cookbook's from-source path is a separate piece of work and is not
|
||||
# required to obtain a newer GCC.
|
||||
#
|
||||
# This script therefore builds the cross compiler directly against the
|
||||
# artifacts the prefix already provides: binutils 2.43.1 and the relibc
|
||||
# sysroot (libc.a, crt*.o, headers). Configure flags mirror the cross arm
|
||||
# of recipes/dev/gcc13/recipe.toml so the resulting compiler is
|
||||
# configured like the one it replaces.
|
||||
#
|
||||
# The GCC 16 source must already carry the Redox target port:
|
||||
# python3 local/patches/gcc-redox-port/apply-redox-port.py \
|
||||
# local/recipes/dev/gcc16/source
|
||||
# (then regenerate libstdc++-v3/configure with autoconf 2.69)
|
||||
# See local/patches/gcc-redox-port/README.md.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
|
||||
TARGET=x86_64-unknown-redox
|
||||
PREFIX_DIR="$ROOT/prefix/$TARGET"
|
||||
SYSROOT="$PREFIX_DIR/sysroot/$TARGET"
|
||||
SRC="$ROOT/local/recipes/dev/gcc16/source"
|
||||
BUILD="$ROOT/build/gcc16-build"
|
||||
INSTALL="$ROOT/build/gcc16-install"
|
||||
JOBS="${JOBS:-$(nproc)}"
|
||||
|
||||
for req in "$SRC/gcc/BASE-VER" "$SYSROOT/lib/libc.a" "$PREFIX_DIR/gcc-install/bin/$TARGET-as"; do
|
||||
[ -e "$req" ] || { echo "FATAL: missing prerequisite: $req" >&2; exit 1; }
|
||||
done
|
||||
|
||||
# The port must be present, or we would silently build a compiler with no
|
||||
# Redox target and only discover it at the end of a ~40 minute build.
|
||||
grep -q 'redox' "$SRC/gcc/config.gcc" || {
|
||||
echo "FATAL: $SRC is not Redox-ported (gcc/config.gcc has no redox arm)." >&2
|
||||
echo " Run local/patches/gcc-redox-port/apply-redox-port.py first." >&2
|
||||
exit 1
|
||||
}
|
||||
grep -q 'redox' "$SRC/libstdc++-v3/configure" || {
|
||||
echo "FATAL: libstdc++-v3/configure has no redox arm -- it was not" >&2
|
||||
echo " regenerated from the patched crossconfig.m4 (autoconf 2.69)." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "GCC version : $(cat "$SRC/gcc/BASE-VER")"
|
||||
echo "target : $TARGET"
|
||||
echo "sysroot : $SYSROOT"
|
||||
echo "install : $INSTALL"
|
||||
echo "jobs : $JOBS"
|
||||
|
||||
export PATH="$PREFIX_DIR/gcc-install/bin:$PATH"
|
||||
# Redox has no SystemTap probes, but the configure probe can see the host's
|
||||
# sys/sdt.h and then libgcc fails including a header the target lacks.
|
||||
# Same reasoning as recipes/dev/gcc13/recipe.toml.
|
||||
export gcc_cv_sys_sdt_h=no
|
||||
|
||||
rm -rf "$BUILD" "$INSTALL"
|
||||
mkdir -p "$BUILD" "$INSTALL"
|
||||
cd "$BUILD"
|
||||
|
||||
"$SRC/configure" \
|
||||
--build=x86_64-pc-linux-gnu \
|
||||
--host=x86_64-pc-linux-gnu \
|
||||
--target="$TARGET" \
|
||||
--prefix="$INSTALL" \
|
||||
--with-sysroot="$SYSROOT" \
|
||||
--with-native-system-header-dir="/include" \
|
||||
--with-linker-hash-style=gnu \
|
||||
--enable-languages=c,c++,lto \
|
||||
--enable-initfini-array \
|
||||
--enable-threads=posix \
|
||||
--enable-libstdcxx-threads \
|
||||
--enable-frame-pointer \
|
||||
--disable-nls \
|
||||
--disable-multilib \
|
||||
--disable-bootstrap \
|
||||
--with-bugurl="https://gitea.redbearos.org/vasilito/RedBear-OS/-/issues"
|
||||
|
||||
"${MAKE:-make}" -j "$JOBS" all-gcc
|
||||
"${MAKE:-make}" -j "$JOBS" all-target-libgcc
|
||||
"${MAKE:-make}" -j "$JOBS" all-target-libstdc++-v3
|
||||
"${MAKE:-make}" install-gcc install-target-libgcc install-target-libstdc++-v3
|
||||
|
||||
echo
|
||||
echo "BUILD OK"
|
||||
"$INSTALL/bin/$TARGET-gcc" --version | head -1
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
#!/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"
|
||||
Reference in New Issue
Block a user