WIP: feat(macos): run the host on macOS: build, runtime, control, crash records and the Vulkan loader #845

Draft
mooki wants to merge 17 commits from mooki/Longshot:mac/topic-macos-host into main
Member

Type: feat · Risk: medium · Tested on: macOS 26.7.1, Apple M4 Max (arm64; x86_64 under Rosetta) · Needs: Windows and Linux, any GPU

Why

Nobody can build or run LS on a Mac today. The builder takes the Linux route there and hands Apple's tools ELF options and x86
CPU flags; the host's POSIX layer is written for Linux (futex waits, ucontext fibers, /proc, Linux's signal context,
MAP_FIXED_NOREPLACE and memfd_create for the guest window, getrandom, process_vm_readv), its jumps and pause hints are
x86 only, and the renderer looks for libvulkan.so.1 with X11 or Wayland surfaces and never enables the portability
extensions MoltenVK requires. The game-free runner thinks a Mac is Linux, and the control bridge, crash records,
longshot_ctl and the builder's memory gate have no macOS route. This PR is the macOS host: it builds on a Mac, natively on
Apple silicon and as x86_64 under Rosetta, packages a relocatable game folder for macOS 14.4 and later, and runs the host with
its control, crash records and the Vulkan loader. It is the first part of the macOS port. See #420.

What changed

The build scripts get a Mach-O command path (arm64 or x86_64, macOS 14.4) and a packager; the host gets native Darwin
memory, waits, faults, threads, fibers, processes, profiler, control sockets and crash records, each in Apple-only branches or
new host/posix/darwin_*.c files; the renderer loads a Vulkan loader or MoltenVK on macOS; the game-free runner, the builder's
memory gate and longshot_ctl know macOS. Windows and Linux keep their code, but for a few stated every-platform changes
(Testing, off Apple). The seventeen original pull requests, in commit order:

  • the game-free runner knows macOS (e81d4af4; Was: #454):
    tests/run_all.py reports macos, reads a macos skip reason and keeps macOS timing apart; 18 checks a Mac has no subject
    for are skipped there; three fixtures get Apple-only repairs.
  • host jumps and pause hints on arm64 (441182e2; Was: #477):
    host/posix/darwin_cpu.c (new) has the arm64 jump in assembly and a yield pause; the x86 bodies stay for every other
    target. Test: tests/test_arm64_host.py (new).
  • guest pages on macOS (10e52402; Was: #478):
    host/posix/darwin_mem.c (new) reserves the guest window with Mach, zeroes freed bytes exactly and keeps 4 KiB guest rules on
    16 KiB hosts; hos_mem.c, hos_svc.c, hos_main.c and win32_posix.c call it under __APPLE__. Test:
    tests/test_darwin_guest_memory.py (new).
  • fault contexts (9784b1b5; Was: #436):
    host/posix/darwin_fault.c (new) reads and writes Darwin's signal context on both CPU routes for win32_posix.c's fault
    bridge. Test: tests/test_darwin_fault_context.py (new).
  • waits and deadlines (a492f0ac; Was: #437):
    host/posix/darwin_wait.c and darwin_wait_state.c (new): waits on awake uptime, address waits over one sequence word kept
    in the executable (so the renderer's copy and the executable's wake each other), SRW locks. Test:
    tests/test_darwin_waits.py (new).
  • the Vulkan loader and device admission (58bdbdc0; Was:
    #438): gpu/vk/vk_loader.h, vk_main.cpp,
    host/posix/darwin_vulkan.c (new) find a loader or MoltenVK (RX_VK_LIBRARY, then beside the game), keep SDL on that
    library, take SDL's instance extensions, enable the portability extensions, and log what refuses an instance or device;
    MkwVkHost gains two Apple callbacks (Apple MKWVK_API_VERSION 24). Tests: tests/test_vk_darwin_admission.py,
    tests/test_vk_darwin_sdl.py (new).
  • the Darwin host (6e361411; Was: #490): Mach thread
    identities and times, guarded native fibers (darwin_fiber.c), dyld paths, same-process restart and posix_spawn children
    (darwin_process.c), memory counters and the low-memory notice, a Mach sampling profiler (darwin_prof.c), the menu's
    share commands (vk_menu.cpp); on Linux it also hardens Discord IPC (host/discord_rpc.c) and the thread error paths
    (win32_posix.c). Test: tests/test_darwin_host.py (new).
  • Mach-O build commands (f68637f8; Was: #453):
    nx2/darwin_toolchain.py and nx2/darwin_build.py (new) form the macOS commands (RX_ARCH); Windows' and Linux' arrays move
    into four functions unchanged, element for element, pinned by tests/build_flags_main.json. Test:
    tests/test_macos_build_flags.py (new).
  • helper classification and the macOS package (9a1094da; Was:
    #479): each Darwin helper goes to its image; every library is
    checked against the target (architecture, macOS 14.4, the closure, dyld's binding) and the game folder carries relocated,
    signed copies (nx2/darwin_package.py, nx2/darwin_archive.py, new). Test: tests/test_macos_package.py (new).
  • the builder's memory gate on macOS (25400283; Was: #455):
    free_mb() and tree_rss() call nx2/darwin_memory.py (new: VM counters, libproc). Test: tests/test_mem_gate_darwin.py.
  • control bridge sockets (1b3354a0; Was: #456):
    host/posix/darwin_control_sockets.c (new), called from small Apple-only branches of host/control.c.
  • the control test's quit case (68d940ca; Was: #457): it waits
    for the bridge to listen and reaps it when a check fails; host/control.c gains a hook only the test build compiles.
  • cache file reservations (eb8d5573; Was: #476):
    fcntl(F_PREALLOCATE) in gpu/vk/pipeline_cache_file.h and F_RDADVISE in vk_progcache.cpp on macOS.
  • guest memory ownership on 16 KiB pages (570a5277; Was:
    #480): one owner in the executable (darwin_guest_mem.c, new),
    import pins and native-page watches, frees under the allocator's lock, byte-atomic dirty marks.
  • vk_programs, vk_shader and the debug tools on Darwin (98c070dc; Was:
    #492): an Apple branch in vk_programs.cpp, vk_shader.cpp
    declares environ, and the debug tools' eight guards in hos_main.c name __APPLE__.
  • crash records (e5a10343; Was: #511): getentropy in
    hos_report_run.c, mach_vm_read_overwrite and dyld's image list in hos_crash_record.c.
  • longshot_ctl sessions (40c1c5f5; Was: #516):
    process_start() in scripts/longshot_ctl.py reads the kernel start time and the boot session through sysctl.
  • docs: docs/development.md (the macOS build, its inputs and switches), docs/control.md, docs/pipeline-cache-storage.md.

Measurements

Verdict: works game-free on both Mac routes, and Windows' and Linux' builds keep main's commands: every member's test
fails on main (or cannot build there) and passes here, on arm64 and on x86_64 under Rosetta where it takes an architecture.
The macOS integration builds carrying these commits played on both routes (Testing). No timing: this is a port's host, with
nothing to speed up. The full suite at this head: 572 passed, 15 failed, 17 skipped against main's 543/33/17 on this Mac, with
no check failing that passes on main.

Baseline: the members' before values were measured before their rebase onto main aa95d35f, on main 6c9edffe or on main
with the members a pull request depended on (as each one's description says); the after values are at this head.

Hardware: macOS 26.7.1, Apple M4 Max, 16-core CPU, 64 GB, Apple clang 21.0.0 (game-free: no GPU)
Scene: none (game-free fixtures; the game runs under Testing)
Method: each member's test before and after, two interleaved runs each (the members' runs); at this head each once per
architecture; the suite once through tools/ls-suite.py
How to reproduce: the commands under Testing, in this tree and in main's with the test files copied in

Before: main @ aa95d35f After: this PR @ 40c1c5f5
#454: the runner's declaration tests 9 failures, 1 error of 27 27 of 27; the run reports macos
#477: test_arm64_host.py 0 of 3 arm64 objects compile 3 of 3, every callee-saved register kept; x86-64 objects byte-identical to main's
#478: test_darwin_guest_memory.py freed bytes stay; the window does not compile freed pages read zero, neighbours kept, 128 MiB given back
#436: test_darwin_fault_context.py 44 errors per architecture 7 PASS lines; 2,048 real faults recovered per route
#437: test_darwin_waits.py no Darwin waits pass; without the shared state 20 of 20 cross-image waits stuck, with it 768 of 768 woke
#438: admission and SDL tests fail 9 PASS lines; the SDL bridge's 16 cases
#490: test_darwin_host.py; the suite fail; 531 passed seven groups pass; 543 passed, no new failure
#453: test_macos_build_flags.py 13 failures of 15 16 of 16; Windows and Linux arrays equal main's
#479: test_macos_build_flags, test_macos_package, test_finish_output fail, or do not start (No module named 'darwin_package') pass (16, 24 and 20 tests)
#455: the memory gate's tests fail (2 of 13 against main's build.py) pass
#456, #457: test_control.py the bridge does not compile; the quit runs hang 5 of 5 40 PASS lines; quit slow 20 of 20, quit fail 20 of 20
#476: cache checks 7 of 7 fail 7 of 7 pass
#480: guest memory on 16 KiB pages; test_collect_wide stop; FAIL pass
#492: vk_programs.cpp, vk_shader.cpp compiles; debug-tools test fail, both architectures compile; pass
#511: test_report_run, test_crash_record FAIL pass: 56 completed child runs plus the lock cases
#516: test_longshot_ctl.py 2 failures, 26 errors 45 tests OK
full game-free suite on this Mac 543 passed, 33 failed, 17 skipped 572 passed, 15 failed, 17 skipped
c1-arm64-host-both: darwin_cpu architectures=2 failed=0
c1-guest-memory-both: PASS: Darwin guest memory: arm64, x86_64
c1-crash-record-x86_64: PASS: 56 completed child runs plus locked-owner/kill cases
c1-darwin-host-both: darwin_host_checks architectures=2 failed=0

Flags and settings

New: one renderer switch read on macOS only (RX_VK_LIBRARY), one build switch (RX_ARCH) and four macOS build inputs;
existing switches that work, or say they cannot, on macOS for the first time. Nothing changes off macOS.

Flag What it is Before this PR After this PR Effect Helps / doesn't help / untested Recommendation
RX_VK_LIBRARY=<path> macOS: the first Vulkan loader or MoltenVK dylib to try (then the ones beside the game, then dyld) not read unset: no override the renderer and SDL load that library first; a bad path is logged and the next is tried helps on macOS; not read on Windows or Linux; untested on an Intel Mac leave unset when the game folder carries a loader or MoltenVK
RX_ARCH=arm64 / x86_64 the macOS game's and renderer's architecture (macOS built as Linux) arm64 on Apple silicon, x86_64 on an Intel Mac picks the Mach-O target helps on macOS; Windows and Linux: not read native arm64; x86_64 for the Rosetta route
LONGSHOT_MOLTENVK macOS build input: the MoltenVK dylib, packaged as libMoltenVK.dylib not read unset: a macOS build refuses without it the folder carries MoltenVK macOS only set it
LONGSHOT_SDL3 macOS build input: the SDL3 dylib SDL2-compat loads not read unset; required when the SDL2 file names SDL3 packaged as libSDL3.0.dylib macOS only; untested: SDL2-compat loading the packaged SDL3 in a game set it beside LONGSHOT_SDL2
LONGSHOT_DARWIN_ARCHIVE_RECEIPT, LONGSHOT_DARWIN_ARCHIVE_RECEIPT_SHA256 macOS build inputs: the receipt for FFmpeg's NASM members without a minimum-macOS command, and its digest not read unset: such members refuse admits exactly the receipted members macOS x86_64; arm64 needs none set both for an x86_64 FFmpeg with NASM
RX_MARCH, EMSDK, SDKROOT, LONGSHOT_FFMPEG, LONGSHOT_SDL2, RX_VK_ONLY (existing; changed on macOS) the CPU level, an LLVM prefix, Apple's SDK, FFmpeg and SDL2 locations, a renderer-only build read on a Mac as on Linux (x86-64-v3 on Apple silicon) Mac arm64: no x86 level; x86_64: x86-64-v2; SDL2 packaged and checked; a renderer-only macOS build skips the packaging the macOS build works macOS only; Windows and Linux unchanged leave the Mac defaults
LONGSHOT_NGX_SDK, LONGSHOT_FSR (existing; refused on macOS) NVIDIA NGX's SDK; AMD's FSR runtime read on a Mac as on Linux macOS: the build stops with "no macOS build" no NGX or FSR build on a Mac neither has a macOS library leave unset on a Mac
HOS_PROFILE, HOS_THREAD_TIMES, HOS_SAMPLE, HOS_SAMPLE_ALL, HOS_SAMPLE_FILE, HOS_CHAIN, RX_MAPS (existing) the host profiler, sampler and symbol maps no macOS route on macOS as on Linux (Mach thread state; Mach-O maps) profiling on macOS macOS; untested in a game run for profiling only
HOS_WATCH, HOS_PIN_BY_CORE, HOS_PIN, HOS_RESERVE_CORE (existing) watchpoints, CPU pinning, the reserved core no macOS route on macOS each says once that it is unavailable none on macOS by design leave unset on macOS
HOS_ZERO_ALL_PAGES, HOS_KEEP_FREED_PAGES, RX_NVN_WATCH_TEXELS_SRC, RX_NVN_WATCH_AFTER, RX_NVN_WATCH_ALL (existing) guest-memory and write-watch debugging switches on macOS: the 4 KiB-page assumptions on macOS: 16 KiB host pages, main's meaning debugging works on a Mac macOS; Windows and Linux unchanged debugging only

Testing

Tested: on macOS 26.7.1, Apple M4 Max, at this head 40c1c5f5 (a clean worktree):

  • The seventeen member pull requests' own tests, deduplicated (40 runs, plus one rerun): on arm64, and on x86_64 under Rosetta
    where the test takes an architecture (--arch, or a fixture built with -arch x86_64): the runner's declaration and
    schedule tests, test_arm64_host, test_darwin_guest_memory, the crash inventory, test_darwin_fault_context,
    test_darwin_waits (native and the two-image mode both arches), test_vk_darwin_admission, test_vk_darwin_sdl,
    test_darwin_host, test_display_startup_failure, test_low_memory_notice, test_prof_symbols, test_macos_build_flags,
    test_cpu_target, test_shader_stamp_cache, test_third_party_objects, test_work_lock, test_finish_output,
    test_macos_package, test_mem_gate_darwin, the memory gate's run_all checks, test_control, the cache checks through
    run_all (7 checks, both arches), test_collect_wide, test_debug_tools_linux, test_crash_record, test_report_run,
    test_longshot_ctl: every run exit 0. (The first x86_64 run of the cache checks ran natively by a fault in the runner, a
    PATH= word left unexpanded; it was run again under Rosetta: 7 passed.)
  • python -I -B tests/run_all.py through tools/ls-suite.py at this head: 572 passed, 15 failed, 17 skipped, against main
    aa95d35f's 543/33/17 on this Mac, compared by test name: no check that passes on main fails here. New and passing: the 11
    new tests. Fixed (FAIL on main, pass here): 17, the members' macOS repairs (test_collect_wide, test_control,
    test_crash_record, test_longshot_ctl, test_low_memory_notice, test_prof_symbols, test_mem_gate,
    test_mem_gate_children, test_mirror_trim, test_oot_state_tap, test_report_run and six cache checks).
    test_appimage_package_retry is skipped on macOS by #454's declaration (main's runner took the Mac for Linux and ran it);
    test_dav1d_av1 runs and passes (skipped on main: #454 links dav1d on macOS). The 15 failures fail on main too, on this Mac:
    test_readback_late, test_appimage_player_build, test_options_budget_once, test_vk_pgo, test_crash_dialog,
    test_walk_key, test_lift_cleanup_error, test_game_layout, test_options_path, test_make_game_cache,
    test_cpm_discovery, test_pipeline_tour, test_linux_preflight, test_env_on, test_split_giants.
  • The renderer's link check at this head (each mkwvk:: name one gpu/vk file declares and another defines; each defining
    .cpp compiled with the tree's own renderer_flags(), arm64 and x86_64): 0 of 594 declared names lack a definition, 66 of
    66 objects compiled, 541 cross-file symbols per architecture all defined.
  • Off Apple (unifdef -U__APPLE__ of every changed non-test C/C++ file, main against this head, compared as tokens): 22
    files are main's text; the 11 new .c files hold only Apple blocks, and the 9 new headers off Apple are an include guard or
    #pragma once (darwin_mem.h's declarations are included only inside __APPLE__ blocks). The six that differ are the
    stated every-platform parts: host/discord_rpc.c (#490, Linux: SOCK_CLOEXEC, the exact sockaddr_un length, a too-long
    path skipped, EINTR retried), host/posix/win32_posix.c (#490, Linux: a failed thread allocation returns NULL with
    ERROR_NOT_ENOUGH_MEMORY, a failed pthread_create destroys its mutex and condition variable, GetThreadId of a bad handle
    sets ERROR_INVALID_HANDLE, the record's struct HThread tag), host/posix/windows.h (ERROR_INSUFFICIENT_BUFFER, a
    comment), host/hos_thread.c (<emmintrin.h> on x86-64 only, true on every Windows and Linux target; the affinity call's
    result read into an unused variable), host/hos_main.c (conditions that also name __APPLE__: the same off Apple) and
    host/control.c (#457's hook, compiled only with the test build's HOS_CONTROL_NO_GAME).
  • macOS game runs with these commits in the stack (integration builds carrying this topic's members): arm64, windowless: run
    E9a on I41 78ec1c47: a 1,197 s hold in play, 12 of 12 must-shows, 0 skipped draws, a clean end
    (reports/2026-11-15-mac-perf-E9.md); x86_64 under Rosetta: run #34 on I38 3f872b0c: 16 m 52 s of play, every draw
    drawn, 19 of 19 checks, a clean exit (reports/2026-11-14-mac-startup-34-x86_64.md).

Not tested: Windows and Linux: nothing was built or run there (the test request below): Discord presence with the new
socket code, the thread-creation error paths (they need an allocation or pthread_create failure), scripts/prof.py on a real
Linux capture, the debug tools and test_copy_save there. A complete macOS game build from this PR alone (the renderer layers
are the next topics); a real restart, share or Discord client on macOS; macOS 14.4 itself (the deployment target; every run
was on 26.7.1); an Intel Mac.

Must be tested:

  • Windows and Linux, any GPU: build this PR and main aa95d35f the same way, run python -I -B tests/run_all.py on each and
    start each to the title, expecting the new tests to pass or skip with their macOS reason, no other check to change status,
    and the vk: lines to match main's (the shader caches are prepared again once, as with any vk_shader.cpp edit) (Test
    Farm: @Beanstalk windows linux, build, run_all and start to the title)

Risks

What could break: on Linux, Discord presence (the new socket flags and length) and the thread-creation error paths; the
build scripts' Windows and Linux arrays moved into functions (pinned element for element against main's). On macOS
everything is new: the host, the build and the package have run game-free and in the integration builds' game runs only.

Turning it off: revert the PR (macOS code is behind __APPLE__ or in Darwin-only files; nothing on Windows or Linux is
switched).

Compatibility: every platform lifts the game again once after updating (nx2/kit.py and the new
nx2/darwin_toolchain.py are lift sources) and prepares its shaders again once (vk_shader.cpp is in the translator's
stamp: ebbf160ce9626041 on main, 6241b7736c8060e3 here); the builder compiles the host's objects again once (hos.h and
host/posix/*.h change). The vk ABI:
MKWVK_API_VERSION is 24 on macOS only (two callbacks appended to MkwVkHost); Windows and Linux keep main's 23 with the same
structure. Saves and longshot_options.ini are unchanged; on macOS longshot_ctl's session files store the new process
identity.

Issues

See #420. The macOS topic PRs, merged in this order; "topic N" in each description means these: 1 #845 (macos-host), 2 #846 (vulkan-on-metal, on 1), 3 #847 (mvk-descriptor-limits), 4 #848 (shader-backend, on 2, 3 and #431), 5 #849 (precompile-metal, on 4), 6 #850 (draw-path, on 4), 7 #851 (draw-path-quads-mesh, on 6, #705 and #707), 8 #852 (mac-perf, on 7).

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main: on aa95d35f.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named). (macOS: 572/15/17, the 15 failures also fail on main, named under Testing; Windows and Linux: the test request.)
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value.
  • MKWVK_API_VERSION bumped (gpu/vk/vk_api.h's MkwVkHost or MkwVkRenderer changed).
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. (Not built there yet: the test request.)
  • Docs updated.
**Type:** feat · **Risk:** medium · **Tested on:** macOS 26.7.1, Apple M4 Max (arm64; x86_64 under Rosetta) · **Needs:** Windows and Linux, any GPU ## Why Nobody can build or run LS on a Mac today. The builder takes the Linux route there and hands Apple's tools ELF options and x86 CPU flags; the host's POSIX layer is written for Linux (futex waits, `ucontext` fibers, `/proc`, Linux's signal context, `MAP_FIXED_NOREPLACE` and `memfd_create` for the guest window, `getrandom`, `process_vm_readv`), its jumps and pause hints are x86 only, and the renderer looks for `libvulkan.so.1` with X11 or Wayland surfaces and never enables the portability extensions MoltenVK requires. The game-free runner thinks a Mac is Linux, and the control bridge, crash records, `longshot_ctl` and the builder's memory gate have no macOS route. This PR is the macOS host: it builds on a Mac, natively on Apple silicon and as x86_64 under Rosetta, packages a relocatable game folder for macOS 14.4 and later, and runs the host with its control, crash records and the Vulkan loader. It is the first part of the macOS port. See #420. ## What changed The build scripts get a Mach-O command path (arm64 or x86_64, macOS 14.4) and a packager; the host gets native Darwin memory, waits, faults, threads, fibers, processes, profiler, control sockets and crash records, each in Apple-only branches or new `host/posix/darwin_*.c` files; the renderer loads a Vulkan loader or MoltenVK on macOS; the game-free runner, the builder's memory gate and `longshot_ctl` know macOS. Windows and Linux keep their code, but for a few stated every-platform changes (Testing, off Apple). The seventeen original pull requests, in commit order: - the game-free runner knows macOS (`e81d4af4`; Was: [#454](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/454)): `tests/run_all.py` reports `macos`, reads a `macos` skip reason and keeps macOS timing apart; 18 checks a Mac has no subject for are skipped there; three fixtures get Apple-only repairs. - host jumps and pause hints on arm64 (`441182e2`; Was: [#477](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/477)): `host/posix/darwin_cpu.c` (new) has the arm64 jump in assembly and a `yield` pause; the x86 bodies stay for every other target. Test: `tests/test_arm64_host.py` (new). - guest pages on macOS (`10e52402`; Was: [#478](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/478)): `host/posix/darwin_mem.c` (new) reserves the guest window with Mach, zeroes freed bytes exactly and keeps 4 KiB guest rules on 16 KiB hosts; `hos_mem.c`, `hos_svc.c`, `hos_main.c` and `win32_posix.c` call it under `__APPLE__`. Test: `tests/test_darwin_guest_memory.py` (new). - fault contexts (`9784b1b5`; Was: [#436](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/436)): `host/posix/darwin_fault.c` (new) reads and writes Darwin's signal context on both CPU routes for `win32_posix.c`'s fault bridge. Test: `tests/test_darwin_fault_context.py` (new). - waits and deadlines (`a492f0ac`; Was: [#437](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/437)): `host/posix/darwin_wait.c` and `darwin_wait_state.c` (new): waits on awake uptime, address waits over one sequence word kept in the executable (so the renderer's copy and the executable's wake each other), SRW locks. Test: `tests/test_darwin_waits.py` (new). - the Vulkan loader and device admission (`58bdbdc0`; Was: [#438](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/438)): `gpu/vk/vk_loader.h`, `vk_main.cpp`, `host/posix/darwin_vulkan.c` (new) find a loader or MoltenVK (`RX_VK_LIBRARY`, then beside the game), keep SDL on that library, take SDL's instance extensions, enable the portability extensions, and log what refuses an instance or device; `MkwVkHost` gains two Apple callbacks (Apple `MKWVK_API_VERSION` 24). Tests: `tests/test_vk_darwin_admission.py`, `tests/test_vk_darwin_sdl.py` (new). - the Darwin host (`6e361411`; Was: [#490](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/490)): Mach thread identities and times, guarded native fibers (`darwin_fiber.c`), dyld paths, same-process restart and `posix_spawn` children (`darwin_process.c`), memory counters and the low-memory notice, a Mach sampling profiler (`darwin_prof.c`), the menu's share commands (`vk_menu.cpp`); on Linux it also hardens Discord IPC (`host/discord_rpc.c`) and the thread error paths (`win32_posix.c`). Test: `tests/test_darwin_host.py` (new). - Mach-O build commands (`f68637f8`; Was: [#453](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/453)): `nx2/darwin_toolchain.py` and `nx2/darwin_build.py` (new) form the macOS commands (`RX_ARCH`); Windows' and Linux' arrays move into four functions unchanged, element for element, pinned by `tests/build_flags_main.json`. Test: `tests/test_macos_build_flags.py` (new). - helper classification and the macOS package (`9a1094da`; Was: [#479](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/479)): each Darwin helper goes to its image; every library is checked against the target (architecture, macOS 14.4, the closure, dyld's binding) and the game folder carries relocated, signed copies (`nx2/darwin_package.py`, `nx2/darwin_archive.py`, new). Test: `tests/test_macos_package.py` (new). - the builder's memory gate on macOS (`25400283`; Was: [#455](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/455)): `free_mb()` and `tree_rss()` call `nx2/darwin_memory.py` (new: VM counters, libproc). Test: `tests/test_mem_gate_darwin.py`. - control bridge sockets (`1b3354a0`; Was: [#456](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/456)): `host/posix/darwin_control_sockets.c` (new), called from small Apple-only branches of `host/control.c`. - the control test's quit case (`68d940ca`; Was: [#457](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/457)): it waits for the bridge to listen and reaps it when a check fails; `host/control.c` gains a hook only the test build compiles. - cache file reservations (`eb8d5573`; Was: [#476](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/476)): `fcntl(F_PREALLOCATE)` in `gpu/vk/pipeline_cache_file.h` and `F_RDADVISE` in `vk_progcache.cpp` on macOS. - guest memory ownership on 16 KiB pages (`570a5277`; Was: [#480](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/480)): one owner in the executable (`darwin_guest_mem.c`, new), import pins and native-page watches, frees under the allocator's lock, byte-atomic dirty marks. - vk_programs, vk_shader and the debug tools on Darwin (`98c070dc`; Was: [#492](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/492)): an Apple branch in `vk_programs.cpp`, `vk_shader.cpp` declares `environ`, and the debug tools' eight guards in `hos_main.c` name `__APPLE__`. - crash records (`e5a10343`; Was: [#511](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/511)): `getentropy` in `hos_report_run.c`, `mach_vm_read_overwrite` and dyld's image list in `hos_crash_record.c`. - `longshot_ctl` sessions (`40c1c5f5`; Was: [#516](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/516)): `process_start()` in `scripts/longshot_ctl.py` reads the kernel start time and the boot session through `sysctl`. - docs: `docs/development.md` (the macOS build, its inputs and switches), `docs/control.md`, `docs/pipeline-cache-storage.md`. ## Measurements **Verdict:** works game-free on both Mac routes, and Windows' and Linux' builds keep main's commands: every member's test fails on main (or cannot build there) and passes here, on arm64 and on x86_64 under Rosetta where it takes an architecture. The macOS integration builds carrying these commits played on both routes (Testing). No timing: this is a port's host, with nothing to speed up. The full suite at this head: 572 passed, 15 failed, 17 skipped against main's 543/33/17 on this Mac, with no check failing that passes on main. Baseline: the members' before values were measured before their rebase onto main `aa95d35f`, on main `6c9edffe` or on main with the members a pull request depended on (as each one's description says); the after values are at this head. Hardware: macOS 26.7.1, Apple M4 Max, 16-core CPU, 64 GB, Apple clang 21.0.0 (game-free: no GPU) Scene: none (game-free fixtures; the game runs under Testing) Method: each member's test before and after, two interleaved runs each (the members' runs); at this head each once per architecture; the suite once through `tools/ls-suite.py` How to reproduce: the commands under Testing, in this tree and in main's with the test files copied in | | Before: main @ aa95d35f | After: this PR @ 40c1c5f5 | |---|---|---| | #454: the runner's declaration tests | 9 failures, 1 error of 27 | 27 of 27; the run reports `macos` | | #477: `test_arm64_host.py` | 0 of 3 arm64 objects compile | 3 of 3, every callee-saved register kept; x86-64 objects byte-identical to main's | | #478: `test_darwin_guest_memory.py` | freed bytes stay; the window does not compile | freed pages read zero, neighbours kept, 128 MiB given back | | #436: `test_darwin_fault_context.py` | 44 errors per architecture | 7 PASS lines; 2,048 real faults recovered per route | | #437: `test_darwin_waits.py` | no Darwin waits | pass; without the shared state 20 of 20 cross-image waits stuck, with it 768 of 768 woke | | #438: admission and SDL tests | fail | 9 PASS lines; the SDL bridge's 16 cases | | #490: `test_darwin_host.py`; the suite | fail; 531 passed | seven groups pass; 543 passed, no new failure | | #453: `test_macos_build_flags.py` | 13 failures of 15 | 16 of 16; Windows and Linux arrays equal main's | | #479: `test_macos_build_flags`, `test_macos_package`, `test_finish_output` | fail, or do not start (`No module named 'darwin_package'`) | pass (16, 24 and 20 tests) | | #455: the memory gate's tests | fail (2 of 13 against main's `build.py`) | pass | | #456, #457: `test_control.py` | the bridge does not compile; the quit runs hang 5 of 5 | 40 PASS lines; `quit slow` 20 of 20, `quit fail` 20 of 20 | | #476: cache checks | 7 of 7 fail | 7 of 7 pass | | #480: guest memory on 16 KiB pages; `test_collect_wide` | stop; FAIL | pass | | #492: `vk_programs.cpp`, `vk_shader.cpp` compiles; debug-tools test | fail, both architectures | compile; pass | | #511: `test_report_run`, `test_crash_record` | FAIL | pass: 56 completed child runs plus the lock cases | | #516: `test_longshot_ctl.py` | 2 failures, 26 errors | 45 tests OK | | full game-free suite on this Mac | 543 passed, 33 failed, 17 skipped | 572 passed, 15 failed, 17 skipped | ``` c1-arm64-host-both: darwin_cpu architectures=2 failed=0 c1-guest-memory-both: PASS: Darwin guest memory: arm64, x86_64 c1-crash-record-x86_64: PASS: 56 completed child runs plus locked-owner/kill cases c1-darwin-host-both: darwin_host_checks architectures=2 failed=0 ``` ### Flags and settings New: one renderer switch read on macOS only (`RX_VK_LIBRARY`), one build switch (`RX_ARCH`) and four macOS build inputs; existing switches that work, or say they cannot, on macOS for the first time. Nothing changes off macOS. | Flag | What it is | Before this PR | After this PR | Effect | Helps / doesn't help / untested | Recommendation | |---|---|---|---|---|---|---| | `RX_VK_LIBRARY=<path>` | macOS: the first Vulkan loader or MoltenVK dylib to try (then the ones beside the game, then dyld) | not read | unset: no override | the renderer and SDL load that library first; a bad path is logged and the next is tried | helps on macOS; not read on Windows or Linux; untested on an Intel Mac | leave unset when the game folder carries a loader or MoltenVK | | `RX_ARCH=arm64` / `x86_64` | the macOS game's and renderer's architecture | (macOS built as Linux) | arm64 on Apple silicon, x86_64 on an Intel Mac | picks the Mach-O target | helps on macOS; Windows and Linux: not read | native arm64; x86_64 for the Rosetta route | | `LONGSHOT_MOLTENVK` | macOS build input: the MoltenVK dylib, packaged as `libMoltenVK.dylib` | not read | unset: a macOS build refuses without it | the folder carries MoltenVK | macOS only | set it | | `LONGSHOT_SDL3` | macOS build input: the SDL3 dylib SDL2-compat loads | not read | unset; required when the SDL2 file names SDL3 | packaged as `libSDL3.0.dylib` | macOS only; untested: SDL2-compat loading the packaged SDL3 in a game | set it beside `LONGSHOT_SDL2` | | `LONGSHOT_DARWIN_ARCHIVE_RECEIPT`, `LONGSHOT_DARWIN_ARCHIVE_RECEIPT_SHA256` | macOS build inputs: the receipt for FFmpeg's NASM members without a minimum-macOS command, and its digest | not read | unset: such members refuse | admits exactly the receipted members | macOS x86_64; arm64 needs none | set both for an x86_64 FFmpeg with NASM | | `RX_MARCH`, `EMSDK`, `SDKROOT`, `LONGSHOT_FFMPEG`, `LONGSHOT_SDL2`, `RX_VK_ONLY` (existing; changed on macOS) | the CPU level, an LLVM prefix, Apple's SDK, FFmpeg and SDL2 locations, a renderer-only build | read on a Mac as on Linux (`x86-64-v3` on Apple silicon) | Mac arm64: no x86 level; x86_64: `x86-64-v2`; SDL2 packaged and checked; a renderer-only macOS build skips the packaging | the macOS build works | macOS only; Windows and Linux unchanged | leave the Mac defaults | | `LONGSHOT_NGX_SDK`, `LONGSHOT_FSR` (existing; refused on macOS) | NVIDIA NGX's SDK; AMD's FSR runtime | read on a Mac as on Linux | macOS: the build stops with "no macOS build" | no NGX or FSR build on a Mac | neither has a macOS library | leave unset on a Mac | | `HOS_PROFILE`, `HOS_THREAD_TIMES`, `HOS_SAMPLE`, `HOS_SAMPLE_ALL`, `HOS_SAMPLE_FILE`, `HOS_CHAIN`, `RX_MAPS` (existing) | the host profiler, sampler and symbol maps | no macOS route | on macOS as on Linux (Mach thread state; Mach-O maps) | profiling on macOS | macOS; untested in a game run | for profiling only | | `HOS_WATCH`, `HOS_PIN_BY_CORE`, `HOS_PIN`, `HOS_RESERVE_CORE` (existing) | watchpoints, CPU pinning, the reserved core | no macOS route | on macOS each says once that it is unavailable | none on macOS | by design | leave unset on macOS | | `HOS_ZERO_ALL_PAGES`, `HOS_KEEP_FREED_PAGES`, `RX_NVN_WATCH_TEXELS_SRC`, `RX_NVN_WATCH_AFTER`, `RX_NVN_WATCH_ALL` (existing) | guest-memory and write-watch debugging switches | on macOS: the 4 KiB-page assumptions | on macOS: 16 KiB host pages, `main`'s meaning | debugging works on a Mac | macOS; Windows and Linux unchanged | debugging only | ## Testing **Tested:** on macOS 26.7.1, Apple M4 Max, at this head `40c1c5f5` (a clean worktree): - The seventeen member pull requests' own tests, deduplicated (40 runs, plus one rerun): on arm64, and on x86_64 under Rosetta where the test takes an architecture (`--arch`, or a fixture built with `-arch x86_64`): the runner's declaration and schedule tests, `test_arm64_host`, `test_darwin_guest_memory`, the crash inventory, `test_darwin_fault_context`, `test_darwin_waits` (native and the two-image mode both arches), `test_vk_darwin_admission`, `test_vk_darwin_sdl`, `test_darwin_host`, `test_display_startup_failure`, `test_low_memory_notice`, `test_prof_symbols`, `test_macos_build_flags`, `test_cpu_target`, `test_shader_stamp_cache`, `test_third_party_objects`, `test_work_lock`, `test_finish_output`, `test_macos_package`, `test_mem_gate_darwin`, the memory gate's run_all checks, `test_control`, the cache checks through run_all (7 checks, both arches), `test_collect_wide`, `test_debug_tools_linux`, `test_crash_record`, `test_report_run`, `test_longshot_ctl`: every run exit 0. (The first x86_64 run of the cache checks ran natively by a fault in the runner, a `PATH=` word left unexpanded; it was run again under Rosetta: 7 passed.) - `python -I -B tests/run_all.py` through `tools/ls-suite.py` at this head: 572 passed, 15 failed, 17 skipped, against main `aa95d35f`'s 543/33/17 on this Mac, compared by test name: no check that passes on main fails here. New and passing: the 11 new tests. Fixed (FAIL on main, pass here): 17, the members' macOS repairs (`test_collect_wide`, `test_control`, `test_crash_record`, `test_longshot_ctl`, `test_low_memory_notice`, `test_prof_symbols`, `test_mem_gate`, `test_mem_gate_children`, `test_mirror_trim`, `test_oot_state_tap`, `test_report_run` and six cache checks). `test_appimage_package_retry` is skipped on macOS by #454's declaration (main's runner took the Mac for Linux and ran it); `test_dav1d_av1` runs and passes (skipped on main: #454 links dav1d on macOS). The 15 failures fail on main too, on this Mac: `test_readback_late`, `test_appimage_player_build`, `test_options_budget_once`, `test_vk_pgo`, `test_crash_dialog`, `test_walk_key`, `test_lift_cleanup_error`, `test_game_layout`, `test_options_path`, `test_make_game_cache`, `test_cpm_discovery`, `test_pipeline_tour`, `test_linux_preflight`, `test_env_on`, `test_split_giants`. - The renderer's link check at this head (each `mkwvk::` name one `gpu/vk` file declares and another defines; each defining `.cpp` compiled with the tree's own `renderer_flags()`, arm64 and x86_64): 0 of 594 declared names lack a definition, 66 of 66 objects compiled, 541 cross-file symbols per architecture all defined. - Off Apple (`unifdef -U__APPLE__` of every changed non-test C/C++ file, main against this head, compared as tokens): 22 files are main's text; the 11 new `.c` files hold only Apple blocks, and the 9 new headers off Apple are an include guard or `#pragma once` (`darwin_mem.h`'s declarations are included only inside `__APPLE__` blocks). The six that differ are the stated every-platform parts: `host/discord_rpc.c` (#490, Linux: `SOCK_CLOEXEC`, the exact `sockaddr_un` length, a too-long path skipped, `EINTR` retried), `host/posix/win32_posix.c` (#490, Linux: a failed thread allocation returns `NULL` with `ERROR_NOT_ENOUGH_MEMORY`, a failed `pthread_create` destroys its mutex and condition variable, `GetThreadId` of a bad handle sets `ERROR_INVALID_HANDLE`, the record's `struct HThread` tag), `host/posix/windows.h` (`ERROR_INSUFFICIENT_BUFFER`, a comment), `host/hos_thread.c` (`<emmintrin.h>` on x86-64 only, true on every Windows and Linux target; the affinity call's result read into an unused variable), `host/hos_main.c` (conditions that also name `__APPLE__`: the same off Apple) and `host/control.c` (#457's hook, compiled only with the test build's `HOS_CONTROL_NO_GAME`). - macOS game runs with these commits in the stack (integration builds carrying this topic's members): arm64, windowless: run E9a on I41 `78ec1c47`: a 1,197 s hold in play, 12 of 12 must-shows, 0 skipped draws, a clean end (`reports/2026-11-15-mac-perf-E9.md`); x86_64 under Rosetta: run #34 on I38 `3f872b0c`: 16 m 52 s of play, every draw drawn, 19 of 19 checks, a clean exit (`reports/2026-11-14-mac-startup-34-x86_64.md`). **Not tested:** Windows and Linux: nothing was built or run there (the test request below): Discord presence with the new socket code, the thread-creation error paths (they need an allocation or `pthread_create` failure), `scripts/prof.py` on a real Linux capture, the debug tools and `test_copy_save` there. A complete macOS game build from this PR alone (the renderer layers are the next topics); a real restart, share or Discord client on macOS; macOS 14.4 itself (the deployment target; every run was on 26.7.1); an Intel Mac. **Must be tested:** - Windows and Linux, any GPU: build this PR and main `aa95d35f` the same way, run `python -I -B tests/run_all.py` on each and start each to the title, expecting the new tests to pass or skip with their macOS reason, no other check to change status, and the `vk:` lines to match main's (the shader caches are prepared again once, as with any `vk_shader.cpp` edit) (Test Farm: @Beanstalk windows linux, build, run_all and start to the title) ## Risks **What could break:** on Linux, Discord presence (the new socket flags and length) and the thread-creation error paths; the build scripts' Windows and Linux arrays moved into functions (pinned element for element against main's). On macOS everything is new: the host, the build and the package have run game-free and in the integration builds' game runs only. **Turning it off:** revert the PR (macOS code is behind `__APPLE__` or in Darwin-only files; nothing on Windows or Linux is switched). **Compatibility:** every platform lifts the game again once after updating (`nx2/kit.py` and the new `nx2/darwin_toolchain.py` are lift sources) and prepares its shaders again once (`vk_shader.cpp` is in the translator's stamp: `ebbf160ce9626041` on main, `6241b7736c8060e3` here); the builder compiles the host's objects again once (`hos.h` and `host/posix/*.h` change). The vk ABI: `MKWVK_API_VERSION` is 24 on macOS only (two callbacks appended to `MkwVkHost`); Windows and Linux keep main's 23 with the same structure. Saves and `longshot_options.ini` are unchanged; on macOS `longshot_ctl`'s session files store the new process identity. ## Issues See #420. The macOS topic PRs, merged in this order; "topic N" in each description means these: 1 #845 (macos-host), 2 #846 (vulkan-on-metal, on 1), 3 #847 (mvk-descriptor-limits), 4 #848 (shader-backend, on 2, 3 and #431), 5 #849 (precompile-metal, on 4), 6 #850 (draw-path, on 4), 7 #851 (draw-path-quads-mesh, on 6, #705 and #707), 8 #852 (mac-perf, on 7). ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`: on `aa95d35f`. - [ ] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). (macOS: 572/15/17, the 15 failures also fail on main, named under Testing; Windows and Linux: the test request.) - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value. - [x] `MKWVK_API_VERSION` bumped (`gpu/vk/vk_api.h`'s `MkwVkHost` or `MkwVkRenderer` changed). - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [ ] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. (Not built there yet: the test request.) - [x] Docs updated.
Was: #454 (#454), branch mac/run-all at 264f826a7c (Sweep3, on main aa95d35f).

Its own commits, squashed:
- test: teach the game-free runner about macOS (45c54bc6f)
- test: skip main's new Windows-only guard check on macOS, and undo the SDK's vsnprintf macro in a fixture (264f826a7)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #477 (#477), branch mac/arm64-host at 0f021f29c1 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): compile host jumps and pause hints on macOS arm64 (0f021f29c)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #478 (#478), branch mac/guest-memory at dfb71ec850 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): preserve guest pages when discarding on macOS (b668404c8)
- fix(runtime): retain guest-page rounding in Darwin memory wrappers (e9c77d9f3)
- test(runtime): cut main's int hos_commit in the Darwin guest-memory test (7e737ce0f)
- test(runtime): follow main's HLE call counts in the Darwin guest-memory fixture (dfb71ec85)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #436 (#436), branch mac/fault-contexts at bccfd1c2e9 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): translate macOS fault contexts on both CPU routes (08940fb3d)
- test(runtime): keep Darwin fault checks native by default (7d7f99dcb)
- test(runtime): classify the fault bridge's fatal _exit in main's exit inventory (bccfd1c2e)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #437 (#437), branch mac/waits at beb8a2881a (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): port Win32 waits and deadlines to macOS (2f05d007f)
- test(runtime): link Darwin waits into the pointer fixture (ef081688d)
- fix(macos): share address wait state through the executable (186a461c5)
- docs(runtime): describe the executable-owned macOS address-wait state (beb8a2881)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #438 (#438), branch mac/vk-admission at 681e37081d (Sweep3, on main aa95d35f).

Its own commits, squashed:
- feat(vk): add macOS Vulkan loader and device admission (6f34d00bc)
- test(vk): use semantic admission contracts (fdd161190)
- test(vk): follow main's LoadLibraryA and float-add choice in the admission fixture (3e088644f)
- test(vk): pin the admission ABI at main's version 23 and macOS 24 (4f4ca3c73)
- fix(macos): a window without Vulkan extensions ends as a clean exit, as main's exit inventory asks (681e37081)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #490 (#490), branch mac/darwin-host at 162a39dcd3 (Sweep3, on main aa95d35f).

It was stacked on #436, #437, #438, #454, #477, #478; their changes are the earlier commits here.

Its own commits, squashed:
- feat(macos): complete Darwin host lifecycle and diagnostics (71a9ed0bb)
- fix(macos): integrate profile consumers and joined-thread shutdown (f420761ab)
- docs(macos): describe Darwin profile symbol loading (04e40191a)
- test(macos): integration fix: cut the tagged HThread in the waits fixture (9c18e64c4)
- test(macos): integration fix: stub the kept startup in the display fixture (5f8d511e6)
- test(macos): integration fix: prof symbols run on macOS, not a skip (a1e73d31e)
- test(macos): the memory-notice fixture runs the Darwin query (f4d7aaf76)
- fix(macos): a failed swap query still shows the low-RAM notice (28ed288a2)
- test(macos): the Darwin LoadLibraryA keeps dlerror()'s text for hos_load_error (52faf1d3d)
- fix(macos): integration fix: main's process affinity for new threads is Linux-only (61ec2411b)
- fix(macos): the POSIX main's end after the game's thread marks the clean end, as main's exit inventory asks (162a39dcd)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #453 (#453), branch mac/build-flags at 8ca4bff7a4 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- build(macos): discover dual-architecture toolchains and form Mach-O commands (499e3853a)
- test(macos): default real link fixtures to the process architecture (f6f6f042c)
- test(macos): isolate synthetic command paths from the test host (7c846ae91)
- build(macos): keep third_party/a64-kit as it is; nx2/darwin_toolchain.py makes its commands Mach-O (88054c966)
- build(macos): follow main's one-way renderer build and CPU target in the moved build code (a5b02633d)
- test(macos): the frozen Windows/Linux build arrays are main e090cc48's (c3009e01c)
- test: main's third-party objects test reads build.py with this PR's macOS names (8ca4bff7a)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #479 (#479), branch mac/build-complete at 1bd269c7e2 (Sweep3, on main aa95d35f).

It was stacked on #437, #453; their changes are the earlier commits here.

Its own commits, squashed:
- build(macos): complete strict standalone dependency packaging (9424b4886)
- fix(macos): bind SDL3, imports and archive members to their real formats (8ad0e3265)
- fix(macos): keep the lazy-bind library ordinal across DONE (48f6ec02b)
- build(macos): take the architecture and SDK from darwin_toolchain when packaging (5ce85548c)
- build(macos): no prebuilt renderer on macOS either, as main has none (1bd269c7e)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #455 (#455), branch mac/mem-gate at 82c2e10341 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(builder): account for available memory and compiler children on macOS (8f8e03b7f)
- fix(builder): avoid stale Darwin available-memory snapshots (5240e431a)
- fix(builder): keep Darwin RSS behind the shared tree backend (82c2e1034)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #456 (#456), branch mac/control-sockets at fc2f104050 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): support control bridge Unix sockets on macOS (5fc3fe390)
- test(control): link the bridge's macOS socket helpers into test_oot_state_tap's fixture (fc2f10405)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #457 (#457), branch mac/control-quit at fe3e8c9178 (Sweep3, on main aa95d35f).

It was stacked on #456; their changes are the earlier commits here.

Its own commits, squashed:
- test(control): quit's parent waits for its bridge to listen, and a failed check ends the bridge it forked (fe3e8c917)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #476 (#476), branch mac/cache-files at 7e561fbb53 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(vk): preserve cache file reservations on macOS (7e561fbb5)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #480 (#480), branch mac/guest-16k at 657b780359 (Sweep3, on main aa95d35f).

It was stacked on #436, #478; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- fix(macos): serialize guest backing and native-page watch lifetimes (d7d999b92)
- fix(macos): retain pending watch faults across protection changes (a6a3e9e98)
- fix(macos): make the guest-memory changes Apple-only; Windows and Linux keep main's code (126d7bd67)
- docs(macos): describe the guest window's one owner, import pins and native-page watches (657b78035)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #492 (#492), branch mac/renderer-compile at 59f750aa38 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(macos): the renderer's last two files compile on Darwin (7ee5fd584)
- fix(macos): the debug tools are compiled on Darwin too (82b2d6606)
- test(macos): the debug tools check reads hos_oot_player_seen's body too (59f750aa3)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #511 (#511), branch mac/crash-records at c4d95017aa (Sweep3, on main aa95d35f).

It was stacked on #436; their changes are the earlier commits here.

Its own commits, squashed:
- fix(runtime): take the macOS report run id from getentropy (d3e86ddd7)
- fix(runtime): read crash-record memory and modules without /proc on macOS (aa039e142)
- test(runtime): build the crash-record fixture on macOS (adebf9dbb)
- test(runtime): link the macOS fault bridge into the crash-record fixture (c4d95017a)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
fix(control): keep command-line sessions alive on macOS
Some checks failed
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 14s
CI / Workflow lint (actionlint) (pull_request) Successful in 19s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 19s
Third-party parts / As their notes say (pull_request) Successful in 30s
PR description / Description follows the template (pull_request_target) Successful in 19s
40c1c5f5f8
Was: #516 (#516), branch mac/longshot-ctl-darwin at 3b9d3cfa2a (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(control): tell macOS processes apart by their sysctl start time (56f4ca876)
- test(control): compare launch's data folder with the resolved run folder (3b9d3cfa2)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Owner

This conflicts with main now: nx2/build.py, nx2/make_game.py and docs/development.md changed on main when the WebGPU renderer was removed from the Windows build (#577: wgpu_native.dll and its build lines are gone). Could you rebase onto current main? The conflicts looked like lines the two sides both touched next to each other, but they repeat in many of this stack's commits, so I left it to you rather than guess.

This conflicts with `main` now: `nx2/build.py`, `nx2/make_game.py` and `docs/development.md` changed on `main` when the WebGPU renderer was removed from the Windows build (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/577: `wgpu_native.dll` and its build lines are gone). Could you rebase onto current `main`? The conflicts looked like lines the two sides both touched next to each other, but they repeat in many of this stack's commits, so I left it to you rather than guess.
Some checks failed
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 14s
CI / Workflow lint (actionlint) (pull_request) Successful in 19s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 19s
Third-party parts / As their notes say (pull_request) Successful in 30s
PR description / Description follows the template (pull_request_target) Successful in 19s
This pull request has changes conflicting with the target branch.
  • docs/development.md
  • nx2/build.py
  • nx2/make_game.py
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'mac/topic-macos-host:mooki-mac/topic-macos-host'
git switch 'mooki-mac/topic-macos-host'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!845
No description provided.