From c3ad85ffc54a80379e5f1c0cb03d7b0f80574963 Mon Sep 17 00:00:00 2001 From: Shokunin <30949000+tetrisgm@users.noreply.github.com> Date: Fri, 25 Sep 2026 20:11:22 -0700 Subject: [PATCH 1/2] Accept the macOS toolchain pack and check Apple's CLT separately The setup host's toolchain health check requires /bin/clang and ld.lld and links with -fuse-ld=lld. The macOS pack (cmake-clang-v1-macos-universal) ships CMake, Ninja, ccache and Python only and relies on the system compiler, so on every Mac the check failed: the wizard deleted latest/, renamed the version folder to .broken, a fresh download ended in "Extracted toolchain but cmake is missing or will not run", and page 0 could never be passed, with or without Xcode installed. On macOS a pack without clang is now the expected layout. Readiness separately checks Apple's Command Line Tools (xcode-select -p, then a tiny /usr/bin/clang compile+link). When they are missing, the wizard shows a repair note telling the player to run xcode-select --install, and the downloaded pack is left in place. Windows and Linux are unchanged. No emulation or runtime behaviour changes. Co-Authored-By: Claude Opus 5.5 --- host/psxrecomp_codegen_host.c | 57 +++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/host/psxrecomp_codegen_host.c b/host/psxrecomp_codegen_host.c index a58ac230..f7111618 100644 --- a/host/psxrecomp_codegen_host.c +++ b/host/psxrecomp_codegen_host.c @@ -3059,8 +3059,17 @@ static int toolchain_bin_compiler_works(const char* bin) { return 0; } #else - if (!join_path(clang, sizeof(clang), bin, "clang") || !path_is_file(clang)) + if (!join_path(clang, sizeof(clang), bin, "clang") || !path_is_file(clang)) { +# if defined(__APPLE__) + /* The macOS pack (cmake-clang-v1-macos-universal) ships CMake, Ninja, + * ccache and Python only; compiling uses the system toolchain from + * Apple's Command Line Tools, checked by macos_system_compiler_works. + * A pack without clang is the normal macOS layout, not a broken one. */ + return 1; +# else return 0; +# endif + } if (!join_path(lld, sizeof(lld), bin, "ld.lld") || !path_is_file(lld)) return 0; #endif @@ -3114,6 +3123,50 @@ static int toolchain_bin_compiler_works(const char* bin) { return ok; } +#if defined(__APPLE__) +/* True when Apple's Command Line Tools are installed and /usr/bin/clang can + * compile and link a tiny program. xcode-select runs first so a machine + * without the CLT gets a repair note instead of the xcrun install prompt on + * every wizard refresh. */ +static int macos_system_compiler_works(void) { + char src[256], exe[256], cmd[1024]; + FILE* f; + int ok; + if (!run_cmd_exit_zero("xcode-select -p >/dev/null 2>&1")) + return 0; + snprintf(src, sizeof(src), "/tmp/psxrecomp-cc-probe-%d.c", (int)getpid()); + snprintf(exe, sizeof(exe), "/tmp/psxrecomp-cc-probe-%d", (int)getpid()); + f = fopen(src, "wb"); + if (!f) + return 0; + fputs("int main(void){return 0;}\n", f); + fclose(f); + snprintf(cmd, sizeof(cmd), "/usr/bin/clang \"%s\" -o \"%s\" >/dev/null 2>&1", + src, exe); + ok = run_cmd_exit_zero(cmd); + unlink(src); + unlink(exe); + return ok; +} +#endif + +/* Pack health says nothing about the macOS system compiler (see above), so + * readiness checks it separately and explains how to fix it. The pack itself + * is left alone: a missing compiler must never delete a good download. */ +static int host_system_compiler_ready(void) { +#if defined(__APPLE__) + if (macos_system_compiler_works()) + return 1; + snprintf(g_tc_repair_note, sizeof(g_tc_repair_note), + "Apple's Command Line Tools are required to build the game. " + "Open Terminal, run: xcode-select --install then reopen this " + "app."); + return 0; +#else + return 1; +#endif +} + static int toolchain_bin_is_healthy(const char* bin) { char cmake[1200]; if (!bin || !bin[0]) @@ -3298,7 +3351,7 @@ static int host_toolchain_is_ready(void) { for (attempt = 0; attempt < 3; ++attempt) { activate_toolchain_path(); if (host_portable_cmake_ready()) - return 1; + return host_system_compiler_ready(); if (!g_toolchain_bin[0]) break; discard_unhealthy_active_toolchain(); From 87453755604e0d9291e5600c83cdccafd58067ad Mon Sep 17 00:00:00 2001 From: Shokunin <30949000+tetrisgm@users.noreply.github.com> Date: Fri, 25 Sep 2026 20:25:36 -0700 Subject: [PATCH 2/2] Report build-tools readiness in --setup-selfcheck Adds toolchain_ready and toolchain_note to the selfcheck JSON: the same pack + system-compiler judgement as wizard page 0, without the cache healing, so scripts and maintainers can check a machine headlessly (the macOS Command Line Tools case above had no headless signal at all). Co-Authored-By: Claude Opus 5.5 --- host/psxrecomp_codegen_host.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/host/psxrecomp_codegen_host.c b/host/psxrecomp_codegen_host.c index f7111618..b616dd9c 100644 --- a/host/psxrecomp_codegen_host.c +++ b/host/psxrecomp_codegen_host.c @@ -4441,6 +4441,18 @@ static void host_selfcheck_or_return(const PsxrecompCodegenHostConfig* cfg, } printf(",\n \"overlay_cache_configured\": %s", overlay_cache ? "true" : "false"); } + /* Build-tools readiness as wizard page 0 judges it, minus its cache + * healing: nothing is deleted or renamed here. toolchain_note carries the + * repair hint the wizard would show (e.g. missing Command Line Tools). */ + { + int tc_ready; + g_tc_repair_note[0] = '\0'; + activate_toolchain_path(); + tc_ready = host_portable_cmake_ready() && host_system_compiler_ready(); + printf(",\n \"toolchain_ready\": %s", tc_ready ? "true" : "false"); + printf(",\n \"toolchain_note\": "); + host_json_str(g_tc_repair_note); + } printf("\n}\n"); fflush(stdout); exit(missing ? 2 : 0);