fix(macos): build vk_programs, vk_shader and the debug tools on Darwin #492

Closed
mooki wants to merge 3 commits from mooki/Longshot:mac/renderer-compile into main
Member

Type: fix · Risk: low · Tested on: macOS 26.7.1, Apple M4 Max (game-free checks, arm64 and x86_64 compiles; no game run on this branch) · Needs: none

Why

A macOS build stops in three files: two in the renderer (gpu/vk/vk_programs.cpp, gpu/vk/vk_shader.cpp) do not
compile, and the debug tools in host/hos_main.c are left out of a macOS build, so the executable does not link. This
PR gives each an Apple branch, part of the macOS port (#420). Windows and Linux compile the same text as before.
Every platform rebuilds its shader caches once after this PR, because it edits gpu/vk/vk_shader.cpp, which the
shader stamp hashes.

  • vk_programs.cpp: the program life log's thread_major_faults() asks getrusage(RUSAGE_THREAD). Darwin has no
    per-thread fault count at all: getrusage takes only RUSAGE_SELF and RUSAGE_CHILDREN (sys/resource.h), the
    per-thread thread_info flavours (THREAD_BASIC_INFO, THREAD_EXTENDED_INFO, which is proc_threadinfo) hold run
    times and scheduling but no faults or page-ins, and task_events_info, proc_taskinfo and rusage_info's
    ri_pageins count the whole task.
  • vk_shader.cpp: translator_stamp reads _environ, which host/posix/windows.h defines as environ. Darwin's
    headers do not declare environ for C++ (only crt_externs.h's _NSGetEnviron).
  • hos_main.c: the eight debug-tool regions (cheats, pouch and inventory, clock, teleport and age, flight, lift,
    free view) are guarded by #if defined(_WIN32) || defined(__linux__). A macOS build compiles them out, but
    host/control.c's game table names seven of their functions.

How to reproduce

Seen on: macOS 26.7.1, Apple M4 Max, Apple clang 21.0.0 (Command Line Tools, SDK 27), arm64 and x86_64 (compiles
with the renderer's flags, and this PR's game-free test against main's hos_main.c); the link error on a macOS
integration build. Only macOS is affected.
Settings and switches: defaults (the renderer's flags from nx2/build.py's renderer_flags()).
Steps: on a Mac, compile main's gpu/vk/vk_programs.cpp and gpu/vk/vk_shader.cpp with the renderer's flags for
arm64 or x86_64; and run this PR's python -I -B tests/test_debug_tools_linux.py beside main's host/hos_main.c.
Expected: two Mach-O objects, and every debug tool compiled on macOS as on Windows and Linux.
Actual: at main @ 6c9edffe, on each architecture:

gpu/vk/vk_programs.cpp:46:19: error: use of undeclared identifier 'RUSAGE_THREAD'
gpu/vk/vk_shader.cpp:1306:21: error: use of undeclared identifier 'environ'; did you mean 'env_on'?
ld: Undefined symbols: _hos_oot_current_map, _hos_oot_destination, _hos_oot_teleport_ask, _hos_oot_teleport_result,
    _hos_oot_teleport_cancel, _hos_oot_age_ask, _hos_oot_state   (named by host/control.c's game table)

The test exits 1 with 26 lines of the debug tools not compiled on macOS. (The ld line is from the macOS integration
branch's link, once the two compile errors were fixed.)

What changed

Each of the three files gets an Apple branch: the life log says major_faults unavailable on macOS, vk_shader.cpp
declares environ, and the debug tools' eight guards name __APPLE__ too. Windows and Linux preprocess to main's text;
the test now checks the guards for macOS as well.

  • Read first: the eight guards in host/hos_main.c and the Apple branches of vk_programs.cpp and vk_shader.cpp.
  • gpu/vk/vk_programs.cpp (Apple only): thread_major_faults() and its start value are not compiled on Darwin,
    with a comment giving the reason above. The life log's create line ends major_faults unavailable there instead of
    major_faults <n>. It is one token, so a parser that splits on spaces still finds the key and no number. Neither the
    task's page-in count (other threads' disk waits booked to this create call) nor a 0 (which reads as "no faults") is
    logged in its place.
  • gpu/vk/vk_shader.cpp (Apple only): a namespace-scope extern char** environ;, the declaration
    vk_menu.cpp and vk_bug_report.cpp already use. _environ keeps its spelling, which
    tests/test_program_stamp_knobs.py looks for. libdyld exports environ on both architectures, so the strict
    -undefined error link of the Vulkan dylib resolves it.
  • host/hos_main.c: the eight guards read #if defined(_WIN32) || defined(__linux__) || defined(__APPLE__).
    Since #399 the flight readiness guard sits in hos_oot_player_seen(), which the Skip title screen also asks, so on
    macOS that row now stops its presses once the player is seen, as on Windows and Linux.
    Every call inside has a macOS provider, nothing is stubbed: the SRW locks (host/posix/windows.h over the waits PR's
    darwin_wait.c), GetAsyncKeyState, GetForegroundWindow and GetWindowThreadProcessId (win32_posix.c),
    GetCurrentProcessId, hos_flight_input, hos_free_camera_input and hos_move_stick_held (nn_hid.c),
    hos_now_ns, hos_sys_alloc, rx_option_set, and libSystem's math and pthread calls. The #else stubs stay for
    the web build.
  • tests/test_debug_tools_linux.py: it evaluates each guard for Windows, Linux and now macOS, and also checks the
    seven functions host/control.c's game table names, and hos_oot_player_seen() (18 entries in all). Before, a guard
    naming a third platform would have counted as unknown, so the test could no longer have caught one that dropped
    _WIN32 or __linux__. It reads the source as text, so it gives the same answer on every OS.
  • Design: the debug tools now compile on macOS, so two existing warnings show there under -Wall (the build passes
    -Wno-everything): -Wlogical-not-parentheses at !child == bridge_adult (intended: the adult flag compared with
    the bridge's) and an unused oot_item_kinds. Linux and Windows compile the same code today.
  • Left out: renaming the test; it keeps its file name (test_debug_tools_linux.py).
  • Commits: review 6c9edffe..752d8d7b: three commits, no dependency. 9fbf09cd is the renderer's two files; 05d42dcd
    is the debug tools and their test; 752d8d7b, new with the rebase, has the test check hos_oot_player_seen() too.
  • Rebased on main 6c9edffe (2026-11-14). One conflict, in host/hos_main.c, from #399 (Skip title screen): #399
    moved hos_oot_flight_shortcut_ready()'s guarded body into a new hos_oot_player_seen() and made the shortcut call
    it, where this PR adds __APPLE__ to that guard. Resolved by keeping #399's two functions and adding __APPLE__ to
    the guard where it now is, so the guards are still eight and all eight name __APPLE__. Because the shortcut's first
    statement is now a plain call, the test would have passed with that guard left without __APPLE__: 752d8d7b adds
    hos_oot_player_seen() to the test's list (with the guard lacking __APPLE__ in a scratch copy it fails on macOS;
    the old list passed). On macOS this also lets the Skip title screen stop at play, as it does on Windows and Linux.
    vk_programs.cpp and vk_shader.cpp rebased without conflict.

Measurements

Verdict: fixed, a game-free proof (nothing to time): main's two renderer files fail to compile for arm64 and
x86_64 and this PR's build; the debug-tools test fails on main's hos_main.c and passes here, in two interleaved runs
each; the full suite is unchanged by test name.

Commits: main 6c9edffe5d (2026-11-14); this PR mac/renderer-compile @
752d8d7b93.
Hardware: Apple M4 Max, 16 cores, 64 GiB, macOS 26.7.1; Apple clang 21.0.0 (Command Line Tools, SDK 27); Python 3.14.10.
No GPU, no game.
Scene: none. Game-free.
Method: compiles: vk_programs.cpp and vk_shader.cpp, for arm64 and for x86_64, with the renderer's flags
(nx2/build.py's renderer_flags(), written out as one command, with a fixed LONGSHOT_SHADER_STAMP for
vk_shader.cpp): main's two files on one side, this PR's on the other. A compile is deterministic, so one run per
file and architecture. (Before the rebase, on 5e072fc8, both sides took the command from the build-flags PR, #453, with
the stamp the build computes; the results were the same.) Test: tests/test_debug_tools_linux.py from this PR, run on
this PR's tree and on a copy holding main's host/hos_main.c, interleaved: PR, main, PR, main. main's own version of
the test also runs on this PR's tree. Suite: tests/run_all.py --jobs 6 on this PR, compared by test name with a main
run on the same Mac.
How to reproduce: python -I -B tests/test_debug_tools_linux.py (it reads host/hos_main.c beside it). For the
compiles, a macOS build with the build-flags PR, or nx2/build.py's renderer_flags() on its own.

Before: main @ 6c9edffe After: this PR @ 752d8d7b
vk_programs.cpp, arm64 and x86_64 error: RUSAGE_THREAD undeclared Mach-O object
vk_shader.cpp, arm64 and x86_64 2 errors: environ undeclared Mach-O object
tests/test_debug_tools_linux.py, runs 1 and 2 exit 1: 26 lines of the debug tools not compiled on macOS exit 0: ok: the 18 debug tools are compiled on Windows, Linux, macOS
full game-free suite 531 passed, 32 failed, 17 skipped 531 passed, 32 failed, 17 skipped
main @ 6c9edffe (each architecture):
gpu/vk/vk_programs.cpp:46:19: error: use of undeclared identifier 'RUSAGE_THREAD'
gpu/vk/vk_shader.cpp:1306:21: error: use of undeclared identifier 'environ'; did you mean 'env_on'?
gpu/vk/vk_shader.cpp:1306:17: error: cannot initialize a variable of type 'char **' with an lvalue of type 'bool (const char *)'

main @ 6c9edffe, tests/test_debug_tools_linux.py (each run; 26 such lines):
host/hos_main.c:575 (static int oot_pouch_change(Ctx *c, const char *name, int delta) {) is not compiled on macOS
host/hos_main.c:1123 (int hos_oot_state(int *event, int *loading, int *child) {) is not compiled on macOS
host/hos_main.c:1418 (const int64_t seen = __atomic_load_n(&flight_player_seen, __ATOMIC_RELAXED);) is not compiled on macOS

this PR @ 752d8d7b:
ok: the 18 debug tools are compiled on Windows, Linux, macOS

vk_shader.cpp is still one of the files the shader stamp hashes (nx2/translator_files.py since #370), so the stamp
changes: that is the one-time cache rebuild. (Measured before the rebase with #453's command: 0xbc2a6a5c36fef83f on
main 5e072fc8, 0xcbcf3214c5e45816 on this PR.)

Screenshots: none; nothing on screen.

Flags and settings

None new. The program life log (RX_VK_LOG_PROGRAM_LIFE=1) writes major_faults unavailable on macOS; the same line
elsewhere is unchanged.

Testing

Tested:

  • The compiles and the test, as above. main's own tests/test_debug_tools_linux.py also passes on this PR's
    hos_main.c (ok: the 10 debug tools are compiled on Windows and Linux).

  • Windows and Linux see the same text (unifdef, text only, not a build):

    • unifdef -U__APPLE__ of this PR's vk_programs.cpp and vk_shader.cpp equals main's files byte for byte;
    • host/hos_main.c with -D_WIN32 -U__linux__ -U__APPLE__ (1678 lines) and with -U_WIN32 -D__linux__ -U__APPLE__ (1920 lines) equals main's.
  • The whole suite, tests/run_all.py --jobs 6, on the same Mac:

    main @ 6c9edffe:     531 passed, 32 failed, 17 skipped in 181 s (linux, 6 at once)
    this PR @ 752d8d7b:  531 passed, 32 failed, 17 skipped in 303 s (linux, 6 at once)
    
    • By test name, against main 6c9edffe's run on the same Mac: no status changed. tests/test_debug_tools_linux.py
      passes on both: main's version checks Windows and Linux only.
    • These 32 checks fail here and on main on this Mac, by name (not triaged here: some need the macOS port's other pull
      requests, some are checks main added or changed since 5e072fc8): test_appimage_package_retry,
      test_appimage_player_build, test_collect_wide, test_control, test_cpm_discovery, test_crash_dialog,
      test_crash_record, test_env_on, test_game_layout, test_lift_cleanup_error, test_linux_preflight,
      test_longshot_ctl, test_low_memory_notice, test_make_game_cache, test_mem_gate, test_mem_gate_children,
      test_mirror_trim, test_oot_state_tap, test_pcache_header_read, test_pipeline_cache_file,
      test_pipeline_cache_save, test_pipeline_play_cache, test_pipeline_tour, test_prof_symbols,
      test_program_cache_cleanup, test_program_cache_one_variant, test_readback_late, test_report_run,
      test_split_giants, test_vk_pgo, test_vram_budget_row, test_walk_key.
    • The same 17 checks skipped as on main.
    • Crash reports during the run: none (main's run: fault-arm64-2026-11-14-180704.ips,
      recorder_sync_test.exe-2026-11-14-180744.ips).
  • History, not rerun on this branch: when these two commits were first made (05b5d88f, d26e5f88, on the macOS
    integration branch), a replay of a macOS executable link with the new hos_main.c object linked with no undefined
    symbol, where it had 7 before. Integration builds that carry them have since built both images and started the game
    on macOS (see #420). That speaks for those builds, not for this branch alone.

  • After the rebase onto main aa95d35f, at 59f750aa (752d8d7b before the rebases onto e090cc48 and aa95d35f):
    Sweep3's checks of this head (the C/C++ it changes compiled, and its own tests run, on arm64 and x86_64 where they
    apply) gave the same results as before; python -I -B tests/run_all.py on wave S1's merge 11a5b4e7, which carries
    this head: 568/22/17 (passed/failed/skipped) against main aa95d35f's 543/33/17 on this Mac, no new failure
    (reports/2026-11-15-rebase-sweep-3.md).

Not tested:

  • A Windows or Linux build, and a game start there (the shader caches' one rebuild and the life log's
    major_faults <n> there were not seen; the preprocessed text is main's).
  • A full macOS build of this branch: on main plus this PR alone, macOS has no build commands (#453) and lacks the
    other macOS host PRs.
  • The debug tools themselves on macOS (cheats, teleport, flight, free view) in a game.
  • macOS 14.4 itself, whose libdyld exports environ per the SDK's .tbd (vk_menu.cpp relies on it already).

Must be tested: None: the unifdef comparison shows Windows and Linux compile main's text byte for byte
(vk_programs.cpp and vk_shader.cpp with -U__APPLE__, and host/hos_main.c for Windows and for Linux, equal
main's), and the changed test reads the source as text, so its result does not depend on the OS it runs on. The one
change Windows and Linux see is the shader stamp (vk_shader.cpp's bytes), which only makes the first start translate
every program again. The macOS side is covered under Tested. The same comparison at the rebased head 59f750aa against
main aa95d35f gives the same result.

Risks

What could break:

  • Every platform: nothing in the compiled code off Apple: the preprocessed text is main's.
  • macOS: the life log has no per-thread fault count; a reader comparing create calls by major_faults sees
    unavailable instead.
  • Landing order: it depends on no other PR.

Turning it off: revert the three commits.

Compatibility: every platform: vk_shader.cpp is hashed into LONGSHOT_SHADER_STAMP (its file list is in
nx2/translator_files.py, which nx2/build.py compiles in), so after updating, the first start translates the shader
programs again, as with any edit to that file. Saves, the options file and the vk ABI are unchanged.

Issues

See #420.

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. (nothing to test elsewhere: Must be tested is None)
  • Rebased on current main: on aa95d35f (#761, 2026-11-15), head 59f750aa, without a new conflict; the one with
    #399 from the 6c9edffe rebase stays resolved as in Reviewer notes; this PR's own commits, old → new: 9fbf09cd →
    7ee5fd58, 05d42dcd → 82b2d660, 752d8d7b → 59f750aa; the commit names elsewhere in this description are from
    before the rebase.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named). On macOS: 531 passed, 17
    skipped, and 32 failures that also fail on main 6c9edffe on this Mac, named under Testing. After the rebase onto main
    aa95d35f (head 59f750aa): wave S1's merge 11a5b4e7, 568/22/17 against main aa95d35f's 543/33/17, no new failure.
  • 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.
  • A game-free test added for the fix, failing on main and passing here. tests/test_debug_tools_linux.py now
    checks macOS; the renderer files' proof is the compile above.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
**Type:** fix · **Risk:** low · **Tested on:** macOS 26.7.1, Apple M4 Max (game-free checks, arm64 and x86_64 compiles; no game run on this branch) · **Needs:** none ## Why A macOS build stops in three files: two in the renderer (`gpu/vk/vk_programs.cpp`, `gpu/vk/vk_shader.cpp`) do not compile, and the debug tools in `host/hos_main.c` are left out of a macOS build, so the executable does not link. This PR gives each an Apple branch, part of the macOS port (#420). Windows and Linux compile the same text as before. **Every platform rebuilds its shader caches once after this PR**, because it edits `gpu/vk/vk_shader.cpp`, which the shader stamp hashes. - **`vk_programs.cpp`:** the program life log's `thread_major_faults()` asks `getrusage(RUSAGE_THREAD)`. Darwin has no per-thread fault count at all: `getrusage` takes only `RUSAGE_SELF` and `RUSAGE_CHILDREN` (`sys/resource.h`), the per-thread `thread_info` flavours (`THREAD_BASIC_INFO`, `THREAD_EXTENDED_INFO`, which is `proc_threadinfo`) hold run times and scheduling but no faults or page-ins, and `task_events_info`, `proc_taskinfo` and `rusage_info`'s `ri_pageins` count the whole task. - **`vk_shader.cpp`:** `translator_stamp` reads `_environ`, which `host/posix/windows.h` defines as `environ`. Darwin's headers do not declare `environ` for C++ (only `crt_externs.h`'s `_NSGetEnviron`). - **`hos_main.c`:** the eight debug-tool regions (cheats, pouch and inventory, clock, teleport and age, flight, lift, free view) are guarded by `#if defined(_WIN32) || defined(__linux__)`. A macOS build compiles them out, but `host/control.c`'s game table names seven of their functions. ## How to reproduce **Seen on:** macOS 26.7.1, Apple M4 Max, Apple clang 21.0.0 (Command Line Tools, SDK 27), arm64 and x86_64 (compiles with the renderer's flags, and this PR's game-free test against `main`'s `hos_main.c`); the link error on a macOS integration build. Only macOS is affected. **Settings and switches:** defaults (the renderer's flags from `nx2/build.py`'s `renderer_flags()`). **Steps:** on a Mac, compile `main`'s `gpu/vk/vk_programs.cpp` and `gpu/vk/vk_shader.cpp` with the renderer's flags for arm64 or x86_64; and run this PR's `python -I -B tests/test_debug_tools_linux.py` beside `main`'s `host/hos_main.c`. **Expected:** two Mach-O objects, and every debug tool compiled on macOS as on Windows and Linux. **Actual:** at `main` @ `6c9edffe`, on each architecture: ``` gpu/vk/vk_programs.cpp:46:19: error: use of undeclared identifier 'RUSAGE_THREAD' gpu/vk/vk_shader.cpp:1306:21: error: use of undeclared identifier 'environ'; did you mean 'env_on'? ld: Undefined symbols: _hos_oot_current_map, _hos_oot_destination, _hos_oot_teleport_ask, _hos_oot_teleport_result, _hos_oot_teleport_cancel, _hos_oot_age_ask, _hos_oot_state (named by host/control.c's game table) ``` The test exits 1 with 26 lines of the debug tools not compiled on macOS. (The `ld` line is from the macOS integration branch's link, once the two compile errors were fixed.) ## What changed Each of the three files gets an Apple branch: the life log says `major_faults unavailable` on macOS, `vk_shader.cpp` declares `environ`, and the debug tools' eight guards name `__APPLE__` too. Windows and Linux preprocess to `main`'s text; the test now checks the guards for macOS as well. - Read first: the eight guards in `host/hos_main.c` and the Apple branches of `vk_programs.cpp` and `vk_shader.cpp`. - **`gpu/vk/vk_programs.cpp`** (Apple only): `thread_major_faults()` and its start value are not compiled on Darwin, with a comment giving the reason above. The life log's create line ends `major_faults unavailable` there instead of `major_faults <n>`. It is one token, so a parser that splits on spaces still finds the key and no number. Neither the task's page-in count (other threads' disk waits booked to this create call) nor a 0 (which reads as "no faults") is logged in its place. - **`gpu/vk/vk_shader.cpp`** (Apple only): a namespace-scope `extern char** environ;`, the declaration `vk_menu.cpp` and `vk_bug_report.cpp` already use. `_environ` keeps its spelling, which `tests/test_program_stamp_knobs.py` looks for. libdyld exports `environ` on both architectures, so the strict `-undefined error` link of the Vulkan dylib resolves it. - **`host/hos_main.c`:** the eight guards read `#if defined(_WIN32) || defined(__linux__) || defined(__APPLE__)`. Since #399 the flight readiness guard sits in `hos_oot_player_seen()`, which the Skip title screen also asks, so on macOS that row now stops its presses once the player is seen, as on Windows and Linux. Every call inside has a macOS provider, nothing is stubbed: the SRW locks (`host/posix/windows.h` over the waits PR's `darwin_wait.c`), `GetAsyncKeyState`, `GetForegroundWindow` and `GetWindowThreadProcessId` (`win32_posix.c`), `GetCurrentProcessId`, `hos_flight_input`, `hos_free_camera_input` and `hos_move_stick_held` (`nn_hid.c`), `hos_now_ns`, `hos_sys_alloc`, `rx_option_set`, and libSystem's math and pthread calls. The `#else` stubs stay for the web build. - **`tests/test_debug_tools_linux.py`:** it evaluates each guard for Windows, Linux and now macOS, and also checks the seven functions `host/control.c`'s game table names, and `hos_oot_player_seen()` (18 entries in all). Before, a guard naming a third platform would have counted as unknown, so the test could no longer have caught one that dropped `_WIN32` or `__linux__`. It reads the source as text, so it gives the same answer on every OS. - Design: the debug tools now compile on macOS, so two existing warnings show there under `-Wall` (the build passes `-Wno-everything`): `-Wlogical-not-parentheses` at `!child == bridge_adult` (intended: the adult flag compared with the bridge's) and an unused `oot_item_kinds`. Linux and Windows compile the same code today. - Left out: renaming the test; it keeps its file name (`test_debug_tools_linux.py`). - Commits: review `6c9edffe..752d8d7b`: three commits, no dependency. `9fbf09cd` is the renderer's two files; `05d42dcd` is the debug tools and their test; `752d8d7b`, new with the rebase, has the test check `hos_oot_player_seen()` too. - **Rebased on `main` 6c9edffe (2026-11-14).** One conflict, in `host/hos_main.c`, from #399 (Skip title screen): #399 moved `hos_oot_flight_shortcut_ready()`'s guarded body into a new `hos_oot_player_seen()` and made the shortcut call it, where this PR adds `__APPLE__` to that guard. Resolved by keeping #399's two functions and adding `__APPLE__` to the guard where it now is, so the guards are still eight and all eight name `__APPLE__`. Because the shortcut's first statement is now a plain call, the test would have passed with that guard left without `__APPLE__`: `752d8d7b` adds `hos_oot_player_seen()` to the test's list (with the guard lacking `__APPLE__` in a scratch copy it fails on macOS; the old list passed). On macOS this also lets the Skip title screen stop at play, as it does on Windows and Linux. `vk_programs.cpp` and `vk_shader.cpp` rebased without conflict. ## Measurements **Verdict:** fixed, a game-free proof (nothing to time): `main`'s two renderer files fail to compile for arm64 and x86_64 and this PR's build; the debug-tools test fails on `main`'s `hos_main.c` and passes here, in two interleaved runs each; the full suite is unchanged by test name. Commits: main 6c9edffe5da1f5b5383977aeab3f544c0de25d4c (2026-11-14); this PR `mac/renderer-compile` @ 752d8d7b930866fb8631a3f4c97f112eee2919bd. Hardware: Apple M4 Max, 16 cores, 64 GiB, macOS 26.7.1; Apple clang 21.0.0 (Command Line Tools, SDK 27); Python 3.14.10. No GPU, no game. Scene: none. Game-free. Method: compiles: `vk_programs.cpp` and `vk_shader.cpp`, for arm64 and for x86_64, with the renderer's flags (`nx2/build.py`'s `renderer_flags()`, written out as one command, with a fixed `LONGSHOT_SHADER_STAMP` for `vk_shader.cpp`): `main`'s two files on one side, this PR's on the other. A compile is deterministic, so one run per file and architecture. (Before the rebase, on 5e072fc8, both sides took the command from the build-flags PR, #453, with the stamp the build computes; the results were the same.) Test: `tests/test_debug_tools_linux.py` from this PR, run on this PR's tree and on a copy holding `main`'s `host/hos_main.c`, interleaved: PR, main, PR, main. `main`'s own version of the test also runs on this PR's tree. Suite: `tests/run_all.py --jobs 6` on this PR, compared by test name with a `main` run on the same Mac. How to reproduce: `python -I -B tests/test_debug_tools_linux.py` (it reads `host/hos_main.c` beside it). For the compiles, a macOS build with the build-flags PR, or `nx2/build.py`'s `renderer_flags()` on its own. | | Before: main @ 6c9edffe | After: this PR @ 752d8d7b | |---|---|---| | `vk_programs.cpp`, arm64 and x86_64 | error: `RUSAGE_THREAD` undeclared | Mach-O object | | `vk_shader.cpp`, arm64 and x86_64 | 2 errors: `environ` undeclared | Mach-O object | | `tests/test_debug_tools_linux.py`, runs 1 and 2 | exit 1: 26 lines of the debug tools not compiled on macOS | exit 0: `ok: the 18 debug tools are compiled on Windows, Linux, macOS` | | full game-free suite | 531 passed, 32 failed, 17 skipped | 531 passed, 32 failed, 17 skipped | ``` main @ 6c9edffe (each architecture): gpu/vk/vk_programs.cpp:46:19: error: use of undeclared identifier 'RUSAGE_THREAD' gpu/vk/vk_shader.cpp:1306:21: error: use of undeclared identifier 'environ'; did you mean 'env_on'? gpu/vk/vk_shader.cpp:1306:17: error: cannot initialize a variable of type 'char **' with an lvalue of type 'bool (const char *)' main @ 6c9edffe, tests/test_debug_tools_linux.py (each run; 26 such lines): host/hos_main.c:575 (static int oot_pouch_change(Ctx *c, const char *name, int delta) {) is not compiled on macOS host/hos_main.c:1123 (int hos_oot_state(int *event, int *loading, int *child) {) is not compiled on macOS host/hos_main.c:1418 (const int64_t seen = __atomic_load_n(&flight_player_seen, __ATOMIC_RELAXED);) is not compiled on macOS this PR @ 752d8d7b: ok: the 18 debug tools are compiled on Windows, Linux, macOS ``` `vk_shader.cpp` is still one of the files the shader stamp hashes (`nx2/translator_files.py` since #370), so the stamp changes: that is the one-time cache rebuild. (Measured before the rebase with #453's command: `0xbc2a6a5c36fef83f` on main 5e072fc8, `0xcbcf3214c5e45816` on this PR.) Screenshots: none; nothing on screen. ### Flags and settings None new. The program life log (`RX_VK_LOG_PROGRAM_LIFE=1`) writes `major_faults unavailable` on macOS; the same line elsewhere is unchanged. ## Testing **Tested:** - The compiles and the test, as above. `main`'s own `tests/test_debug_tools_linux.py` also passes on this PR's `hos_main.c` (`ok: the 10 debug tools are compiled on Windows and Linux`). - **Windows and Linux see the same text** (`unifdef`, text only, not a build): - `unifdef -U__APPLE__` of this PR's `vk_programs.cpp` and `vk_shader.cpp` equals `main`'s files byte for byte; - `host/hos_main.c` with `-D_WIN32 -U__linux__ -U__APPLE__` (1678 lines) and with `-U_WIN32 -D__linux__ -U__APPLE__` (1920 lines) equals `main`'s. - **The whole suite**, `tests/run_all.py --jobs 6`, on the same Mac: ``` main @ 6c9edffe: 531 passed, 32 failed, 17 skipped in 181 s (linux, 6 at once) this PR @ 752d8d7b: 531 passed, 32 failed, 17 skipped in 303 s (linux, 6 at once) ``` - By test name, against main 6c9edffe's run on the same Mac: no status changed. `tests/test_debug_tools_linux.py` passes on both: `main`'s version checks Windows and Linux only. - These 32 checks fail here and on main on this Mac, by name (not triaged here: some need the macOS port's other pull requests, some are checks main added or changed since 5e072fc8): `test_appimage_package_retry`, `test_appimage_player_build`, `test_collect_wide`, `test_control`, `test_cpm_discovery`, `test_crash_dialog`, `test_crash_record`, `test_env_on`, `test_game_layout`, `test_lift_cleanup_error`, `test_linux_preflight`, `test_longshot_ctl`, `test_low_memory_notice`, `test_make_game_cache`, `test_mem_gate`, `test_mem_gate_children`, `test_mirror_trim`, `test_oot_state_tap`, `test_pcache_header_read`, `test_pipeline_cache_file`, `test_pipeline_cache_save`, `test_pipeline_play_cache`, `test_pipeline_tour`, `test_prof_symbols`, `test_program_cache_cleanup`, `test_program_cache_one_variant`, `test_readback_late`, `test_report_run`, `test_split_giants`, `test_vk_pgo`, `test_vram_budget_row`, `test_walk_key`. - The same 17 checks skipped as on main. - Crash reports during the run: none (main's run: fault-arm64-2026-11-14-180704.ips, recorder_sync_test.exe-2026-11-14-180744.ips). - **History, not rerun on this branch:** when these two commits were first made (`05b5d88f`, `d26e5f88`, on the macOS integration branch), a replay of a macOS executable link with the new `hos_main.c` object linked with no undefined symbol, where it had 7 before. Integration builds that carry them have since built both images and started the game on macOS (see #420). That speaks for those builds, not for this branch alone. - **After the rebase onto main aa95d35f**, at `59f750aa` (`752d8d7b` before the rebases onto e090cc48 and aa95d35f): Sweep3's checks of this head (the C/C++ it changes compiled, and its own tests run, on arm64 and x86_64 where they apply) gave the same results as before; `python -I -B tests/run_all.py` on wave S1's merge `11a5b4e7`, which carries this head: 568/22/17 (passed/failed/skipped) against main aa95d35f's 543/33/17 on this Mac, no new failure (`reports/2026-11-15-rebase-sweep-3.md`). **Not tested:** - A Windows or Linux build, and a game start there (the shader caches' one rebuild and the life log's `major_faults <n>` there were not seen; the preprocessed text is `main`'s). - A full macOS build of this branch: on `main` plus this PR alone, macOS has no build commands (#453) and lacks the other macOS host PRs. - The debug tools themselves on macOS (cheats, teleport, flight, free view) in a game. - macOS 14.4 itself, whose libdyld exports `environ` per the SDK's `.tbd` (`vk_menu.cpp` relies on it already). **Must be tested:** None: the unifdef comparison shows Windows and Linux compile `main`'s text byte for byte (`vk_programs.cpp` and `vk_shader.cpp` with `-U__APPLE__`, and `host/hos_main.c` for Windows and for Linux, equal `main`'s), and the changed test reads the source as text, so its result does not depend on the OS it runs on. The one change Windows and Linux see is the shader stamp (`vk_shader.cpp`'s bytes), which only makes the first start translate every program again. The macOS side is covered under Tested. The same comparison at the rebased head `59f750aa` against main aa95d35f gives the same result. ## Risks **What could break:** - **Every platform:** nothing in the compiled code off Apple: the preprocessed text is `main`'s. - **macOS:** the life log has no per-thread fault count; a reader comparing create calls by `major_faults` sees `unavailable` instead. - Landing order: it depends on no other PR. **Turning it off:** revert the three commits. **Compatibility:** **every platform:** `vk_shader.cpp` is hashed into `LONGSHOT_SHADER_STAMP` (its file list is in `nx2/translator_files.py`, which `nx2/build.py` compiles in), so after updating, the first start translates the shader programs again, as with any edit to that file. Saves, the options file and the vk ABI are unchanged. ## Issues See #420. ## 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. (nothing to test elsewhere: Must be tested is None) - [x] Rebased on current `main`: on aa95d35f (#761, 2026-11-15), head `59f750aa`, without a new conflict; the one with #399 from the 6c9edffe rebase stays resolved as in Reviewer notes; this PR's own commits, old → new: `9fbf09cd` → `7ee5fd58`, `05d42dcd` → `82b2d660`, `752d8d7b` → `59f750aa`; the commit names elsewhere in this description are from before the rebase. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). On macOS: 531 passed, 17 skipped, and 32 failures that also fail on main 6c9edffe on this Mac, named under Testing. After the rebase onto main aa95d35f (head `59f750aa`): wave S1's merge `11a5b4e7`, 568/22/17 against main aa95d35f's 543/33/17, no new failure. - [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] A game-free test added for the fix, failing on `main` and passing here. `tests/test_debug_tools_linux.py` now checks macOS; the renderer files' proof is the compile above. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened.
vk_programs.cpp: the life log's thread_major_faults() asked getrusage for
RUSAGE_THREAD, which Darwin lacks. Darwin keeps no count of one thread's
major faults: getrusage takes RUSAGE_SELF and RUSAGE_CHILDREN only, and the
per-thread thread_info flavours (THREAD_BASIC_INFO, THREAD_EXTENDED_INFO,
which is proc_threadinfo) hold run times and scheduling, no faults or
page-ins; task_events_info, proc_taskinfo and rusage_info count the whole
task. Rather than log another thread's faults or a 0 as this create call's,
the create line there ends "major_faults unavailable".

vk_shader.cpp: translator_stamp's _environ is environ, which Darwin's
headers do not declare for C++; it gets the namespace-scope declaration
vk_menu.cpp and vk_bug_report.cpp already use (libdyld exports it).

Both are Apple-only branches: with __APPLE__ undefined the files are
byte-identical to before (unifdef -U__APPLE__).

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
fix(macos): the debug tools are compiled on Darwin too
All checks were successful
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
CI / Conventional Commit title (pull_request) Successful in 4s
PR description / Description follows the template (pull_request_target) Successful in 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 7s
Third-party parts / As their notes say (pull_request) Successful in 8s
Website / Website on Cloudflare (pull_request_target) Has been skipped
bf85ed4ae0
host/hos_main.c's eight debug-tool guards (cheats, pouch and inventory,
clock, teleport and age, flight, lift, free view) named only _WIN32 and
__linux__, so a Darwin build compiled them out, and its executable did not
link: host/control.c's game table names hos_oot_current_map,
hos_oot_destination, hos_oot_teleport_ask, hos_oot_teleport_result,
hos_oot_teleport_cancel, hos_oot_age_ask and hos_oot_state.

Every call in those regions has a Darwin provider, nothing stubbed: the SRW
locks (windows.h's Darwin branch over darwin_wait.c), GetAsyncKeyState,
GetForegroundWindow and GetWindowThreadProcessId (win32_posix.c),
GetCurrentProcessId, hos_flight_input, hos_free_camera_input and
hos_move_stick_held (nn_hid.c), hos_now_ns, hos_sys_alloc, rx_option_set,
and libSystem's math and pthread calls.

tests/test_debug_tools_linux.py now evaluates the conditions for macOS as
well and checks the seven functions the game table names; with the old
guards it fails on macOS. Windows and Linux preprocess to the same text as
before (unifdef per platform).

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
mooki force-pushed mac/renderer-compile from bf85ed4ae0
All checks were successful
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
CI / Conventional Commit title (pull_request) Successful in 4s
PR description / Description follows the template (pull_request_target) Successful in 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 7s
Third-party parts / As their notes say (pull_request) Successful in 8s
Website / Website on Cloudflare (pull_request_target) Has been skipped
to 752d8d7b93
All checks were successful
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) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 5s
Third-party parts / As their notes say (pull_request) Successful in 8s
PR description / Description follows the template (pull_request_target) Successful in 4s
2026-11-15 01:52:22 +00:00
Compare
mooki force-pushed mac/renderer-compile from 752d8d7b93
All checks were successful
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) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 5s
Third-party parts / As their notes say (pull_request) Successful in 8s
PR description / Description follows the template (pull_request_target) Successful in 4s
to 67ede2434b
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) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 4s
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 5s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 5s
Third-party parts / As their notes say (pull_request) Successful in 9s
2026-11-15 07:14:19 +00:00
Compare
mooki force-pushed mac/renderer-compile from 67ede2434b
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) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 4s
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 5s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 5s
Third-party parts / As their notes say (pull_request) Successful in 9s
to 59f750aa38
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) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 4s
CI / Workflow lint (actionlint) (pull_request) Successful in 9s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 7s
Third-party parts / As their notes say (pull_request) Successful in 11s
PR description / Description follows the template (pull_request_target) Successful in 5s
2026-11-15 13:06:00 +00:00
Compare
mooki changed title from WIP: fix(macos): build vk_programs, vk_shader and the debug tools on Darwin to fix(macos): build vk_programs, vk_shader and the debug tools on Darwin 2026-11-15 13:13:25 +00:00
Author
Member

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

Folded into #845 (feat(macos): run the host on macOS: build, runtime, control, crash records and the Vulkan loader)
mooki closed this pull request 2026-11-15 18:07:33 +00:00
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) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 4s
CI / Workflow lint (actionlint) (pull_request) Successful in 9s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 7s
Third-party parts / As their notes say (pull_request) Successful in 11s
PR description / Description follows the template (pull_request_target) Successful in 5s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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!492
No description provided.