Rewrote 20 issue writeups to the extern/runtime-class vocabulary (#foreign→extern, foreign_class_map→runtime_class_map, parseForeignClassDecl→parseRuntimeClassDecl, findForeignMethodInChain→findRuntimeMethodInChain, dedupeForeignSymbol→ dedupeExternSymbol, is_foreign_c_api→is_extern_c_api, stale filename refs to the renamed examples, foreign-class→runtime-class, bare foreign→extern). Renamed issues/0043-…-foreign-class-…→…-runtime-class-…. PHASE 9 COMPLETE — 9.4 GATE PASSES: zero 'foreign' across src/library/examples/ issues/docs/editors/specs/readme/CLAUDE, excluding only the SQLite API constant SQLITE_CONSTRAINT_FOREIGNKEY + vendored sqlite3.c/.h (upstream third-party). Suite green (644 corpus / 443 unit, 0 failed).
5.8 KiB
FIXED. Two parts, both needed for Finder/open to work:
- cwd-relative assets —
SdlPlatform.initnow chdir's toSDL_GetBasePath()when running from inside a.app(sx commitb31fbae,library/modules/platform/sdl3.sx), mirroring uikit.sx's iOSchdir_to_bundle. Gated to the.appcase so thesx rundev flow keeps the project CWD. - Gatekeeper-rejected signature — the bundle was signed with a
Development cert, which
spctlrejects, so a standaloneopenwouldn't launch it. Switched the macOS build to ad-hoc signing (the bundler's macOS/sim default — just leave the codesign identity empty; game commitd80a350,build.sx).
Verified: a plain cd game && sx build main.sx then open sx-out/macos/SxChess.app launches and renders (was: instant stbtt segfault
on missing font, or no launch at all). It was NOT App Translocation — the
bundle had no com.apple.quarantine xattr.
Symptom
A bundled macOS .app built with sx build crashes on launch when started
via Finder double-click or open Foo.app, but runs fine when launched from a
shell whose CWD is the bundle directory.
Observed: open sx-out/macos/SxChess.app → process exits within ~1s (segfaults
inside stbtt_ScaleForPixelHeight because the font buffer is null — the asset
wasn't found).
Expected: double-click / open launches the app and it finds its bundled
assets, same as on iOS.
Root: assets are loaded with CWD-relative paths (e.g.
"assets/fonts/default.ttf"), but Finder/open start a GUI app with CWD=/,
so the relative path resolves against / and the file is missing.
Reproduction
Any consumer that bundles an assets/ dir and loads from it by relative path.
Minimal shape (real case: /Users/agra/projects/game):
// main.sx — loads assets by CWD-relative path
g_pipeline.init_font("assets/fonts/default.ttf", 32.0, dpi); // -> read_file_bytes
g_chess_game.pieces.load("assets/chess/pieces.png", gpu); // -> read_file_bytes
cd game && sx build main.sx # produces sx-out/macos/SxChess.app (assets copied in)
# Works (CWD = bundle dir, so "assets/..." resolves):
cd sx-out/macos/SxChess.app && ./SxChess
# Fails (CWD = /, asset not found -> null buffer -> stbtt segfault):
open sx-out/macos/SxChess.app
# or double-click in Finder
add_asset_dir("assets", "assets") in build.sx correctly copies the tree
into the flat .app (binary at SxChess.app/SxChess, assets at
SxChess.app/assets/...), so the files ARE present in the bundle — they're just
not found because the lookup is CWD-relative and CWD isn't the bundle.
Root cause
The macOS SDL startup never reorients CWD (or the asset root) to the bundle.
SdlPlatform.init (library/modules/platform/sdl3.sx:35)
calls SDL_Init(SDL_INIT_VIDEO) and creates the window but does no chdir,
so read_file_bytes
(library/modules/ui/glyph_cache.sx:202,
and the chess extern read_file_bytes) opens paths relative to whatever CWD
the launcher set — / under Finder/open.
The other platforms already handle this:
- iOS: library/modules/platform/uikit.sx:346
explicitly
chdirs to the bundle'sresourcePath()at startup, with the comment "iOS apps start with CWD=/. chdir to the bundle's resourcePath so the [assets resolve]". - Android: library/modules/platform/android.sx:71
routes
read_file_bytesthroughAAssetManagerso paths resolve against the APK assets regardless of CWD.
macOS has neither — so it only works by accident when launched from a shell sitting in the bundle dir.
Investigation prompt
For a fresh session picking this up:
The fix mirrors the iOS precedent. In SdlPlatform.init
(sdl3.sx:35), before any asset is
loaded, reorient to the bundle's resource directory on macOS only (leave
wasm/emscripten and the dev sx run path alone — those legitimately want the
project CWD).
Recommended approach — SDL_GetBasePath():
- SDL3
SDL_GetBasePath()returns the directory containing the executable (for a.app, that'sSxChess.app/where the assets were copied).chdirto it at the top ofinitwhenBuildOptions.is_macos(gate sosx runduring development isn't affected — or gate on "the base path differs from CWD and contains anassets/dir"). - Add the
externdecl forSDL_GetBasePath(returns*u8, SDL-owned) and callchdir(already used by uikit.sx — reuse the sameextern).
Alternative (no SDL dependency): _NSGetExecutablePath + dirname, same as a
plain macOS resolve. SDL_GetBasePath is simpler and already links SDL3.
Things to verify / watch:
- Don't chdir for the
sx run <file>(JIT) dev flow or for wasm — only the bundled AOT macOS app. The cleanest gate is the bundle context; ifinitcan't seeBuildOptions, gate onSDL_GetBasePath()returning a path that ends in.app/(bundled) vs the build dir (dev). - After chdir, the existing
"assets/..."relative loads resolve unchanged — no call-site changes needed in consumers (chess, glyph_cache). - Confirm the iOS path (uikit, doesn't use SdlPlatform) is untouched.
Verification
cd game && sx build main.sx
open sx-out/macos/SxChess.app # must launch and stay up (board + pieces render)
# screenshot / pgrep -lf sx-out/macos/SxChess -> alive after a few seconds
Before the fix: open → exits ~1s (stbtt segfault, null font buffer).
After: open and Finder double-click both launch and render, matching the
cd bundle && ./SxChess behavior.
Also re-run host + cross suites to confirm no platform-module regression:
zig build && zig build test && bash tests/run_examples.sh.