Files
Drew T ffe2352db2 feat(phase-4): matching-build toolchain (WSL) — make check-env green
- apt: build-essential, binutils-mipsel-linux-gnu 2.42 (+gcc-mipsel 12.x), ninja
  1.11.1, python3-pip/venv, libelf-dev, clang-format, p7zip, bchunk, bsdmainutils
- .venv + splat64 0.41.0 ([mips]: spimdisasm 1.41.0, rabbitizer 1.16.2, PyYAML 6.0.3)
- 4 pinned submodules under tools/: maspsx@874855c5, decomp-permuter@b44b0622,
  asm-differ@2ad4a4a4, m2c@4266cc28 (.gitmodules)
- old-gcc 0.17 cc1 candidates -> tools/bin/gcc-2.7.2-{psx,cdk}/ (32-bit i386 static;
  tarballs are flat + same-named -> per-subdir extraction); CHECKSUMS.sha256 committed
  (gitignore exception !/tools/bin/*.sha256); psx cc1 self-id "GNU C 2.7.2 [AL 1.1,
  MM 40] Sony Playstation"
- Makefile: check-env (.ONESHELL bash) asserts python>=3.12, venv import splat, both
  cc1 (stdin smoke), maspsx, mipsel as/ld/objcopy, sha1(EXE)==EXPECTED_EXE_SHA1;
  binutils>=2.38 -> WARN (verdict deferred to Phase 5, §4.5); extract/build/check/
  expected/clean are loud-failing Phase-5 stubs (names per §6.3)
- docs/SETUP.md: as-built versions; §4.7 corrected (i386, flat-tarball fix); §4.8
  deferred to Phase 6; ledger #5 confirmed (Ubuntu 24.04.4), #6 (2.42), #7 (sha256)
- MILESTONE: make check-env exits 0; zero ROM-derived bytes staged
- bumps project version 1.3.1 -> 1.4.0
2026-06-14 03:56:07 -06:00

9.9 KiB

PhaseEnd — Phase 4: Matching-build toolchain (WSL)

Date: 2026-06-14 · Project Version: 1.4.0 · Phase Status: Complete

Build Log

Files created/changed and complete — do not recreate:

  • Makefile — new, repo root. The live target is check-env (the Phase-4 milestone preflight): .ONESHELL bash, default goal help. Asserts python ≥ 3.12, venv import splat, both cc1 candidates (R12-clean stdin smoke), tools/maspsx/maspsx.py, the three mipsel binutils (as/ld/objcopy), and sha1(committed extracted/retail/SLUS_007.26) == EXPECTED_EXE_SHA1 (imported from tools/bfm_extract/extract_exe.py — no magic literal). binutils ≥ 2.38 → [WARN], not FAIL (§4.5). extract/build/check/expected/clean are loud-failing no-op stubs (names fixed per §6.3; Phase 5 implements them). Consumed by: the daily build (Phase 5 extends this file).
  • .gitmodules — new; 4 submodules under tools/.
  • tools/maspsx, tools/asm-differ, tools/m2c, tools/decomp-permuter — new submodule gitlinks (pinned, see Verification). Their working-tree contents are gitignored-by-submodule (a fresh clone runs git submodule update --init).
  • tools/bin/CHECKSUMS.sha256 — new, committed; sha256 of the two old-gcc 0.17 tarballs. The ONLY thing committed out of the otherwise-ignored tools/bin/. Verify with sha256sum --check.
  • .gitignore — modified: /tools/bin/ → /tools/bin/* + !/tools/bin/*.sha256 (contents-exclude form so the checksum record commits while all compiler binaries/tarballs stay ignored).
  • docs/SETUP.md — modified: as-built versions (binutils 2.42, splat 0.41.0 + deps, gcc tarball sha256, submodule pins, check-env); §4.7 corrected (cc1 is 32-bit i386 not x86-64; flat-tarball → per-subdir extraction fix); §4.8 deferred-to-Phase-6 note; ledger #5/#6/#7 resolved; pin-summary splat/binutils rows updated.
  • phase-ends/CURRENT_PHASE.md — absorbed into this file and deleted (P8).
  • phase-ends/PhaseEnd_Phase4.md — this file.

Local artifacts (gitignored / outside the repo — present on this machine, do NOT recreate; a fresh clone redoes them):

  • .venv/ — Python 3.12.3 venv. Recreate: python3 -m venv .venv && .venv/bin/pip install 'splat64[mips]>=0.41.0,<1.0.0'.
  • tools/bin/gcc-2.7.2-psx/ + tools/bin/gcc-2.7.2-cdk/ — old-gcc 0.17 prebuilts (32-bit i386 static cc1/cc1plus/cpp/gcc/g++) + the two .tar.gz. Recreate per the corrected §4.7.
  • Submodule working trees under tools/{maspsx,asm-differ,m2c,decomp-permuter} — git submodule update --init.

Tools/packages installed:

  • apt: build-essential (make 4.3, g++ 13.3.0), binutils-mipsel-linux-gnu 2.42 + cpp/gcc-mipsel-linux-gnu 12.x, python3-pip 24.0, python3-venv (3.12), ninja-build 1.11.1, libelf-dev, clang-format 18, p7zip-full, bchunk, bsdmainutils (curl/wget/unzip/git/coreutils already present, ensured).
  • venv (pip): splat64 0.41.0; deps spimdisasm 1.41.0, rabbitizer 1.16.2, PyYAML 6.0.3, colorama 0.4.6, intervaltree 3.1.0, tqdm 4.67.1.
  • downloaded (gitignored): old-gcc 0.17 gcc-2.7.2-psx.tar.gz + gcc-2.7.2-cdk.tar.gz.

Verification results (literal):

  • MILESTONE — make check-env → exit 0: [PASS] python3 3.12; venv import splat (splat64 0.41.0); cc1 runs tools/bin/gcc-2.7.2-psx/cc1 and …-cdk/cc1; maspsx present; mipsel as/ld/objcopy all 2.42; extracted/retail/SLUS_007.26 sha1 143dbb89f34491258bbc27810d0a12ec8b43a8dd == EXPECTED_EXE_SHA1. Plus [WARN] mipsel binutils 2.42 ≥ 2.38. check-env: OK.
  • git submodule status: maspsx 874855c5 ✓, decomp-permuter b44b0622 ✓ (both pinned per the table), asm-differ 2ad4a4a4 (HEAD@adoption), m2c 4266cc28 (HEAD@adoption).
  • sha256sum --check tools/bin/CHECKSUMS.sha256: both OK — psx 500a459b…, cdk 42bb0df9….
  • cc1 binaries are 32-bit i386 statically-linked ELF (run via IA-32 emulation); psx cc1 smoke emits GNU C 2.7.2 [AL 1.1, MM 40] Sony Playstation + valid MIPS asm; psx/cdk cc1 are distinct (different sha256 — the naive flat extraction would have silently kept only one).
  • Hygiene: git add tools/bin/ stages only CHECKSUMS.sha256; git status shows zero ROM-derived/binary bytes would stage (.venv, compiler binaries, .tar.gz all ignored). bare make → help; make extract → loud fail (make: *** Error 1).
  • Ubuntu 24.04.4 LTS confirmed (ledger #5).
  • Nothing committed (R8): all work is staged/untracked and uncommitted, awaiting Drew's phase-end commit.

Milestone achieved: make check-env exits 0 in the WSL ext4 clone — both cc1 candidates execute and emit MIPS asm, splat imports in the venv, the mipsel binutils are present, and the committed SLUS_007.26 sha1 equals EXPECTED_EXE_SHA1 — the matching-build toolchain is stood up and self-verifying.

Next: Phase 5 — splat config + build skeleton (all-asm byte-match). Start with config/splat.us.exe.yaml authored (section boundaries iterated until a clean link), config/symbols.us.txt already seeded from Phase 3. (Phase 5 RE-reads gp_value for -G0/-G8, ledger #8; implements the Makefile's stub targets.)

Deviations

Item Plan Actual Reason
cc1 architecture "x86-64 Linux ELF" (§4.7) 32-bit i386 statically-linked old-gcc 0.17 ships i386 binaries; run on x86-64 via IA-32 emulation; §4.7 corrected
old-gcc extraction tar xzf psx ; tar xzf cdk flat (§4.7) per-subdir -C gcc-2.7.2-{psx,cdk} tarballs are flat and share filenames → flat extraction clobbers psx with cdk; §4.7 command fixed
check-env "dump hash" disc-level implied by milestone sha1(committed EXE) == EXPECTED_EXE_SHA1, reused constant fresh-clone-safe (disc-walk needs gitignored disks/); reuses existing code (no magic literal)
cc1 liveness check "cc1 runs (--version)" trivial stdin compile gcc-2.7.2 cc1 rejects --version; stdin→/dev/null compile is the real test, and R12-clean (no temp file)
§4.8 native PsyQ binaries optional Phase-4 checkbox deferred to Phase 6 Drew decision; tie-breaker only if maspsx output is disputed during fingerprinting
submodule pip deps + requirements freeze implied by "installed" deferred (Phase 6 / after Phase-5 green) milestone names only splat/cc1/maspsx/binutils; avoids polluting the to-be-frozen requirements-python.txt
binutils version 2.35 known-good target 2.42 installed + WARN, verdict deferred §4.5 mandates deferral to Phase 5's first full build; Ubuntu 24.04 ships 2.42
Makefile scope check-env only (milestone) check-env + Phase-5 target name stubs §6.3 fixes the names now; loud-failing stubs prevent a silent false-success build

Commit Message

feat(phase-4): matching-build toolchain (WSL) — make check-env green

- apt: build-essential, binutils-mipsel-linux-gnu 2.42 (+gcc-mipsel 12.x), ninja
  1.11.1, python3-pip/venv, libelf-dev, clang-format, p7zip, bchunk, bsdmainutils
- .venv + splat64 0.41.0 ([mips]: spimdisasm 1.41.0, rabbitizer 1.16.2, PyYAML 6.0.3)
- 4 pinned submodules under tools/: maspsx@874855c5, decomp-permuter@b44b0622,
  asm-differ@2ad4a4a4, m2c@4266cc28 (.gitmodules)
- old-gcc 0.17 cc1 candidates -> tools/bin/gcc-2.7.2-{psx,cdk}/ (32-bit i386 static;
  tarballs are flat + same-named -> per-subdir extraction); CHECKSUMS.sha256 committed
  (gitignore exception !/tools/bin/*.sha256); psx cc1 self-id "GNU C 2.7.2 [AL 1.1,
  MM 40] Sony Playstation"
- Makefile: check-env (.ONESHELL bash) asserts python>=3.12, venv import splat, both
  cc1 (stdin smoke), maspsx, mipsel as/ld/objcopy, sha1(EXE)==EXPECTED_EXE_SHA1;
  binutils>=2.38 -> WARN (verdict deferred to Phase 5, §4.5); extract/build/check/
  expected/clean are loud-failing Phase-5 stubs (names per §6.3)
- docs/SETUP.md: as-built versions; §4.7 corrected (i386, flat-tarball fix); §4.8
  deferred to Phase 6; ledger #5 confirmed (Ubuntu 24.04.4), #6 (2.42), #7 (sha256)
- MILESTONE: make check-env exits 0; zero ROM-derived bytes staged
- bumps project version 1.3.1 -> 1.4.0

Rules Added This Phase

Rule Reason
None Phase 4's findings are deviations / doc-corrections (cc1 is i386 not x86-64; the flat-tarball extraction trap; binutils 2.42 WARN; §4.8 deferral), not governance rules. Noted practice (not elevated to a rule): build/preflight targets should be fresh-clone-safe and reuse single-source constants (no magic literals, no gitignored deps) — applied in check-env (imports EXPECTED_EXE_SHA1, hashes the committed EXE). Elevate later if Phase 5's build targets benefit.

PhaseEnd Changelog

v1.3.1 → v1.4.0 — Phase 4 complete. The matching-build toolchain is stood up and self-verifying in the WSL ext4 clone: the apt cross-toolchain (binutils-mipsel 2.42), a Python 3.12 venv with splat64 0.41.0, four pinned submodules (maspsx/asm-differ/m2c/decomp-permuter), and the old-gcc 0.17 cc1 candidates (gcc-2.7.2-psx + gcc-2.7.2-cdk) — all asserted by a new make check-env target that exits 0. Two SETUP.md corrections caught by the bytes: the cc1 prebuilts are 32-bit i386 (not x86-64), and the 0.17 tarballs are flat & same-named so each must extract into its own subdir. binutils 2.42 is WARN-flagged with the regression verdict deferred to Phase 5's first build (§4.5). Ledger #5/#6/#7 resolved; §4.8 native-PsyQ arbitration deferred to Phase 6; submodule pip deps + requirements freeze deferred. No new rules. Next: Phase 5 (splat config + all-asm byte-match).

🛑 Stop Here

PhaseEnd written; CURRENT_PHASE.md absorbed and removed. Drew commits AND pushes this PhaseEnd (R6/R8 — the single Phase-4 commit lands everything: Makefile, .gitmodules, submodule gitlinks, tools/bin/CHECKSUMS.sha256, .gitignore, docs/SETUP.md, PhaseEnd_Phase4.md). Start a fresh session for Phase 5 — splat config + build skeleton. Keep this file forever.