selfhost-verify: artefactos del frente rust (parche run_rustc + runners stage0-musl)
Rastrea las correcciones del frente rust que vivían en .scratch/ (gitignored): - run_rustc.patch (vs mrustc be69c74): minicargo/hello con --target musl; RUSTFLAGS + sitios de link con link-self-contained=no (CRT vía gcc Alpine, link dinámico contra musl); proxy host-units con crt-static off (sin inject de --target, host==target==musl con el stage0 musl-host). - build-stage0-musl.sh: rebuild del stage0 rustc+cargo con host triple musl (CFG_COMPILER_HOST_TRIPLE vía RUSTC_TARGET, --target vía MRUSTC_TARGET), reusa LLVM + bin/mrustc. Gotcha OUTDIR_SUF documentado. - run-runrustc.sh: corre targets de run_rustc en el sandbox devfs apuntando al stage0 musl-host. - README: diagnóstico de los 3 snags acoplados (std-gnu mmap64/open64, CRT self-contained ausente, host-triple gnu + proc-macros) y el workflow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# rust-frontier — self-hosting the builder's rust toolchain
|
||||
|
||||
The last frontier of `selfhost-verify` variante (b): replace the Alpine
|
||||
`rustc/cargo 1.91.1` in `/toolchain` with a hammer-built rust, via the **purist
|
||||
mrustc chain** (no prebuilt rustc binary). Path:
|
||||
|
||||
mrustc → rustc 1.90.0 (builds bundled LLVM) → 1.91.0 → 1.91.1
|
||||
|
||||
These scripts + patch are the working artifacts. The mrustc tree itself lives in
|
||||
`.scratch/mrustc` (gitignored — it's a large third-party clone, upstream master
|
||||
`be69c74`); only our deltas are tracked here.
|
||||
|
||||
## Files
|
||||
|
||||
- **`run_rustc.patch`** — patch against mrustc `be69c74` for `run_rustc/Makefile`
|
||||
and `run_rustc/rustc_proxy.sh`. Apply from the mrustc root:
|
||||
`git -C .scratch/mrustc apply /path/to/run_rustc.patch`
|
||||
- **`build-stage0-musl.sh`** — rebuild the mrustc stage0 `rustc`+`cargo` with a
|
||||
**musl host triple** (`output-1.90.0-x86_64-unknown-linux-musl/`). Run inside
|
||||
the Alpine devfs sandbox (gcc, MRUSTC_TARGET_VER=1.90). Reuses the already-built
|
||||
LLVM and `bin/mrustc`.
|
||||
- **`run-runrustc.sh`** — run a `run_rustc` make target inside the devfs sandbox,
|
||||
pointed at the musl-host stage0.
|
||||
|
||||
> Both runners hardcode `/home/sergio/hammer` and assume the prepared devfs at
|
||||
> `.dev-fs/alpine` (256-TLS-key musl loader + g++; see the bootstrap-devfs notes).
|
||||
|
||||
## Why the patches exist (the snags)
|
||||
|
||||
The lab is **musl-only** (Alpine devfs); the 4/4 inputs (arje-zero/hammerd) are
|
||||
built `--target x86_64-unknown-linux-musl`. Three coupled problems had to be fixed
|
||||
to bootstrap a usable rust there:
|
||||
|
||||
1. **stage-1 std built for gnu** (`mmap64`/`open64` undefined at link).
|
||||
`minicargo` was invoked without `--target`, so it used mrustc's default **gnu**
|
||||
triple — and gnu std references glibc's LFS64 symbols that musl 1.2.5 doesn't
|
||||
export. Fix: pass `--target $(RUSTC_TARGET)` to minicargo (Makefile:162) and to
|
||||
the stage-1 smoke-test (Makefile:172). A correct musl std uses the **base** libc
|
||||
symbols (`open`/`mmap`/…), matching Alpine's reference std.
|
||||
|
||||
2. **self-contained CRT absent.** musl's default link is `-static-pie` against a
|
||||
`lib/rustlib/<t>/lib/self-contained/` CRT dir that the mrustc sysroot never
|
||||
populates. Fix: `-C target-feature=-crt-static -C link-self-contained=no` so the
|
||||
Alpine gcc supplies crt1/crti/crtn + crtbeginS/crtendS and links dynamically
|
||||
against the system musl (RUSTFLAGS in Makefile:111, plus the per-link sites).
|
||||
|
||||
3. **host-triple = gnu on a musl system** (the deep one). cargo compiles
|
||||
build-scripts and **proc-macros** for the *host*; mrustc's stage0 rustc has its
|
||||
host triple baked as `x86_64-unknown-linux-gnu` (not runtime-overridable). A
|
||||
proxy `--target musl` inject fixes build-script *bins*, but **proc-macros are
|
||||
dlopen'd and must match the host triple structurally** — injection makes them
|
||||
target artifacts that rustc rejects. Aliasing musl rlibs as gnu also fails:
|
||||
rustc reads the triple from rlib *metadata* (`E0461`), not the path.
|
||||
|
||||
**The only fix is a stage0 rustc whose host triple is musl** — that's what
|
||||
`build-stage0-musl.sh` produces (`CFG_COMPILER_HOST_TRIPLE` via `RUSTC_TARGET`,
|
||||
`--target` via `MRUSTC_TARGET`). Then host==target==musl: cargo doesn't
|
||||
cross-compile, proc-macros load natively, and `rustc_proxy.sh` only needs the
|
||||
CRT flags (no `--target` inject).
|
||||
|
||||
Gotcha: do **not** pass `OUTDIR_SUF` on make's command line — a command-line var
|
||||
can't be reassigned by the makefile, so the `-musl` suffix append is skipped and
|
||||
the build contaminates the gnu output dir. Let it default.
|
||||
|
||||
## Workflow
|
||||
|
||||
```sh
|
||||
# 1. apply the run_rustc patch into the mrustc clone
|
||||
git -C .scratch/mrustc apply scripts/rust-frontier/run_rustc.patch
|
||||
|
||||
# 2. rebuild stage0 rustc+cargo with a musl host triple (~hours, reuses LLVM)
|
||||
.scratch/build-stage0-musl.sh # -> output-1.90.0-x86_64-unknown-linux-musl/
|
||||
|
||||
# 3. build the optimised rustc + cargo via run_rustc (stage 1/2/3)
|
||||
.scratch/run-runrustc.sh all
|
||||
|
||||
# 4. (next) climb 1.90.0 → 1.91.0 → 1.91.1, then swap rust into /toolchain
|
||||
```
|
||||
|
||||
Full diagnostic history is in the `selfhost-verify-rust-frontier` memory.
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# Path A: rebuild the mrustc stage0 rustc+cargo with a MUSL host triple, so
|
||||
# CFG_COMPILER_HOST_TRIPLE=x86_64-unknown-linux-musl is baked in. This lets
|
||||
# run_rustc's cargo build proc-macros/build-scripts natively (host==target==musl)
|
||||
# without the proxy --target hack. LLVM + mrustc are reused (already built).
|
||||
# Output lands in output-1.90.0-x86_64-unknown-linux-musl/.
|
||||
set -eu
|
||||
ROOT=/home/sergio/hammer
|
||||
DEVFS=$ROOT/.dev-fs/alpine
|
||||
MRUSTC=$ROOT/.scratch/mrustc
|
||||
T=x86_64-unknown-linux-musl
|
||||
|
||||
run() {
|
||||
bwrap \
|
||||
--bind "$DEVFS" / \
|
||||
--bind "$MRUSTC" /mrustc \
|
||||
--dev /dev --proc /proc \
|
||||
--tmpfs /tmp --tmpfs /run \
|
||||
--setenv PATH /usr/bin:/bin:/usr/sbin:/sbin \
|
||||
--setenv HOME /root --setenv TMPDIR /tmp \
|
||||
--setenv MRUSTC_TARGET_VER 1.90 \
|
||||
--setenv CC gcc --setenv CXX g++ \
|
||||
--chdir /mrustc \
|
||||
make -f minicargo.mk \
|
||||
RUSTC_VERSION=1.90.0 \
|
||||
MRUSTC_TARGET=$T RUSTC_TARGET=$T \
|
||||
RUSTC_INSTALL_BINDIR=bin PARLEVEL=8 \
|
||||
"$@"
|
||||
}
|
||||
|
||||
echo "=== [1/3] LIBS (musl bootstrap std) ==="
|
||||
run LIBS
|
||||
echo "=== [2/3] rustc (musl host) ==="
|
||||
run output-1.90.0-$T/rustc
|
||||
echo "=== [3/3] cargo (musl host) ==="
|
||||
LIBGIT2_SYS_USE_PKG_CONFIG=1 run output-1.90.0-$T/cargo
|
||||
echo "=== DONE ==="
|
||||
ls -la output-1.90.0-$T/rustc output-1.90.0-$T/cargo
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
# Run a run_rustc make target inside the Alpine devfs sandbox (musl, 256-TLS loader, gcc).
|
||||
# Usage: run-runrustc.sh <make-target> [extra make args...]
|
||||
set -eu
|
||||
ROOT=/home/sergio/hammer
|
||||
DEVFS=$ROOT/.dev-fs/alpine
|
||||
MRUSTC=$ROOT/.scratch/mrustc
|
||||
TARGET=${1:?make target required}
|
||||
shift || true
|
||||
|
||||
exec bwrap \
|
||||
--bind "$DEVFS" / \
|
||||
--bind "$MRUSTC" /mrustc \
|
||||
--dev /dev --proc /proc \
|
||||
--tmpfs /tmp --tmpfs /run \
|
||||
--setenv PATH /usr/bin:/bin:/usr/sbin:/sbin \
|
||||
--setenv HOME /root \
|
||||
--setenv TMPDIR /tmp \
|
||||
--setenv MRUSTC_TARGET_VER 1.90 \
|
||||
--setenv CC gcc --setenv CXX g++ \
|
||||
--chdir /mrustc/run_rustc \
|
||||
make RUSTC_VERSION=1.90.0 OUTDIR_SUF=-1.90.0-x86_64-unknown-linux-musl \
|
||||
RUSTC_TARGET=x86_64-unknown-linux-musl PARLEVEL=8 \
|
||||
"$TARGET" "$@"
|
||||
@@ -0,0 +1,49 @@
|
||||
diff --git a/run_rustc/Makefile b/run_rustc/Makefile
|
||||
index e78d8c5..4d6ef5d 100644
|
||||
--- a/run_rustc/Makefile
|
||||
+++ b/run_rustc/Makefile
|
||||
@@ -108,7 +108,7 @@ CARGO_FLAGS := --target $(RUSTC_TARGET) -j $(PARLEVEL) --release --verbose
|
||||
CARGO_ENV := CFG_COMPILER_HOST_TRIPLE=$(RUSTC_TARGET)
|
||||
CARGO_ENV += RUSTC_BOOTSTRAP=1
|
||||
CARGO_ENV += CARGO_HOME=$(CARGO_HOME)
|
||||
-CARGO_ENV += RUSTFLAGS="-Z force-unstable-if-unmarked -C link_args=-Wl,-rpath,\$$ORIGIN/../lib -C target-feature=-crt-static"
|
||||
+CARGO_ENV += RUSTFLAGS="-Z force-unstable-if-unmarked -C link_args=-Wl,-rpath,\$$ORIGIN/../lib -C target-feature=-crt-static -C link-self-contained=no"
|
||||
|
||||
fn_opt_copy = (test -e "$2" && test ! "$1" -nt "$2") || cp "$1" "$2"
|
||||
|
||||
@@ -159,7 +159,7 @@ $(LIBDIR_S)libstd.rlib: $(BINDIR_S)rustc $(MINICARGO) Makefile
|
||||
@echo "[MINICARGO] $(RUST_SRC_LIBS)std > $(LIBDIR_S)"
|
||||
mkdir -p $(LIBDIR_S)
|
||||
ifneq ($(TARGETVER_LEAST_1_74),)
|
||||
- $V+STD_ENV_ARCH=$(RUSTC_ARCH) MRUSTC_PATH=$(abspath $(BINDIR_S)rustc) $(MINICARGO) --vendor-dir $(VENDOR_DIR) --script-overrides ../script-overrides/stable-$(RUSTC_VERSION)-$(PLATFORM)/ --output-dir $(LIBDIR_S) $(RUST_SRC_LIBS)sysroot
|
||||
+ $V+STD_ENV_ARCH=$(RUSTC_ARCH) MRUSTC_PATH=$(abspath $(BINDIR_S)rustc) $(MINICARGO) --vendor-dir $(VENDOR_DIR) --script-overrides ../script-overrides/stable-$(RUSTC_VERSION)-$(PLATFORM)/ --output-dir $(LIBDIR_S) --target $(RUSTC_TARGET) $(RUST_SRC_LIBS)sysroot
|
||||
else
|
||||
$V+MRUSTC_PATH=$(abspath $(BINDIR_S)rustc) $(MINICARGO) --vendor-dir $(VENDOR_DIR) --script-overrides ../script-overrides/stable-$(RUSTC_VERSION)-$(PLATFORM)/ --output-dir $(LIBDIR_S) $(RUST_SRC_LIBS)std
|
||||
$V+MRUSTC_PATH=$(abspath $(BINDIR_S)rustc) $(MINICARGO) --vendor-dir $(VENDOR_DIR) --script-overrides ../script-overrides/stable-$(RUSTC_VERSION)-$(PLATFORM)/ --output-dir $(LIBDIR_S) $(RUST_SRC_LIBS)panic_unwind
|
||||
@@ -169,7 +169,7 @@ endif
|
||||
# Build hello_world using the bootstrapping compiler (mrustc-built rustc)
|
||||
$(BINDIR_S)hello_world: $(RUST_SRC_HELLO) $(LIBDIR_S)libstd.rlib $(BINDIR_S)rustc
|
||||
@mkdir -p $(dir $@)
|
||||
- $V$(BINDIR_S)rustc $(RUSTFLAGS_$@) -L $(LIBDIR_S) $< -o $@
|
||||
+ $V$(BINDIR_S)rustc $(RUSTFLAGS_$@) --target $(RUSTC_TARGET) -C target-feature=-crt-static -C link-self-contained=no -L $(LIBDIR_S) $< -o $@
|
||||
|
||||
# ---
|
||||
# Stage 2: Build a proper libstd (which includes dynamc libraries too)
|
||||
diff --git a/run_rustc/rustc_proxy.sh b/run_rustc/rustc_proxy.sh
|
||||
index 3f4f2b9..78f6f1d 100755
|
||||
--- a/run_rustc/rustc_proxy.sh
|
||||
+++ b/run_rustc/rustc_proxy.sh
|
||||
@@ -17,7 +17,12 @@ if is_target "$@"; then
|
||||
#echo " [REAL]" "$@" >&2
|
||||
${PROXY_RUSTC} "$@"
|
||||
else
|
||||
+ # Host (build-script / proc-macro) build. With the musl-host stage0 rustc its
|
||||
+ # default target IS x86_64-unknown-linux-musl, so no --target inject is needed
|
||||
+ # (host==target==musl, proc-macros load natively). Just force dynamic +
|
||||
+ # non-self-contained so the Alpine gcc supplies the CRT (the mrustc sysroot has
|
||||
+ # no self-contained CRT dir, and musl's default is static-pie).
|
||||
#echo " [BOOTSTRAP]" "$@" >&2
|
||||
- ${PROXY_MRUSTC} "$@"
|
||||
+ ${PROXY_MRUSTC} -C target-feature=-crt-static -C link-self-contained=no "$@"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user