gcc: applier that ports Redox onto pristine GCC, validated on 16.1.0
redbear-ci / check (push) Has been cancelled
redbear-ci / check (push) Has been cancelled
Applies the extracted port to an unpacked GCC tree: copies the 5 Redox-owned files, then inserts each redox arm at an anchored point. Validated against a real gcc-16.1.0 tree (blake3 5f001609f662143ce9285cd740bd0acfeeaf7f13731b46fd1d9ebe620c5c340d). Findings from that validation: - GCC 16 already recognises redox in config.sub upstream, one fewer file to patch than in 13.2.0. - Two anchors moved since 13.2.0 and were re-derived: solaris folded into the linux arm in crossconfig.m4, and the mingw32 targets were consolidated in mkfixinc.sh. - libgcc's riscv64 arm had been truncated during the original capture; restored. Two idempotency bugs found by comparing redox-line counts against the 13.2.0 reference rather than trusting "it ran clean": - a substring probe matched the generic block's case label inside the already-inserted aarch64/riscv64 label, silently skipping the second crossconfig.m4 block; - a first-line probe matched the aarch64 label inside CONFIG_GCC_OS, silently skipping config.gcc's tm_file target arms, which would have produced a tree that configures but never pulls in redox.h. Now probes on the block's longest line, matched whole. config.gcc reaches 16/16 redox lines, matching the 13.2.0 reference exactly. Verified for x86_64-unknown-redox: config.gcc tm_file arm incl. redox.h, config.host xm_file, libgcc arm, crossconfig generic arm, mkfixinc arm, gcc/config/redox.h, and the _GLIBCXX_USE_WEAK_REF define. Re-running is a no-op. NOT YET BUILT: no compiler has been produced, and gcc/configure plus libstdc++-v3/configure still need regenerating from crossconfig.m4 with autoconf.
This commit is contained in:
+266
@@ -0,0 +1,266 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Apply the Redox target port to a pristine GCC source tree.
|
||||
|
||||
Usage: apply-redox-port.py <gcc-source-root> [--check]
|
||||
|
||||
Extracted from redox-os/gcc branch redox-13.2.0 (see README.md). The port is
|
||||
13 files: 5 Redox-owned (copied verbatim from files/) and 8 existing GCC files
|
||||
that need a `*-*-redox*` arm registered.
|
||||
|
||||
Every edit is anchored on stable upstream text and is IDEMPOTENT: a file that
|
||||
already mentions redox in the relevant place is left alone. Anchors were chosen
|
||||
to be the kind of plumbing that changes slowly between GCC releases; if one
|
||||
stops matching after a version bump, the script reports it rather than silently
|
||||
producing a half-ported tree.
|
||||
|
||||
NOTE: gcc/configure and libstdc++-v3/configure also reference redox in the
|
||||
13.2.0 fork, but they are GENERATED. Do not patch them here -- regenerate from
|
||||
crossconfig.m4 with autoconf after running this script.
|
||||
"""
|
||||
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
FILES = HERE / "files"
|
||||
|
||||
# --- blocks to insert, keyed by file -----------------------------------------
|
||||
|
||||
CONFIG_GCC_OS = """*-*-redox*)
|
||||
gas=yes
|
||||
gnu_ld=yes
|
||||
default_use_cxa_atexit=yes
|
||||
gcc_cv_initfini_array=yes
|
||||
tmake_file="${tmake_file} t-slibgcc"
|
||||
extra_options="${extra_options} redox.opt"
|
||||
case ${enable_threads} in
|
||||
yes)
|
||||
thread_file='posix'
|
||||
;;
|
||||
esac
|
||||
case ${target} in
|
||||
i[34567]86-*-redox* | x86_64-*-redox*)
|
||||
xm_file=i386/xm-redox.h
|
||||
;;
|
||||
aarch64-*-redox*)
|
||||
xm_file=aarch64/xm-redox.h
|
||||
;;
|
||||
riscv64*-*-redox*)
|
||||
xm_file=riscv/xm-redox.h
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"""
|
||||
|
||||
CONFIG_GCC_TARGETS = """aarch64-*-redox*)
|
||||
\ttm_file="${tm_file} elfos.h aarch64/aarch64-elf.h aarch64/aarch64-elf-raw.h redox.h newlib-stdint.h"
|
||||
\t;;
|
||||
i[34567]86-*-redox*)
|
||||
\ttm_file="${tm_file} i386/unix.h i386/att.h elfos.h i386/i386elf.h redox.h newlib-stdint.h"
|
||||
\t;;
|
||||
riscv64*-*-redox*)
|
||||
\ttm_file="${tm_file} elfos.h riscv/elf.h redox.h newlib-stdint.h"
|
||||
\t;;
|
||||
x86_64-*-redox*)
|
||||
\ttm_file="${tm_file} i386/unix.h i386/att.h elfos.h i386/i386elf.h i386/x86-64.h redox.h newlib-stdint.h"
|
||||
\t;;
|
||||
"""
|
||||
|
||||
CONFIG_HOST = """ i[34567]86-*-redox* | x86_64-*-redox*)
|
||||
host_xm_file=i386/xm-redox.h
|
||||
;;
|
||||
aarch64-*-redox*)
|
||||
host_xm_file=aarch64/xm-redox.h
|
||||
;;
|
||||
riscv64*-*-redox*)
|
||||
host_xm_file=riscv/xm-redox.h
|
||||
;;
|
||||
"""
|
||||
|
||||
CONFIG_BUILD = """ i[34567]86-*-redox* | x86_64-*-redox* )
|
||||
build_xm_file=i386/xm-redox.h
|
||||
;;
|
||||
aarch64-*-redox*)
|
||||
build_xm_file=aarch64/xm-redox.h
|
||||
;;
|
||||
riscv64*-*-redox*)
|
||||
build_xm_file=riscv/xm-redox.h
|
||||
;;
|
||||
"""
|
||||
|
||||
LIBGCC_OS = """*-*-redox*)
|
||||
extra_parts="$extra_parts crtbegin.o crtbeginS.o crtend.o crtendS.o"
|
||||
tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic"
|
||||
tmake_file="$tmake_file t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver"
|
||||
;;
|
||||
"""
|
||||
|
||||
LIBGCC_TARGETS = """i[34567]86-*-redox*)
|
||||
\ttmake_file="$tmake_file i386/t-crtstuff"
|
||||
\t;;
|
||||
x86_64-*-redox*)
|
||||
\ttmake_file="$tmake_file i386/t-crtstuff"
|
||||
\t;;
|
||||
aarch64-*-redox*)
|
||||
\textra_parts="$extra_parts crtfastmath.o"
|
||||
\ttmake_file="${tmake_file} ${cpu_type}/t-aarch64"
|
||||
\ttmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc"
|
||||
\ttmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
|
||||
\tmd_unwind_header=aarch64/aarch64-unwind.h
|
||||
\t;;
|
||||
"""
|
||||
|
||||
CROSSCONFIG_AARCH64 = """ aarch64-*-redox* | riscv64*-*-redox*)
|
||||
SECTION_FLAGS='-ffunction-sections -fdata-sections'
|
||||
AC_SUBST(SECTION_FLAGS)
|
||||
AC_DEFINE(HAVE_ALIGNED_ALLOC)
|
||||
;;
|
||||
|
||||
"""
|
||||
|
||||
CROSSCONFIG_GENERIC = """ *-redox*)
|
||||
GLIBCXX_CHECK_COMPILER_FEATURES
|
||||
GLIBCXX_CHECK_LINKER_FEATURES
|
||||
GLIBCXX_CHECK_MATH_SUPPORT
|
||||
GLIBCXX_CHECK_STDLIB_SUPPORT
|
||||
AC_CHECK_FUNCS(aligned_alloc posix_memalign memalign _aligned_malloc)
|
||||
;;
|
||||
"""
|
||||
|
||||
MKFIXINC = """ aarch64-*-redox* | \\
|
||||
i?86-*-redox* | \\
|
||||
riscv64*-*-redox* | \\
|
||||
x86_64-*-redox* | \\
|
||||
"""
|
||||
|
||||
OS_DEFINES = """
|
||||
// Causes issues on Redox
|
||||
#define _GLIBCXX_USE_WEAK_REF 0
|
||||
"""
|
||||
|
||||
# (relative path, anchor text, block, insert_before)
|
||||
EDITS = [
|
||||
("gcc/config.gcc", "*-*-netbsd*)", CONFIG_GCC_OS, True),
|
||||
("gcc/config.gcc", "i[34567]86-pc-msdosdjgpp*)", CONFIG_GCC_TARGETS, True),
|
||||
("gcc/config.host", "esac", CONFIG_HOST, True),
|
||||
("gcc/config.build", "esac", CONFIG_BUILD, True),
|
||||
("libgcc/config.host", "*-*-rtems*)", LIBGCC_OS, True),
|
||||
("libgcc/config.host", "i[34567]86-*-elf*)", LIBGCC_TARGETS, True),
|
||||
("libstdc++-v3/crossconfig.m4", " *-hpux*)", CROSSCONFIG_AARCH64, True),
|
||||
# GCC 16 moved *-solaris* into the *-linux* arm and consolidated the
|
||||
# mingw32 targets, so these two anchors differ from 13.2.0.
|
||||
("libstdc++-v3/crossconfig.m4", " *-mingw32*)", CROSSCONFIG_GENERIC, True),
|
||||
("fixincludes/mkfixinc.sh", " *-mingw32* | \\", MKFIXINC, True),
|
||||
]
|
||||
|
||||
|
||||
def already_ported(path: Path, marker: str = "redox") -> bool:
|
||||
try:
|
||||
return marker in path.read_text(encoding="utf-8", errors="replace").lower()
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def apply_edit(root: Path, rel: str, anchor: str, block: str, check: bool) -> str:
|
||||
p = root / rel
|
||||
if not p.is_file():
|
||||
return f"MISSING {rel}"
|
||||
text = p.read_text(encoding="utf-8", errors="replace")
|
||||
# Idempotency must be per-EDIT, not per-file: crossconfig.m4 and
|
||||
# config.gcc each take TWO separate blocks, so a whole-file "does it
|
||||
# mention redox" test would silently skip the second one.
|
||||
# Match the probe as a COMPLETE line. A substring test is wrong here:
|
||||
# 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()):
|
||||
return f"skip {rel} (block already present)"
|
||||
idx = text.find(anchor)
|
||||
if idx == -1:
|
||||
return f"ANCHOR-FAIL {rel} :: {anchor!r} not found -- re-derive for this GCC version"
|
||||
if check:
|
||||
return f"would-apply {rel} at offset {idx}"
|
||||
p.write_text(text[:idx] + block + text[idx:], encoding="utf-8")
|
||||
return f"applied {rel}"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) < 2:
|
||||
print(__doc__)
|
||||
return 2
|
||||
root = Path(sys.argv[1]).resolve()
|
||||
check = "--check" in sys.argv
|
||||
if not (root / "gcc" / "config.gcc").is_file():
|
||||
print(f"ERROR: {root} does not look like a GCC source tree", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
rc = 0
|
||||
|
||||
# 1. Redox-owned files (pure copies -- always safe).
|
||||
for src in sorted(FILES.rglob("*")):
|
||||
if not src.is_file():
|
||||
continue
|
||||
rel = src.relative_to(FILES)
|
||||
dst = root / rel
|
||||
if check:
|
||||
print(f"would-copy {rel}")
|
||||
continue
|
||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(src, dst)
|
||||
print(f"copied {rel}")
|
||||
|
||||
# 2. config.sub: add redox to the recognised OS list.
|
||||
cs = root / "config.sub"
|
||||
if cs.is_file():
|
||||
t = cs.read_text(encoding="utf-8", errors="replace")
|
||||
if "redox" in t:
|
||||
print("skip config.sub (already references redox)")
|
||||
elif "| fuchsia* " in t:
|
||||
if not check:
|
||||
cs.write_text(t.replace("| fuchsia* ", "| fuchsia* | redox* ", 1),
|
||||
encoding="utf-8")
|
||||
print(("would-apply " if check else "applied ") + "config.sub")
|
||||
else:
|
||||
print("ANCHOR-FAIL config.sub :: '| fuchsia* ' not found")
|
||||
rc = 1
|
||||
|
||||
# 3. os_defines.h: append before the trailing #endif.
|
||||
od = root / "libstdc++-v3/config/os/generic/os_defines.h"
|
||||
if od.is_file():
|
||||
t = od.read_text(encoding="utf-8", errors="replace")
|
||||
if "Redox" in t:
|
||||
print("skip os_defines.h (already references Redox)")
|
||||
else:
|
||||
i = t.rfind("#endif")
|
||||
if i == -1:
|
||||
print("ANCHOR-FAIL os_defines.h :: no trailing #endif")
|
||||
rc = 1
|
||||
else:
|
||||
if not check:
|
||||
od.write_text(t[:i] + OS_DEFINES + "\n" + t[i:], encoding="utf-8")
|
||||
print(("would-apply " if check else "applied ") + "os_defines.h")
|
||||
|
||||
# 4. Anchored insertions.
|
||||
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:
|
||||
rc = 1
|
||||
|
||||
print()
|
||||
print("NEXT: regenerate configure from crossconfig.m4 with autoconf "
|
||||
"(gcc/configure and libstdc++-v3/configure are GENERATED).")
|
||||
if rc:
|
||||
print("One or more anchors failed -- the tree is NOT fully ported.",
|
||||
file=sys.stderr)
|
||||
return rc
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user