mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
ci: macOS arm64 build + port_addr self-test on PRs into macos
Adds a GitHub-hosted macos-15 (Apple Silicon) workflow for pushes and PRs into the macos branch: build with Homebrew GCC, once with PORT_ADDR_STRICT off and once on, then run the ROM-free address-model self-test. - main.c: new --selftest flag, handled right after portAddrInit() and before crashInit/config/ROM/SDL. Exits 0 if the self-test passed, 1 if not. Listed in --help. - port_addr.c/.h: portAddrSelfTest() now returns its result and portAddrSelfTestPassed() exposes it; no change to normal runs. - macos.yml: contents: read only, no secrets, no ROM, persist-credentials off, so it is safe for fork PRs. The strict entry also requires the GE_ADDRSTRICT_SELFTEST report, proving the validator is live. - docs: building.md CI note; plan M4 row no longer lists macOS CI as outstanding (ROM sweeps stay with the self-hosted job in #131).
This commit is contained in:
1 parent
92986a07a9
commit
7b08a04f54
6 files changed
+123
-3
No files matched your search
@@ -0,0 +1,85 @@
|
||||
name: macOS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ macos ]
|
||||
pull_request:
|
||||
branches: [ macos ]
|
||||
workflow_dispatch:
|
||||
|
||||
# Minimal token: this job only reads the repo. It runs on GitHub-hosted
|
||||
# runners only, never receives secrets, and never sees a ROM, so it is safe
|
||||
# for fork PRs (untrusted PR code must not reach a box that holds a ROM).
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: macos-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
# What this proves: the native Apple Silicon (arm64) port BUILDS and LINKS
|
||||
# with Homebrew GCC, and the ROM-free address-model self-test passes
|
||||
# (`ge007.aarch64 --selftest`: window round-trips, absolute-symbol base,
|
||||
# image-relative encoding, portAddrIsInWindow). It does NOT run the game.
|
||||
#
|
||||
# Matrix:
|
||||
# strict=OFF the default build.
|
||||
# strict=ON -DPORT_ADDR_STRICT=ON; additionally proves the validator is
|
||||
# live by feeding it a deliberately unmapped address
|
||||
# (GE_ADDRSTRICT_SELFTEST=1) and requiring its report.
|
||||
#
|
||||
# Level runs need a ROM, so they live elsewhere: the self-hosted sweep
|
||||
# (`platform=macos`, tools_pc/level_sweep_mac.sh) from #131, on a runner with
|
||||
# its own ROM that never runs PR code.
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-15
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
strict: [ OFF, ON ]
|
||||
env:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_MAXSIZE: 500M
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install dependencies
|
||||
run: brew install cmake gcc sdl2 ccache
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ccache-macos-${{ matrix.strict }}-${{ hashFiles('CMakeLists.txt') }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-macos-${{ matrix.strict }}-${{ hashFiles('CMakeLists.txt') }}-
|
||||
ccache-macos-${{ matrix.strict }}-
|
||||
|
||||
- name: Regenerate ROM-asset symbol file (US)
|
||||
run: python3 scripts/gen_romassets.py u
|
||||
|
||||
- name: Configure (ntsc-final)
|
||||
run: cmake -S . -B build-pc -DROMID=ntsc-final -DPORT_ADDR_STRICT=${{ matrix.strict }}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build-pc -j"$(sysctl -n hw.ncpu)"
|
||||
|
||||
- name: ccache stats
|
||||
run: ccache -s
|
||||
|
||||
- name: Version
|
||||
run: ./build-pc/ge007.aarch64 --version
|
||||
|
||||
- name: Address-model self-test
|
||||
run: ./build-pc/ge007.aarch64 --selftest
|
||||
|
||||
- name: PORT_ADDR_STRICT detector is live
|
||||
if: matrix.strict == 'ON'
|
||||
run: |
|
||||
set -o pipefail
|
||||
GE_ADDRSTRICT_SELFTEST=1 ./build-pc/ge007.aarch64 --selftest 2>&1 | tee selftest.log
|
||||
grep -F 'PORT_ADDR_STRICT: 0x30000000 is not a mapped N64 address' selftest.log
|
||||
@@ -213,6 +213,23 @@ GE_ADDRSTRICT_SELFTEST=1 ./build-strict/ge007.aarch64 -level_09
|
||||
|
||||
See findings MACOS-SFX-BOUND through MACOS-ADDR-STRICT for the bug family this exists to catch.
|
||||
|
||||
### macOS CI and the ROM-free self-test
|
||||
|
||||
`.github/workflows/macos.yml` runs on GitHub-hosted Apple Silicon for pushes and
|
||||
PRs into the `macos` branch. It builds with Homebrew GCC (once with
|
||||
`PORT_ADDR_STRICT` off, once on) and runs the address-model self-test, which
|
||||
needs no ROM:
|
||||
|
||||
```sh
|
||||
./build-pc/ge007.aarch64 --selftest # exit 0 = pass, 1 = fail
|
||||
```
|
||||
|
||||
The self-test covers the window round-trips, the generated absolute-symbol base,
|
||||
the image-relative encoding and `portAddrIsInWindow()`. With a `PORT_ADDR_STRICT`
|
||||
build, `GE_ADDRSTRICT_SELFTEST=1` additionally proves the validator fires. Level
|
||||
runs need a ROM and are covered by the self-hosted sweep
|
||||
(PR #131, `tools_pc/level_sweep_mac.sh`), not by this job.
|
||||
|
||||
### Packaging a macOS app
|
||||
|
||||
```sh
|
||||
|
||||
@@ -581,7 +581,7 @@ Record as a `Dxx`.
|
||||
| M1 | **done** | shifted-window address model (MACOS-ADDR-WINDOW); self-test ALL PASS on the #88 base |
|
||||
| M2 | **done** | game-code re-basing sweep complete; **21/21 solo levels boot, render and run crash-free**, including with full controller input |
|
||||
| M3 | **done (core)** | #88's AppKit main-thread guard; `tools_pc/level_sweep_mac.sh` (crash + rendered-pixel check); the two Core-profile GL nits are cosmetic and parked in `docs/dev/GRAPHICS-BACKLOG.md` |
|
||||
| M4 | **done (core)** | `tools_pc/bundle-mac.sh` → signed, double-clickable `GoldenEye.app` (+ zip/sha256); `docs/building.md` macOS section + `tools_pc/README.md`. Outstanding: CI for macOS, and a live run of the `.app` from Finder |
|
||||
| M4 | **done (core)** | `tools_pc/bundle-mac.sh` → signed, double-clickable `GoldenEye.app` (+ zip/sha256); `docs/building.md` macOS section + `tools_pc/README.md`. CI: GitHub-hosted build + `--selftest` (`.github/workflows/macos.yml`); ROM sweeps via the self-hosted job (#131). Outstanding: a live run of the `.app` from Finder |
|
||||
|
||||
**Verified state (2026-09-18).** `build-pc/ge007.aarch64` (Homebrew GCC 16.2)
|
||||
opens a window, renders, plays music **and sound effects**, and runs every solo
|
||||
|
||||
@@ -86,6 +86,10 @@ void portAddrStrictCheck(uint32_t a);
|
||||
* any of the port's fixed mappings and before large allocations. */
|
||||
void portAddrInit(void);
|
||||
|
||||
/* Result of the ROM-free self-test portAddrInit() ran (1 = all checks passed).
|
||||
* Used by `--selftest` so CI can gate on it without a ROM. */
|
||||
int portAddrSelfTestPassed(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -68,6 +68,8 @@ static void portPrintHelp(const char *argv0)
|
||||
printf("\nusage: %s [options] [-level_XX]\n\n"
|
||||
" --help this message\n"
|
||||
" --version build id only\n"
|
||||
" --selftest run the ROM-free address-model self-test and\n"
|
||||
" exit (0 = pass, 1 = fail); needs no ROM\n"
|
||||
" -fresh wipe playtest data + config before starting\n"
|
||||
" (removes ge007.eep save and ge007.ini; the\n"
|
||||
" ini is re-written with defaults on exit)\n"
|
||||
@@ -109,6 +111,10 @@ int main(int argc, char **argv)
|
||||
* failure here is reported before SDL/GL are involved. */
|
||||
portAddrInit();
|
||||
|
||||
if (sysArgCheck("--selftest")) {
|
||||
return portAddrSelfTestPassed() ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Crash handler first, so any failure below is debuggable. */
|
||||
crashInit();
|
||||
|
||||
|
||||
+10
-2
@@ -42,7 +42,7 @@ static int portAddrCheck(const char *what, int ok)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void portAddrSelfTest(void)
|
||||
static int portAddrSelfTest(void)
|
||||
{
|
||||
const uintptr_t B = (uintptr_t)PORT_ADDR_BASE;
|
||||
int ok = 1;
|
||||
@@ -74,6 +74,14 @@ static void portAddrSelfTest(void)
|
||||
}
|
||||
sysLogPrintf(ok ? LOG_INFO : LOG_ERROR, "portAddr: selftest %s",
|
||||
ok ? "ALL PASS" : "FAILURES");
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int g_portAddrSelfTestOk = 0;
|
||||
|
||||
int portAddrSelfTestPassed(void)
|
||||
{
|
||||
return g_portAddrSelfTestOk;
|
||||
}
|
||||
|
||||
#ifdef PORT_ADDR_STRICT
|
||||
@@ -199,7 +207,7 @@ void portAddrInit(void)
|
||||
(unsigned long long)PORT_ADDR_BASE,
|
||||
(unsigned long long)g_portImageBase, g_portUseImageRel);
|
||||
|
||||
portAddrSelfTest();
|
||||
g_portAddrSelfTestOk = portAddrSelfTest();
|
||||
|
||||
#ifdef PORT_ADDR_STRICT
|
||||
portAddrStrictSelfTest();
|
||||
|
||||
Reference in new issue
Block a user