Skip to content

rust + go: bootstrap both language toolchains from the hex0-rooted, CS-attested chains - #667

Merged
bryan-minimal merged 19 commits into
mainfrom
bryan/rust-chain-attested
Sep 24, 2026
Merged

bryan-minimal merged 19 commits into
mainfrom
bryan/rust-chain-attested

Conversation

@bryan-minimal

@bryan-minimal bryan-minimal commented Aug 31, 2026 •

Copy link
Copy Markdown
Member

rust + go: bootstrap both toolchains from source, starting at hex0

packages/rust and packages/go currently start from a downloaded binary compiler (rust's stage0 snapshot from static.rust-lang.org, go's bootstrap toolchain from go.dev). This PR replaces both with chains of in-tree packages that begin at the 229-byte hex0 seed and end at the compilers rust and go build with today. No recipe in the chain touches the network at build time.

What is in the PR

38 new packages, 4 modified. They form four ladders plus two flips.

  1. stage0 ladder (stage0-*, amd64): hex0 → hex1 → kaem → mes → mescc → tcc 0.9.26 → tcc 0.9.27 → musl 1.1.24 → binutils 2.30 → gcc 4.0.4 → gcc 4.7.4 → gcc 10.4.0 → gcc 15.2.0, with gmp-mpfr-mpc, linux-headers, binutils-2.41, musl-1.2.5 and three tcc/musl relink steps (-s1/-s3/-s4) as the intermediate rungs. Each package builds only with what the previous rung installed. The early rungs are kaem scripts (*.kaem), the rest are build.sh.
  2. glibc-hosted toolchain: glibc-bedrock-2.42, binutils-2.46-glibc, gcc-15.2.0-glibc (C and C++). Built by the top of the stage0 ladder, installed under versioned prefixes (/usr/lib/glibc-bedrock-2.42, …) so they never collide with the distro toolchain. Every binary they produce is linked with an explicit dynamic linker and rpath into that prefix.
  3. rust ladder: mrustc (pinned upstream commit plus a patch series for aarch64 and shared-library builds, each patch documented in its header) builds mrustc-rustc-1.90.0 (rustc 1.90.0 + cargo + std). From there rustc-1.91.1 → 1.92.0 → 1.93.1 → 1.94.1 → 1.95.0 → 1.96.0, each rung a standard ./x.py build whose stage0 is the previous rung's install prefix. Each rung installs to /usr/lib/rustc-<version> and ships a functional gate (compile and run a program that exercises generics, trait objects, unwinding, TLS, proc-macros and cargo; the pass value is computed, never a literal).
  4. go ladder: go-1.4 (C-only root, built with the glibc-hosted gcc) → go-1.17.13 → go-1.20.14 → go-1.22.6 → go-1.24.9, each using the previous rung as GOROOT_BOOTSTRAP.
  5. packages/rust: stage0 is now the rustc-1.96.0 rung (bootstrap.toml [build] rustc/cargo point at its prefix, so x.py skips the snapshot download); the seed tarball Sources and the download fallback are gone, the stage0 is asserted by --version before the build starts, and cargo runs with CARGO_NET_OFFLINE=true. Runtime deps and outputs are unchanged.
  6. packages/go: bootstraps from go-1.24.9 on amd64 and from the sealed arm ladder artifact on arm64; the go.dev bindist Source is gone and a missing bootstrap is fatal. Version moves 1.26.6 → 1.27.0, which needed two small source bridges in otel-collector and trivy for go 1.27 API removals.

hex0 is the single binary trust root: a sha-pinned Source (amd64 seed and the sealed aarch64 seed).

How to review it efficiently

  • Clones. The rustc rungs, the go rungs and the two musl variants are byte-identical apart from version strings and stage0 pointers. Read one of each (rustc-1.93.1, go-1.20.14, stage0-musl-1.1.24) and diff -r it against its siblings; the diffs are a few lines each.
  • The two mechanisms that matter are in packages/rustc-*/build.sh (and, for stage0 pinning, packages/rust/build.sh): (a) stage0 pinning via bootstrap.toml, asserted at start by --version and --print sysroot against the expected prefix; (b) the rungs' offline harness: network tools on PATH replaced by stubs that exit non-zero, CARGO_NET_OFFLINE=true, and empty .git markers inside vendored *-sys crates so their build.rs never runs git submodule update.
  • Outputs. Every chain package exports only its own versioned prefix (one recursive OutputData glob). Ladder packages that legitimately ship ELF files as data (loaders, crt objects, musl's empty crti.o) use allow_executable / allow_data explicitly.
  • Architecture scope. The stage0 and rung packages are amd64-only and export empty collections on arm64. rust and go on arm64 consume the sealed arm-ladder artifacts as pinned Sources; the arm64 rust rungs above 1.90 are not built from source yet and are the next tranche.

Build cost

Ladder rungs take minutes each; mrustc-rustc-1.90.0 about an hour; each rustc rung 30 to 60 minutes; rust and go about an hour each. Cold, the whole chain is roughly a day of sequential build time; with a warm artifact cache only changed links rebuild. Byte-seal .answers files are present but unpinned; pinning is a data-only follow-up once each rung has two identical cold builds.

Follow-ups (not in this PR)

  • attrs metadata (license_spdx, upstream_version) for the stage0 and rung packages.
  • Express the tcc -s1/-s3/-s4 inputs as pristine source plus patch files instead of prepared tarballs.
  • arm64 rust rungs above 1.90 from source; pin the byte seals.

@coderabbitai

coderabbitai Bot commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 244 files, which is 94 over the limit of 150.

To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to Team to raise the limit.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Check out review usage here.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

⚙️ Run configuration

Configuration used: Repository: gominimal/pkgs/.coderabbit.yaml

Review profile: CHILL

Plan: Essentials

Run ID: 9d9c9ce6-cf5d-412a-a4ac-d5475dd8b721

📥 Commits

Reviewing files that changed from the base of the PR and between 79d15b4 and d9cbb47.

📒 Files selected for processing (244)
  • packages/binutils-2.46-glibc/build.ncl
  • packages/binutils-2.46-glibc/build.sh
  • packages/binutils-2.46-glibc/stage0.answers
  • packages/gcc-15.2.0-glibc/build.ncl
  • packages/gcc-15.2.0-glibc/build.sh
  • packages/gcc-15.2.0-glibc/stage0.answers
  • packages/glibc-bedrock-2.42/build.ncl
  • packages/glibc-bedrock-2.42/build.sh
  • packages/go-1.17.13/build.ncl
  • packages/go-1.17.13/build.sh
  • packages/go-1.20.14/build.ncl
  • packages/go-1.20.14/build.sh
  • packages/go-1.22.6/build.ncl
  • packages/go-1.22.6/build.sh
  • packages/go-1.24.9/build.ncl
  • packages/go-1.24.9/build.sh
  • packages/go-1.4/build.ncl
  • packages/go-1.4/build.sh
  • packages/go/build.ncl
  • packages/go/build.sh
  • packages/hex0/build.ncl
  • packages/hex0/build.sh
  • packages/mrustc-rustc-1.90.0/README.md
  • packages/mrustc-rustc-1.90.0/build.ncl
  • packages/mrustc-rustc-1.90.0/build.sh
  • packages/mrustc-rustc-1.90.0/gate190.rs
  • packages/mrustc-rustc-1.90.0/gate_pm.rs
  • packages/mrustc-rustc-1.90.0/gate_pm_use.rs
  • packages/mrustc-rustc-1.90.0/gatelib.rs
  • packages/mrustc-rustc-1.90.0/rustc-1.90.0.answers
  • packages/mrustc/aarch64-support.patch
  • packages/mrustc/archive-zerolen-skip.sh
  • packages/mrustc/build.ncl
  • packages/mrustc/build.sh
  • packages/mrustc/gate.rs
  • packages/mrustc/hir-ord-unevaluated.patch
  • packages/mrustc/mrustc.answers
  • packages/otel-collector/build.sh
  • packages/rust/bootstrap.toml
  • packages/rust/build.ncl
  • packages/rust/build.sh
  • packages/rustc-1.91.1/README.md
  • packages/rustc-1.91.1/build.ncl
  • packages/rustc-1.91.1/build.sh
  • packages/rustc-1.91.1/gate_pm.rs
  • packages/rustc-1.91.1/gate_pm_use.rs
  • packages/rustc-1.91.1/gatelib.rs
  • packages/rustc-1.91.1/gatestd.rs
  • packages/rustc-1.91.1/rustc-1.91.1.answers
  • packages/rustc-1.92.0/README.md
  • packages/rustc-1.92.0/build.ncl
  • packages/rustc-1.92.0/build.sh
  • packages/rustc-1.92.0/gate_pm.rs
  • packages/rustc-1.92.0/gate_pm_use.rs
  • packages/rustc-1.92.0/gatelib.rs
  • packages/rustc-1.92.0/gatestd.rs
  • packages/rustc-1.92.0/rustc-1.92.0.answers
  • packages/rustc-1.93.1/README.md
  • packages/rustc-1.93.1/build.ncl
  • packages/rustc-1.93.1/build.sh
  • packages/rustc-1.93.1/gate_pm.rs
  • packages/rustc-1.93.1/gate_pm_use.rs
  • packages/rustc-1.93.1/gatelib.rs
  • packages/rustc-1.93.1/gatestd.rs
  • packages/rustc-1.93.1/rustc-1.93.1.answers
  • packages/rustc-1.94.1/README.md
  • packages/rustc-1.94.1/build.ncl
  • packages/rustc-1.94.1/build.sh
  • packages/rustc-1.94.1/gate_pm.rs
  • packages/rustc-1.94.1/gate_pm_use.rs
  • packages/rustc-1.94.1/gatelib.rs
  • packages/rustc-1.94.1/gatestd.rs
  • packages/rustc-1.94.1/rustc-1.94.1.answers
  • packages/rustc-1.95.0/README.md
  • packages/rustc-1.95.0/build.ncl
  • packages/rustc-1.95.0/build.sh
  • packages/rustc-1.95.0/gate_pm.rs
  • packages/rustc-1.95.0/gate_pm_use.rs
  • packages/rustc-1.95.0/gatelib.rs
  • packages/rustc-1.95.0/gatestd.rs
  • packages/rustc-1.95.0/rustc-1.95.0.answers
  • packages/rustc-1.96.0/README.md
  • packages/rustc-1.96.0/build.ncl
  • packages/rustc-1.96.0/build.sh
  • packages/rustc-1.96.0/gate_pm.rs
  • packages/rustc-1.96.0/gate_pm_use.rs
  • packages/rustc-1.96.0/gatelib.rs
  • packages/rustc-1.96.0/gatestd.rs
  • packages/rustc-1.96.0/rustc-1.96.0.answers
  • packages/rustc-1.97.1/README.md
  • packages/rustc-1.97.1/build.ncl
  • packages/rustc-1.97.1/build.sh
  • packages/rustc-1.97.1/gate_pm.rs
  • packages/rustc-1.97.1/gate_pm_use.rs
  • packages/rustc-1.97.1/gatelib.rs
  • packages/rustc-1.97.1/gatestd.rs
  • packages/rustc-1.97.1/rustc-1.97.1.answers
  • packages/stage0-binutils-2.30/build.ncl
  • packages/stage0-binutils-2.30/build.sh
  • packages/stage0-binutils-2.30/libiberty-add-missing-config-directory-reference.patch
  • packages/stage0-binutils-2.30/new-gettext.patch
  • packages/stage0-binutils-2.30/opcodes-ensure-i386-init-dependencies-are-satisfied.patch
  • packages/stage0-binutils-2.30/stage0.answers
  • packages/stage0-binutils-2.41/build.ncl
  • packages/stage0-binutils-2.41/build.sh
  • packages/stage0-binutils-2.41/stage0.answers
  • packages/stage0-gcc-10.4.0/build.ncl
  • packages/stage0-gcc-10.4.0/build.sh
  • packages/stage0-gcc-10.4.0/stage0.answers
  • packages/stage0-gcc-15.2.0/build.ncl
  • packages/stage0-gcc-15.2.0/build.sh
  • packages/stage0-gcc-15.2.0/stage0.answers
  • packages/stage0-gcc-4.0.4/build.ncl
  • packages/stage0-gcc-4.0.4/build.sh
  • packages/stage0-gcc-4.0.4/stage0.answers
  • packages/stage0-gcc-4.7.4/build.ncl
  • packages/stage0-gcc-4.7.4/build.sh
  • packages/stage0-gcc-4.7.4/stage0.answers
  • packages/stage0-gmp-mpfr-mpc/build.ncl
  • packages/stage0-gmp-mpfr-mpc/build.sh
  • packages/stage0-hex1/build.ncl
  • packages/stage0-hex1/build.sh
  • packages/stage0-kaem/bootstrap.kaem
  • packages/stage0-kaem/build.ncl
  • packages/stage0-kaem/stage0.answers
  • packages/stage0-linux-headers-6.12.43/build.ncl
  • packages/stage0-linux-headers-6.12.43/build.sh
  • packages/stage0-mes/build.ncl
  • packages/stage0-mes/config.h
  • packages/stage0-mes/mes.answers
  • packages/stage0-mes/mes.kaem
  • packages/stage0-mescc-full/build.ncl
  • packages/stage0-mescc-full/mescc-full.kaem
  • packages/stage0-mescc-full/simple-patch.c
  • packages/stage0-mescc-full/stage0.answers
  • packages/stage0-mescc/build.ncl
  • packages/stage0-mescc/mescc.kaem
  • packages/stage0-mescc/stage0.answers
  • packages/stage0-musl-1.1.24-cc2/amd64-syscall-arch.patch
  • packages/stage0-musl-1.1.24-cc2/amd64-va-list.patch
  • packages/stage0-musl-1.1.24-cc2/avoid_sys_clone.patch
  • packages/stage0-musl-1.1.24-cc2/build.ncl
  • packages/stage0-musl-1.1.24-cc2/build.sh
  • packages/stage0-musl-1.1.24-cc2/disable_ctype_headers.patch
  • packages/stage0-musl-1.1.24-cc2/drop-dynamic-crt.patch
  • packages/stage0-musl-1.1.24-cc2/madvise_preserve_errno.patch
  • packages/stage0-musl-1.1.24-cc2/makefile.patch
  • packages/stage0-musl-1.1.24-cc2/skip-pic-crt.patch
  • packages/stage0-musl-1.1.24-cc2/stage0.answers
  • packages/stage0-musl-1.1.24/amd64-syscall-arch.patch
  • packages/stage0-musl-1.1.24/amd64-va-list.patch
  • packages/stage0-musl-1.1.24/avoid_sys_clone.patch
  • packages/stage0-musl-1.1.24/build.ncl
  • packages/stage0-musl-1.1.24/build.sh
  • packages/stage0-musl-1.1.24/disable_ctype_headers.patch
  • packages/stage0-musl-1.1.24/drop-dynamic-crt.patch
  • packages/stage0-musl-1.1.24/madvise_preserve_errno.patch
  • packages/stage0-musl-1.1.24/makefile.patch
  • packages/stage0-musl-1.1.24/skip-pic-crt.patch
  • packages/stage0-musl-1.1.24/stage0.answers
  • packages/stage0-musl-1.2.5/build.ncl
  • packages/stage0-musl-1.2.5/build.sh
  • packages/stage0-musl-1.2.5/stage0.answers
  • packages/stage0-tcc-0.9.26/addback-fileopen.after
  • packages/stage0-tcc-0.9.26/addback-fileopen.before
  • packages/stage0-tcc-0.9.26/build.ncl
  • packages/stage0-tcc-0.9.26/fix-mul.after
  • packages/stage0-tcc-0.9.26/fix-mul.before
  • packages/stage0-tcc-0.9.26/fix-plt.after
  • packages/stage0-tcc-0.9.26/fix-plt.before
  • packages/stage0-tcc-0.9.26/fix-setjmp.after
  • packages/stage0-tcc-0.9.26/fix-setjmp.before
  • packages/stage0-tcc-0.9.26/fix-shift.after
  • packages/stage0-tcc-0.9.26/fix-shift.before
  • packages/stage0-tcc-0.9.26/fix-stdarg.after
  • packages/stage0-tcc-0.9.26/fix-stdarg.before
  • packages/stage0-tcc-0.9.26/fix-swapb.after
  • packages/stage0-tcc-0.9.26/fix-swapb.before
  • packages/stage0-tcc-0.9.26/fix-swapf.after
  • packages/stage0-tcc-0.9.26/fix-swapf.before
  • packages/stage0-tcc-0.9.26/fix-vararg.after
  • packages/stage0-tcc-0.9.26/fix-vararg.before
  • packages/stage0-tcc-0.9.26/remove-fileopen.after
  • packages/stage0-tcc-0.9.26/remove-fileopen.before
  • packages/stage0-tcc-0.9.26/simple-patch.c
  • packages/stage0-tcc-0.9.26/stage0.answers
  • packages/stage0-tcc-0.9.26/tcc.kaem
  • packages/stage0-tcc-0.9.27-musl-s1/build.ncl
  • packages/stage0-tcc-0.9.27-musl-s1/build.sh
  • packages/stage0-tcc-0.9.27-musl-s3/build.ncl
  • packages/stage0-tcc-0.9.27-musl-s3/build.sh
  • packages/stage0-tcc-0.9.27-musl-s4/build.ncl
  • packages/stage0-tcc-0.9.27-musl-s4/build.sh
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_args.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_args.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_bigframe.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_bigframe.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_float.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_float.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_longlong.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_longlong.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_mul.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_mul.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_recursion.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_recursion.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_setjmp.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_setjmp.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_shift.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_shift.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_struct.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_struct.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_switch.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_switch.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_varargs.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_varargs.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_xobj.expected
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_xobj_lib.c
  • packages/stage0-tcc-0.9.27-musl-s4/torture/t_xobj_main.c
  • packages/stage0-tcc-0.9.27/addback-fileopen.after
  • packages/stage0-tcc-0.9.27/addback-fileopen.before
  • packages/stage0-tcc-0.9.27/build.ncl
  • packages/stage0-tcc-0.9.27/cast-signed-direct.after
  • packages/stage0-tcc-0.9.27/cast-signed-direct.before
  • packages/stage0-tcc-0.9.27/check-reloc-null.after
  • packages/stage0-tcc-0.9.27/check-reloc-null.before
  • packages/stage0-tcc-0.9.27/dont-skip-weak-symbols-ar.after
  • packages/stage0-tcc-0.9.27/dont-skip-weak-symbols-ar.before
  • packages/stage0-tcc-0.9.27/fiwix-paddr.after
  • packages/stage0-tcc-0.9.27/fiwix-paddr.before
  • packages/stage0-tcc-0.9.27/fix-setjmp.after
  • packages/stage0-tcc-0.9.27/fix-setjmp.before
  • packages/stage0-tcc-0.9.27/fix-stdarg.after
  • packages/stage0-tcc-0.9.27/fix-stdarg.before
  • packages/stage0-tcc-0.9.27/ignore-static-inside-array.after
  • packages/stage0-tcc-0.9.27/ignore-static-inside-array.before
  • packages/stage0-tcc-0.9.27/neg-float-const.after
  • packages/stage0-tcc-0.9.27/neg-float-const.before
  • packages/stage0-tcc-0.9.27/remove-fileopen.after
  • packages/stage0-tcc-0.9.27/remove-fileopen.before
  • packages/stage0-tcc-0.9.27/stage0.answers
  • packages/stage0-tcc-0.9.27/static-link.after
  • packages/stage0-tcc-0.9.27/static-link.before
  • packages/stage0-tcc-0.9.27/tcc.kaem
  • packages/trivy/build.sh

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing

Comment @coderabbitai help to get the list of available commands.

bryan-minimal added a commit that referenced this pull request Sep 2, 2026
…ader lists, s1 comment corrected

Consumer-verified (PR comment 5500513628): no rung reads R4a's or R4b's merged /usr copies any
more — s3 (-nostdinc/-nostdlib vs the §E sysroot), s4/R5 (-nostdinc -I $MB/include), gcc-4.0.4
(CPATH/LIBRARY_PATH/LIBGCC2_INCLUDES already at /usr/lib/musl-bedrock; its comment said
-I/usr/include and was stale).  Dropping usr/include/** + usr/lib/{libc.a,*.o,*.a} from both
removes two contenders from the first-writer-wins header draw in every downstream sandbox.
binutils-2.30/2.41: headers = explicit bfd.h-class brace list (absent names match nothing).
s1: the mes-first -I comment overclaimed — mes ships its libc headers at the TOP level and only
9 names under /usr/include/mes/, so s1 is still draw-dependent; mesl_roll is the real mitigation.

Each narrowed pkg gets a build.sh RE-CAPTURE BUMP (outputs are not in the spec hash).
Spec-hash diff via minimal dump: arm64 0 changed; amd64 158 changed = everything above R4a
(expected: one cold amd64 round).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@bryan-minimal
bryan-minimal marked this pull request as ready for review September 3, 2026 21:35
@bryan-minimal
bryan-minimal requested review from jtnkminimal, msample and twitchyliquid64 and removed request for twitchyliquid64 September 3, 2026 21:35
hex0 (sha-pinned seed) -> hex1 -> kaem -> mes -> mescc -> tcc 0.9.26/0.9.27 -> musl 1.1.24 -> binutils 2.30 ->
gcc 4.0.4 -> 4.7.4 -> 10.4.0 -> 15.2.0, with gmp/mpfr/mpc, linux-headers, binutils 2.41, musl 1.2.5 and the
tcc/musl relink steps as intermediate rungs. Each package builds only with what the previous rung installed.
amd64-only; the packages export empty collections on arm64.
…15.2.0-glibc

Built by the top of the stage0 ladder and installed under versioned prefixes so they never collide with the
distro toolchain. Binaries they produce are linked with an explicit dynamic linker and rpath into that prefix.
gcc ships C and C++; each package carries a compile-and-run gate.
mrustc at a pinned upstream commit plus a patch series (aarch64 and shared-library fixes, each documented in its
header) builds rustc 1.90.0 with cargo and std from the rustc-1.90.0 source tarball, fully offline, into
/usr/lib/mrustc-rust-1.90.0. Functional gates compile and run programs covering generics, trait objects,
unwinding, TLS, proc-macros and cargo.
Standard ./x.py build with bootstrap.toml [build] rustc/cargo pinned at the previous rung's install prefix, so
the stage0 snapshot download never happens; network tools are stubbed to fail closed and vendored *-sys crates
get empty .git markers. Each rung installs to /usr/lib/rustc-<version> and ships the same functional gate set.
The directories differ only in versions and stage0 pointers.
…14 -> 1.22.6 -> 1.24.9 rungs

go-1.4 (C-only root) is built with the glibc-hosted gcc; each later rung uses the previous one as
GOROOT_BOOTSTRAP. packages/go bootstraps from go-1.24.9 on amd64 and from the sealed arm ladder artifact on
arm64; the go.dev bindist Source is removed and a missing bootstrap is fatal. Version 1.26.6 -> 1.27.0, with
source bridges in otel-collector and trivy for go 1.27 API removals.
bootstrap.toml [build] rustc/cargo point at the rustc-1.96.0 package's prefix; the seed tarball Sources and the
download fallback are removed, the stage0 is asserted by --version before the build, and cargo runs with
CARGO_NET_OFFLINE=true. On arm64 the stage0 is the sealed arm ladder artifact. Runtime deps and outputs are
unchanged.
@bryan-minimal
bryan-minimal force-pushed the bryan/rust-chain-attested branch from 2f2f8bc to 336bba3 Compare September 16, 2026 17:56
@bryan-minimal
bryan-minimal removed the request for review from twitchyliquid64 September 16, 2026 18:25

@0chroma 0chroma left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: rust + go hex0-rooted bootstrap chains

Reviewed the full branch. CI is green (minimal-check and a full minimal build pass); note CodeRabbit skipped this PR entirely — 236 files exceed its 150-file limit — so this needs human eyes.

Verified correct

  • Ladder consistency. Every GOROOT_BOOTSTRAP / stage0 prefix resolves to a package present in that file's build_deps; no dependency cycles. Min-bootstrap versions line up: go1.27 needs ≥1.24.6, the 1.24.9 rung's own minBootstrap is exactly its predecessor 1.22.6, earlier rungs still accept the go1.4 default.
  • Hashes. Source shas recomputed against upstream for go 1.17.13/1.20.14/1.22.6/1.24.9/1.27.0, glibc-2.42, binutils 2.30/2.41/2.46, gcc 4.0.4/4.7.4/10.4.0/15.2.0, musl, gmp/mpfr/mpc, mes, tcc, linux-6.12.43 — all match. Arch prebuilt shas are pinned and match their URL path segments.
  • Stage0 pinning. --version / --print sysroot / src/version+src/stage0 assertions abort on mismatch; stub PATH dirs are genuinely prepended with the curl/git shadowing asserted; CARGO_NET_OFFLINE=true; the vendor.rs sed patch fails closed (grep before and after, exit 1).
  • Gates. Pass values are computed from guarded sums, never literals; each gated command is rc-captured so set -e can't short-circuit.
  • go-1.27 bridges. trivy 0.74.0 has exactly the two json.SkipFunc sites the rewrite targets and errors.ErrUnsupported is the documented replacement; otel 0.159.0's manifest has a replaces: block and no swiss mention, and the pinned swiss pseudo-version carries the right build guard.

Findings

  1. Dead arm64 prebuilt branches — glibc-bedrock-2.42/build.ncl, binutils-2.46-glibc/build.ncl, gcc-15.2.0-glibc/build.ncl: the inner match supplies an 'Arm64 prebuilt Source, but the outer match collapses arm64 to an empty BuildSpec. Those Sources are never fetched and the build.sh aarch64 blocks are unreachable. Harmless functionally (arm64 doesn't consume these), but the comments claiming "on aarch64 the prebuilt is extracted instead" are false.
  2. stage0-tcc-0.9.27-musl-s1/build.sh:38 — on extract/cd failure it copies /usr/bin/tcc-0.9.26 to $OUTPUT_DIR/usr/bin/tcc-musl and exits 0, so a failure mode installs a mislabeled binary that would be cached. Every other path in this PR fails shut; this one should too.
  3. s1/s3 are retry-driven, not gated — they run under set +e with an env-layout perturbation loop (4–6 tries) and ship no stage0.answers. A first-try success is deterministic, but nothing pins that it happened.
  4. Reproducibility seals are inert — most later rungs' sha256sum -c gates are commented out / SEAL_FATAL=0, *.answers are # UNPINNED, and the six rustc rungs don't declare .answers as a Local dep at all, so the seal check at rustc-1.95.0/build.sh:604 is dead code. The PR body discloses pinning as a follow-up — this is just a request to track it somewhere concrete.
  5. packages/rust diverges from the chain's own claims — unlike every rung it has no curl/wget/git stubs and no network tripwire, and build.ncl still declares needs = { dns, internet }, while the headline is "no recipe in the chain touches the network at build time." Either add the tripwire or state in the PR why the top-level package is deliberately exempt.
  6. Comment drift — rustc-1.94.1/build.ncl:3 says its stage0 is "the rustc-1.94.1 package" (should be 1.93.1); binutils-2.46-glibc/build.ncl:3 says "same sha as packages/binutils" but that package is now 2.47; glibc-bedrock-2.42/build.ncl similarly vs glibc 2.44.
  7. Nits — the "OutputBin's checker rejects the interpreter" rationale is inaccurate (OutputBin only special-cases shebang scripts, never ELF interpreters); the find ./*/ -delete clean-state blocks are safe only because every Source is extract=false; a few import identifiers don't match package names (stage0-tcc-r2, stage0-cc, stage0-binutils-r10, …).

The ladder machinery is solid and the central claims hold. Findings 1–2 are quick fixes and 3–5 are worth addressing or explicitly waiving before this lands. Not blocking on my side, but I didn't want it to merge on a green CI + bot-skip alone.

@bryan-minimal

bryan-minimal commented Sep 18, 2026 •

Copy link
Copy Markdown
Member Author

Thanks for the careful read. Fixes for 1, 2, 4, 5, 6 and 7 are in b638f0a; 3 and part of 4 are waived below with the reasoning.

  1. Dead arm64 Source arms — removed the inner match in all three -glibc specs (the amd64 Source is now unconditional inside amd64_spec) and the unreachable aarch64 blocks in their build.sh.
  2. s1 fallback — an extract or cd failure now exits 1. Nothing is copied into $OUTPUT_DIR on that path any more.
  3. s1/s3 retry loops — waived, with the reasoning on record: the perturbation loop exists because mes-m2's arena layout makes the first tcc compile a coin flip (an ASLR-shaped lottery in the seed compiler, not in our recipes; root-caused separately). The loop only re-runs the identical compile until it does not crash; a run that completes produces the same bytes. The rung pins for s1/s3 are in the same tracking item as 4.
  4. Seals inert — the six rustc rungs now declare rustc-<v>.answers as a Local input, so the seal check in build.sh reads a real file instead of being dead code. The pins themselves stay # UNPINNED in this PR: cutting them needs a second cold build per rung on the merged recipes, which is the follow-up already listed in the description. It stays on the follow-ups list in the description.
  5. packages/rust tripwire — added the same curl/wget/git stub harness the rungs use (PATH precedence asserted, NETWORK-TRIPWIRE checked after install) and dropped needs = { dns, internet }. The top-level package now makes the same claim as the chain.
  6. Comment drift — fixed all three.
  7. Nits — the OutputBin rationale now says why the binutils programs are OutputData (consumers reach them by absolute path under the package's own prefix); the stage0 imports are named after their packages instead of ladder-rung labels. The find ./*/ -delete blocks are indeed safe only because every Source is extract = false; that is the invariant those recipes rely on, and it is stated next to each.

Note for the merge: the s1 and -glibc build.sh changes move spec hashes at the bottom of the chain, so buildbot will run a cold chain build again after this push.

…t offline tripwire, seal answers declared, comment drift, package-name imports

- stage0-tcc-0.9.27-musl-s1: an extract failure exits 1 instead of shipping tcc-0.9.26 as tcc-musl
- glibc-bedrock-2.42 / binutils-2.46-glibc / gcc-15.2.0-glibc: the arm64 Source arm and the
  aarch64 build.sh block were unreachable (the outer match makes arm64 an empty spec); removed
- rust: the rungs' curl/wget/git stub harness and NETWORK-TRIPWIRE check; `needs` dropped
- rustc-1.91.1..1.96.0: the .answers file is a declared Local input, so the seal check can read it
- comments: rustc-1.94.1's stage0 is 1.93.1; the -glibc trio no longer claims parity with the
  production binutils/glibc versions; OutputData rationale for the binutils programs
- stage0 imports named after their packages instead of ladder-rung labels

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@bryan-minimal
bryan-minimal requested a review from a team as a code owner September 18, 2026 19:19
… so build.rs never calls git submodule

The tripwire added in the previous commit fired on `git submodule update --init curl` from the
vendored curl-sys build.rs: the rungs pre-empt that call with an empty .git marker in the bundled
submodule dir. Same block, same rationale.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@bryan-minimal

Copy link
Copy Markdown
Member Author

Follow-up 318d00c: the new rust tripwire fired on buildbot on git submodule update --init curl from the vendored curl-sys build.rs (the build itself had completed; the stub had refused the call). The rungs pre-empt that call with their P0c block, an empty .git marker in the bundled submodule dir; ported the same block to packages/rust.

bryan-minimal added a commit that referenced this pull request Sep 19, 2026
The build failed on both arches in seconds:

  error: rustc 1.97.1 is not supported by the following packages:
    atuin@18.22.0 requires rustc 1.98.0

packages/rust is on 1.97.1; latest stable is 1.98.1. Bumping the Rust
toolchain rotates spec hashes for the 121 packages that import rust or go, and
packages/rust/build.ncl is also rewritten by the in-flight hex0 bootstrap work
(#667), so that bump wants to be a deliberate, scheduled change rather than a
side effect of a routine version sweep.

Dropping this one package lets the other six updates in this stack land. atuin
comes back with the Rust bump.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Sep 19, 2026
bryan-minimal and others added 2 commits September 20, 2026 11:20
…ess from it

The builder ORs `needs` over a package's dependencies; the Rust programs that depend on rust fetch
their crates during their own builds and were getting network through this flag. rust's own build
stays offline: build.sh stubs curl/wget/git and fails on any attempt (NETWORK-TRIPWIRE).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@bryan-minimal

Copy link
Copy Markdown
Member Author

32d7df3 restores needs = { dns, internet } on packages/rust. Dropping it for finding 5 broke the Rust programs downstream: the builder grants network to a package when any of its dependencies declares needs.internet (minimal crates/op/src/specs.rs, the OR over dependencies), and ripgrep and friends fetch their crates during their own builds through that inherited flag (buildbot: cargo build → crates.io → TLS verify failed without the sandbox network setup). rust's own build stays offline and tripwired; the comment on the flag now says why it is there.

@bryan-minimal
bryan-minimal added this pull request to the merge queue Sep 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Sep 24, 2026
@bryan-minimal
bryan-minimal added this pull request to the merge queue Sep 24, 2026
Merged via the queue into main with commit d0b0026 Sep 24, 2026
12 checks passed
@bryan-minimal
bryan-minimal deleted the bryan/rust-chain-attested branch September 24, 2026 23:33
bryan-minimal added a commit that referenced this pull request Sep 29, 2026
- packages/go/build.ncl: keep main's hex0-bootstrapped, source-built shape
  (#667); bump it to 1.27.1 with the 1.27.1 source sha256 (verified against
  go.dev's published checksum and by hashing the tarball). The branch's
  prebuilt amd64 url/sha is obsolete under #667.
- packages/otel-collector/build.sh: take main's Go-1.27 swiss pin; drop the
  branch's duplicate (main's guard exits if swiss is already pinned).
- packages/trivy/build.sh (semantic conflict git didn't flag): keep this
  branch's upstream json/v2 patch (trivy dc3c56eed5, also handles
  json:",inline") and drop #667's sed SkipFunc bridge, which deliberately
  exits 1 when no json.SkipFunc is left, i.e. after the patch has run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bryan-minimal added a commit that referenced this pull request Sep 29, 2026
croc >= 11.5.2 declares go 1.27.0; this branch last built against go 1.26
and failed. Main is now on go 1.27.0 (hex0-bootstrapped, #667), so the bump
no longer waits on #758. No conflicts; vs main the branch still changes only
packages/croc/build.ncl.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
cvince pushed a commit to capysc/pkgs that referenced this pull request Oct 2, 2026
…ak each other (gominimal#671)

* fix(pnpm): depend on node, not node-lts — two npms in one sandbox breaks both

pnpm only needs *a* node for its `#!/usr/bin/env node` shebang, but whichever
one it names enters the closure of every package built with pnpm. `next` and
`agent-browser` both declare `node` themselves, so each sandbox held TWO npm
installs at the same paths.

The sandbox hardlinks closure members first-writer-wins PER FILE, so
/usr/lib/node_modules/npm came out a blend: minipass-flush/index.js from npm
11.17.0 (named `{ Minipass }` import) beside a nested minipass@3.3.6 from npm
11.11.1 (default export only). That tree never existed upstream and cannot
load — `class Flush extends undefined` throws and every `npm install` dies.
It broke `next` for two days and blocked gominimal#665, gominimal#667, gominimal#669 and gominimal#659.

Verified: closure of next 75->74 and agent-browser 114->113 with node-lts gone,
capy (the only other node-lts consumer) untouched; next, pnpm and agent-browser
each build --rebuild clean and pass min check 15/15.

Supersedes gominimal#670, whose fix was a no-op against node-lts's own output.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refine: take only the node BINARY, not the whole package

Review point from Bryan: pnpm should not be dictating a node version to its
consumers at all. The spec language cannot express that today — RuntimeDep is
BuildSpec | Subset | UpstreamPkg, all concrete, with no "consumer provides it"
form — but `subsetOf` gets most of the way there.

pnpm needs a node to interpret `#!/usr/bin/env node` and nothing else. Taking
`subsetOf node ["node"]` instead of the whole package means pnpm can never
contribute an npm tree to any closure, so the two-npms-merged-per-file failure
is structurally impossible rather than merely absent from today's fleet.

Residual, and worth stating: pnpm still names a version, so a future node-lts
consumer adding pnpm would collide on the `node` binary. That is a much smaller
failure than an unloadable module graph, and the real fix is a virtual/provided
dependency in the spec language.

Verified with the subset: next, pnpm and agent-browser all build --rebuild
clean and pass min check, including pnpm's `missing runtime_deps` — which
independently confirms the bare binary satisfies the shebang.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
cvince pushed a commit to capysc/pkgs that referenced this pull request Oct 2, 2026
* Update age to 1.3.2

* Update ast-grep to 0.45.3

* Update atuin to 18.22.0

* Update bash-completions to 2.18.0

* Update bash-language-server to 5.8.0

* Update bzip3 to 1.5.4

* Update chezmoi to 2.72.2

* Hold atuin at 18.19.0: 18.22.0 needs rustc 1.98.0, we ship 1.97.1

The build failed on both arches in seconds:

  error: rustc 1.97.1 is not supported by the following packages:
    atuin@18.22.0 requires rustc 1.98.0

packages/rust is on 1.97.1; latest stable is 1.98.1. Bumping the Rust
toolchain rotates spec hashes for the 121 packages that import rust or go, and
packages/rust/build.ncl is also rewritten by the in-flight hex0 bootstrap work
(gominimal#667), so that bump wants to be a deliberate, scheduled change rather than a
side effect of a routine version sweep.

Dropping this one package lets the other six updates in this stack land. atuin
comes back with the Rust bump.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: gominimal-pkgmgr-mgr[bot] <285843623+gominimal-pkgmgr-mgr[bot]@users.noreply.github.com>
Co-authored-by: bryan <bryan@minimal.dev>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
cvince pushed a commit to capysc/pkgs that referenced this pull request Oct 2, 2026
Mirrors gominimal#727's go 1.26.6 -> 1.26.8. Both bumps exist for the same reason: the
routine package sweeps have started landing upstream releases whose toolchain
floor is above what we ship. pkgs#725 failed on

  error: rustc 1.97.1 is not supported by the following packages:
    atuin@18.22.0 requires rustc 1.98.0

atuin is held at 18.19.0 on that branch until this lands.

1.98.1 is current stable and one patch above atuin's floor. Source tarball
mirrored to gs://minimal-staging-archives/rustc-1.98.1-src.tar.xz: downloaded
from static.rust-lang.org, sha256 verified against the upstream .sha256 file
(be1816e7...), uploaded, then re-read back out of the bucket and re-hashed to
confirm the round trip. That matches the existing convention — the mirrored
1.97.1 object hashes to exactly the sha256 upstream publishes.

Only the version and source hash change.  pins
 with no version, and  carries no version
references, so nothing else in the recipe moves.

Note for scheduling: this rotates spec hashes for the packages that import
rust, and packages/rust/build.ncl is also rewritten by the hex0 bootstrap work
in gominimal#667 — expect a conflict there whichever lands second.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
cvince pushed a commit to capysc/pkgs that referenced this pull request Oct 2, 2026
…al#734)

Every cold bun build on res-server-arm64 (c4a-standard-72) stalls at the
same line — 'zig obj -> bun-zig.{0..71}.o' — and sits there with zero cache
writes until the 6h watchdog kills the run. Three sandboxes, 2026-09-19/20/21,
two of them on gominimal#667 (which rotates bun's spec hash via rust). amd64 with 144
shards completes in ~4 min. The fast arm64 'successes' in the run history are
cache hydrations, not compiles.

bun's local profile sets -Dllvm_codegen_threads=availableParallelism()
(scripts/build/zig.ts codegenThreads); upstream CI never exceeds 8 shards and
shipped releases use 1. Pin arm64 to 8 with the same sed+verify-grep pattern
as the lol-html patch (gominimal#228). This PR's own build is the experiment: a cold
arm64 bun build either completes, or hangs again and we capture the process
tree live.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
evanspearman pushed a commit to evanspearman/pkgs that referenced this pull request Oct 20, 2026
…ea, openjdk-9..25) (gominimal#775)

* jvm: bootstrap OpenJDK from source (jikes/jamvm/classpath root, icedtea, openjdk-9..25)

Clean re-cut of bryan/jvm-ladder onto main d0b0026: only the ladder package
directories, none of the stale pre-gominimal#667 chain that branch carried.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jvm: the base packages the ladder imports (zip, fastjar, which, ant-bootstrap, giflib, libICE/libSM/libXt)

The clean re-cut carried only the rung directories; these eight are imported by
classpath, ecj4-bootstrap, icedtea and the openjdk rungs and were left on the
test branch. Sources are all mirrored in the staging bucket.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* which: keep main's 2.25 (the ladder only needs the package, not its 2.21 copy)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jvm: nickel format

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jvm: import aliases named after their folders

minimal's imports checker requires a bare-word import alias to equal the folder it
imports; dashed aliases follow the ghc-9-6-7 convention (dots become dashes).
Variable references only; record keys and strings are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jvm rungs: pkgmgr freeze marker

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* giflib, fastjar: build in the sandbox

giflib: build the library targets only; `all` also builds the utilities and runs
doc/ through ImageMagick's convert, which the sandbox does not have.
fastjar: the bundled 2008 config.guess/config.sub predate aarch64, so the modern
GNU pair comes in as Sources (as libtecla does); zlib was an undeclared dependency.

Both verified with a bare PATH on amd64 and arm64 lab VMs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jvm ladder: re-run the buildbot

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jvm ladder: re-run the buildbot with the upload retry deployed

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* zip: bzip2 is a build and runtime dependency

unix/configure finds bzlib.h (bzip2 rides in through base at build time) and links
-lbz2, so the binary needs libbz2.so.1.0 wherever it runs; classpath-0.93's sandbox
had no bzip2 and `zip -r glibj.zip` failed to load.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jvm rungs: declare runtime_deps

None of the rungs declared any. The lab VM is one filesystem, the sandbox is not:
icedtea-7's configure ran classpath-devel's javah wrapper, which execs
/usr/lib/jamvm-1.5.1/bin/jamvm, in a closure without jamvm-1.5.1. Each rung now
names what its installed files exec or load: the VMs their class library and libz
(libffi for jamvm-2.0.0), the Classpath tool wrappers and ecj javac wrappers their VM
and class library, the JDKs libz.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jvm rungs: sysroot link flags before the caller's arguments

OpenJDK's freetype_versioncheck link line carries its own -Wl,-rpath,/usr/lib; with
the wrapper's flags appended after it, /usr/lib came first in RPATH and the sysroot's
ld.so loaded the system libc.so.6 (symbol lookup error: __pointer_chk_guard,
GLIBC_PRIVATE). The lab VM has no /usr/lib/libc.so.6, so it never showed. The
wrapper now puts its -L/-B/--dynamic-linker/-rpath flags ahead of the arguments.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* mrustc: restore main's build.sh (touched by the wrapper reorder glob by mistake)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* icedtea, openjdk rungs: compile C as gnu17

gcc 15 defaults to C23, where hotspot's serviceability agent (`typedef int bool;` in
agent/src/os/linux/libproc.h) no longer compiles; the lab's gcc 14 defaulted to gnu17.
The Classpath and jamvm-2.0.0 rungs already pinned it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* icedtea-8, openjdk rungs: rename hotspot's uabs

glibc 2.42's <stdlib.h> declares `unsigned int uabs(int)`; hotspot's inline overloads
of the same name (utilities/globalDefinitions.hpp) then fail to compile against the
bedrock sysroot. Rename hotspot's to hs_uabs after unpacking; the openjdk rungs apply
the same rename conditionally, as a no-op where their hotspot has none.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* openjdk-23..25: the uabs rename too (these rungs apply no patches, so the anchor differs)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* openjdk rungs: gnu17 and a warning demotion in the JDK's own CFLAGS

The wrapper's -std=gnu17 does not survive the JDK's flag handling for libnet's gio
shims (K&R `()` prototypes, "too many arguments" under gcc 15's C23), so it goes into
--with-extra-cflags, which the JDK appends last. jtreg's libTestJNI.c trips gcc 14's
incompatible-pointer-types error; it is a warning again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* openjdk rungs: --with-build-user=minimal

The sandbox runs as a uid with no passwd entry, so `whoami` fails; JDK 21+'s configure
refuses an empty build user ("Value cannot be empty"). Naming it also keeps the
recorded build user identical between the lab and the sandbox.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* openjdk-24, 25: make images, not all

JDK 24 added a static-launcher target to `all`; it links the launcher statically and
fails against the versioned sysroot. The rung ships the jdk image only.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jdk rungs: runtime_deps from an audit of the installed trees

bin/runtime-deps-audit.py (minimermetic) walks every ELF's DT_NEEDED/PT_INTERP and every
script's exec targets and resolves them against the declared runtime closure. On the lab
rehearsal trees the JDK images load the X libraries, alsa, fontconfig, lcms2, freetype,
libpng, giflib and libjpeg from AWT, sound, font and image code; jikes' interpreter is
the sysroot's ld.so. All were build deps only.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* openjdk-15..22: libawt_xawt loads libXcursor too (audit)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jdk rungs: address CR review (BUILDINFO newline, dead flags/deps, orphan patches)

- openjdk-9..25: BUILDINFO heredoc wrote a literal "\n" between the
  source and boot fields; split it onto its own line.
- jamvm-1.5.1: drop --enable-runtime-reloc. 1.5.1's configure.ac only
  defines runtime-reloc-checks and its autoconf-2.61 configure ignores
  unknown options silently, so the flag never did anything (JVMFLAGS
  passes -Xnoinlining, so reloc mode is moot anyway).
- openjdk-23..25: drop the libxcursor build dep; these rungs do not
  apply the xcursor-no-dynamic patch, so nothing links it.
- openjdk-15/16: remove three classlist patches build.ncl never applies.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* jvm ladder: drop duplicate gawk/diffutils deps; trim jikes narration

- all 17 openjdk rungs listed gawk and diffutils twice in build_deps.
- jikes-1.22: replace the lab-notebook banner and private-infra references
  with the classpath-0.93-style header.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* openjdk rungs: stop re-setting SOURCE_DATE_EPOCH

9-14: the export was a no-op (nothing under make/ in 12/13/14 reads it), so
drop it. 15-25: pass configure's own --with-source-date=315532802 (jmod
rejects the sandbox's pre-1980 0) instead of overriding the sandbox
variable, the nspr pattern pkgs' CLAUDE.md asks for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: report why the bedrock gcc does not run

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: run the bedrock toolchain against the sysroot's libc

The B5 gcc and B4 binutils have no RUNPATH; their loader is the
sysroot's ld.so, which searches /usr/lib and found production glibc
2.44 there (symbol lookup error: __pointer_chk_guard, GLIBC_PRIVATE).
Wrap every executable that loads through that ld.so with
LD_LIBRARY_PATH=$SR/lib and put the wrappers first on PATH.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: no trace for the wrapper scan; list the wrapped tools

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: print config.log's tail when configure fails

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: print the failing compiler test from config.log

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: assemble and link with production binutils

The sealed binutils-2.46-glibc and production binutils 2.47 both put
libsframe.so.3 in /usr/lib; whichever wins, as from one loads the
other's library and aborts (stack smashing). Production binutils is
consistent with the production glibc it runs on; the bedrock gcc keeps
its sysroot-libc wrapper and still links against the 2.42 sysroot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: production as and ld run without the sysroot library path

The bedrock gcc wrapper exports LD_LIBRARY_PATH for gcc and its cc1;
the production as it spawned inherited it, loaded the 2.42 libc and
aborted. Give as/ld wrappers that unset it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: point the bedrock gcc drivers at the wrapped as/ld with -B

gcc looks for as in its own tool dirs before PATH and found an
unwrapped copy, which inherited the sysroot library path and aborted.
-B is searched first, for the driver and for collect2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: on configure failure, report which as gcc runs and how each loads

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jikes-1.22: bind the sysroot libc per process, not through the environment

LD_LIBRARY_PATH leaked from the bedrock gcc into the production /bin/sh
and as it ran, which then aborted on the 2.42 libc. Start each bedrock
program (drivers, cc1, cc1plus, collect2, lto1) through the sysroot's
ld.so with --library-path; the drivers find the wrapped internals via -B.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* jvm ladder: run the bedrock gcc against its sysroot libc, link with production binutils

On main the amd64 bedrock roots are sealed tarballs and /usr/lib holds
production glibc 2.44. The B5 gcc has no RUNPATH, so its 2.42 loader
picked up the 2.44 libc and nothing ran. Every rung now starts each
bedrock program through the sysroot's ld.so with --library-path (per
process, so the production as, ld and /bin/sh it runs keep their own
libc), and assembles and links with production binutils 2.47 instead of
the sealed 2.46, whose libsframe.so.3 collides with 2.47's in /usr/lib.
Proven on jikes-1.22 in the sandbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants