mirror of
https://github.com/imjasonh/nescript
synced 2026-07-07 00:22:50 +00:00
ci: fold mesen-dbg job into the main CI workflow
Move the Mesen2 .dbg validation job from its own workflow file into the existing ci.yml so all CI lives in one place. Same job content and same workarounds (settings.json shim, GLOBALIZATION_INVARIANT, xvfb-run) — only the file location changed. The MESEN_VERSION env var moves up to the workflow-level env block. https://claude.ai/code/session_01DfN3pKJLryr7vvNFBpcqmC
This commit is contained in:
parent
d075bc2c43
commit
90e01bd197
2 changed files with 102 additions and 120 deletions
102
.github/workflows/ci.yml
vendored
102
.github/workflows/ci.yml
vendored
|
|
@ -9,6 +9,12 @@ on:
|
|||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTFLAGS: "-D warnings"
|
||||
# Pin the Mesen2 release the `mesen-dbg` job tests against. Bump
|
||||
# this when the upstream binary's behaviour changes in a way that
|
||||
# affects the probe (new label-name normalisation, .dbg format
|
||||
# additions, etc.). See https://github.com/SourMesen/Mesen2/releases
|
||||
# for the source URLs.
|
||||
MESEN_VERSION: "2.1.1"
|
||||
|
||||
jobs:
|
||||
check:
|
||||
|
|
@ -203,3 +209,99 @@ jobs:
|
|||
tests/emulator/actual/
|
||||
tests/emulator/goldens/
|
||||
tests/emulator/report.json
|
||||
|
||||
mesen-dbg:
|
||||
# Validates that the `.dbg` debug-info file `nescript build --dbg`
|
||||
# emits is actually consumable by Mesen2 — the same emulator NES
|
||||
# developers use for source-level debugging. Builds the compiler,
|
||||
# builds an example ROM with `--dbg`, then launches the Mesen2
|
||||
# release binary in `--testRunner` mode. Mesen auto-loads the
|
||||
# co-located .dbg, runs `tests/mesen/probe.lua`, and exits with a
|
||||
# status code the script picks. CI fails if any code label we
|
||||
# promised to emit is missing or unresolved.
|
||||
name: Mesen2 .dbg validation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Install Mesen runtime deps
|
||||
# libsdl2-2.0-0: Mesen links to it for audio/video even though
|
||||
# we're running headless. Without it MesenCore.so fails to
|
||||
# load with `cannot open shared object file: libSDL2-2.0.so.0`.
|
||||
# xvfb: Mesen's Avalonia UI initialises an X11 connection at
|
||||
# startup before checking `--testRunner`, so even the headless
|
||||
# path needs *some* display.
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
libsdl2-2.0-0 \
|
||||
xvfb
|
||||
|
||||
- name: Cache Mesen2 binary
|
||||
id: mesen-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: mesen2
|
||||
key: mesen2-${{ env.MESEN_VERSION }}-linux-x64
|
||||
|
||||
- name: Download Mesen2
|
||||
if: steps.mesen-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
mkdir -p mesen2
|
||||
cd mesen2
|
||||
curl -sL -o Mesen.zip \
|
||||
"https://github.com/SourMesen/Mesen2/releases/download/${MESEN_VERSION}/Mesen_${MESEN_VERSION}_Linux_x64.zip"
|
||||
unzip -q Mesen.zip
|
||||
chmod +x Mesen
|
||||
rm Mesen.zip
|
||||
|
||||
- name: Build NEScript
|
||||
run: cargo build --release
|
||||
|
||||
- name: Build test ROM with .dbg
|
||||
# `hello_sprite` is the smallest example with a state handler,
|
||||
# so its .dbg exercises every record kind render_dbg emits
|
||||
# (file, mod, seg, scope, span, line, sym) without a long
|
||||
# compile.
|
||||
run: |
|
||||
./target/release/nescript build examples/hello_sprite.ne \
|
||||
--dbg /tmp/hello.dbg \
|
||||
--output /tmp/hello.nes
|
||||
|
||||
- name: Validate .dbg via Mesen2 testRunner
|
||||
# Three workarounds are baked into this single command — see
|
||||
# the comments inside for *why* each is needed. Removing any
|
||||
# of them turns this into a multi-hour debugging exercise (it
|
||||
# took several hours of investigation to find the
|
||||
# GLOBALIZATION workaround in particular; see the commit
|
||||
# message for d075bc2).
|
||||
run: |
|
||||
# 1. `touch settings.json`: Mesen's first-run check
|
||||
# (`Program.cs:56`) launches the GUI setup wizard
|
||||
# *before* the `--testRunner` dispatch when no settings
|
||||
# file exists. The wizard never closes in headless CI,
|
||||
# blocking forever. The file's *contents* don't matter:
|
||||
# Configuration.Deserialize catches any JSON parse error
|
||||
# and falls back to defaults, so a 0-byte file is fine.
|
||||
touch mesen2/settings.json
|
||||
|
||||
# 2. `DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1`: .NET's
|
||||
# globalization layer pulls in libicuuc, which loads
|
||||
# system libstdc++. MesenCore.so is built with a
|
||||
# statically-bundled libstdc++; on Ubuntu 24.04 the
|
||||
# interposition causes a `std::bad_cast` from a static
|
||||
# regex initialiser in `Base6502Assembler.cpp` long
|
||||
# before any user code runs. Invariant mode skips ICU
|
||||
# entirely, which means system libstdc++ is never
|
||||
# loaded and MesenCore's bundled copy wins.
|
||||
#
|
||||
# 3. `xvfb-run -a`: Mesen's Avalonia UI runs `XOpenDisplay`
|
||||
# during AppBuilder setup before the `--testRunner`
|
||||
# dispatch in `Program.cs:74`. xvfb-run gives it a
|
||||
# throwaway X server; -a auto-allocates a display number.
|
||||
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \
|
||||
xvfb-run -a ./mesen2/Mesen \
|
||||
--testRunner /tmp/hello.nes tests/mesen/probe.lua \
|
||||
--timeout=15
|
||||
|
|
|
|||
120
.github/workflows/mesen.yml
vendored
120
.github/workflows/mesen.yml
vendored
|
|
@ -1,120 +0,0 @@
|
|||
name: Mesen .dbg Smoke Test
|
||||
|
||||
# Validates that the `.dbg` debug-info file `nescript build --dbg` emits
|
||||
# is actually consumable by Mesen2 — the same emulator NES developers
|
||||
# use for source-level debugging. The job:
|
||||
# 1. Builds the compiler.
|
||||
# 2. Builds an example ROM with `--dbg`.
|
||||
# 3. Launches the Mesen2 release binary in `--testRunner` mode.
|
||||
# 4. Mesen auto-loads the co-located .dbg, runs `tests/mesen/probe.lua`,
|
||||
# and exits with a status code the script picks.
|
||||
# 5. CI fails if any code label we promised is missing or unresolved.
|
||||
#
|
||||
# This is a separate workflow from `ci.yml` because it depends on the
|
||||
# Mesen2 binary download (40 MB) + xvfb + a couple of Mesen-specific
|
||||
# environment workarounds that aren't worth threading through the main
|
||||
# CI matrix.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTFLAGS: "-D warnings"
|
||||
# Pin the Mesen2 release we test against. Bump this when the upstream
|
||||
# binary's behaviour changes in a way that affects our probe (new
|
||||
# label-name normalisation, .dbg format additions, etc.). See
|
||||
# https://github.com/SourMesen/Mesen2/releases for the source URLs.
|
||||
MESEN_VERSION: "2.1.1"
|
||||
|
||||
jobs:
|
||||
mesen-dbg:
|
||||
name: Mesen2 .dbg validation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Install Mesen runtime deps
|
||||
# libsdl2-2.0-0: Mesen links to it for audio/video even though
|
||||
# we're running headless. Without it MesenCore.so fails to
|
||||
# load with `cannot open shared object file: libSDL2-2.0.so.0`.
|
||||
# xvfb: Mesen's Avalonia UI initialises an X11 connection at
|
||||
# startup before checking `--testRunner`, so even the headless
|
||||
# path needs *some* display.
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
libsdl2-2.0-0 \
|
||||
xvfb
|
||||
|
||||
- name: Cache Mesen2 binary
|
||||
id: mesen-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: mesen2
|
||||
key: mesen2-${{ env.MESEN_VERSION }}-linux-x64
|
||||
|
||||
- name: Download Mesen2
|
||||
if: steps.mesen-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
mkdir -p mesen2
|
||||
cd mesen2
|
||||
curl -sL -o Mesen.zip \
|
||||
"https://github.com/SourMesen/Mesen2/releases/download/${MESEN_VERSION}/Mesen_${MESEN_VERSION}_Linux_x64.zip"
|
||||
unzip -q Mesen.zip
|
||||
chmod +x Mesen
|
||||
rm Mesen.zip
|
||||
|
||||
- name: Build NEScript
|
||||
run: cargo build --release
|
||||
|
||||
- name: Build test ROM with .dbg
|
||||
# `hello_sprite` is the smallest example with a state handler,
|
||||
# so its .dbg exercises every record kind render_dbg emits
|
||||
# (file, mod, seg, scope, span, line, sym) without a long
|
||||
# compile.
|
||||
run: |
|
||||
./target/release/nescript build examples/hello_sprite.ne \
|
||||
--dbg /tmp/hello.dbg \
|
||||
--output /tmp/hello.nes
|
||||
|
||||
- name: Validate .dbg via Mesen2 testRunner
|
||||
# Three workarounds are baked into this single command — see the
|
||||
# comments inside for *why* each is needed. Removing any of them
|
||||
# turns this into a multi-hour debugging exercise (it took
|
||||
# several hours of investigation to find the GLOBALIZATION
|
||||
# workaround in particular; see commit message of the change
|
||||
# that added this workflow).
|
||||
run: |
|
||||
# 1. `touch settings.json`: Mesen's first-run check
|
||||
# (`Program.cs:56`) launches the GUI setup wizard
|
||||
# *before* the `--testRunner` dispatch when no settings
|
||||
# file exists. The wizard never closes in headless CI,
|
||||
# blocking forever. The file's *contents* don't matter:
|
||||
# Configuration.Deserialize catches any JSON parse error
|
||||
# and falls back to defaults, so a 0-byte file is fine.
|
||||
touch mesen2/settings.json
|
||||
|
||||
# 2. `DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1`: .NET's
|
||||
# globalization layer pulls in libicuuc, which loads
|
||||
# system libstdc++. MesenCore.so is built with a
|
||||
# statically-bundled libstdc++; on Ubuntu 24.04 the
|
||||
# interposition causes a `std::bad_cast` from a static
|
||||
# regex initialiser in `Base6502Assembler.cpp` long
|
||||
# before any user code runs. Invariant mode skips ICU
|
||||
# entirely, which means system libstdc++ is never
|
||||
# loaded and MesenCore's bundled copy wins.
|
||||
#
|
||||
# 3. `xvfb-run -a`: Mesen's Avalonia UI runs `XOpenDisplay`
|
||||
# during AppBuilder setup before the `--testRunner`
|
||||
# dispatch in `Program.cs:74`. xvfb-run gives it a
|
||||
# throwaway X server; -a auto-allocates a display number.
|
||||
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \
|
||||
xvfb-run -a ./mesen2/Mesen \
|
||||
--testRunner /tmp/hello.nes tests/mesen/probe.lua \
|
||||
--timeout=15
|
||||
Loading…
Add table
Add a link
Reference in a new issue