Files
BFM-decomp/phase-ends/PhaseEnd_Phase4.md
T
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

124 lines
9.9 KiB
Markdown

# 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.