From afc4e5eac730ef89fbb68460be5af87ca05cde35 Mon Sep 17 00:00:00 2001 From: Alex Vanderveen Date: Mon, 3 Aug 2026 07:20:26 -0400 Subject: [PATCH] Require cmake-clang-v1 1.0.4 for Linux IPO linking. Floor ensure-toolchain at 1.0.4 (libxml2 + clang.cfg -fuse-ld=lld) and prepend pack lib/ to LD_LIBRARY_PATH when activating the toolchain. Co-authored-by: Cursor --- docs/LOCAL_CODEGEN_SDK.md | 4 ++-- host/psxrecomp_codegen_host.c | 28 ++++++++++++++++++++-------- tools/toolchain_pack.py | 17 ++++++++++++----- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/docs/LOCAL_CODEGEN_SDK.md b/docs/LOCAL_CODEGEN_SDK.md index 16688adc..18101922 100644 --- a/docs/LOCAL_CODEGEN_SDK.md +++ b/docs/LOCAL_CODEGEN_SDK.md @@ -41,8 +41,8 @@ with host-native `curl` + `tar`/`unzip` when possible — so Microsoft Store Python AppData redirection cannot hide cmake. Offline zips unpack to the same path. A legacy `%LOCALAPPDATA%/psxrecomp/…` cache is migrated automatically. Override with `RETCOMM_TOOLCHAIN_DIR`. Require a floor version via -`RETCOMM_TOOLCHAIN_MIN_VERSION` / `ensure-toolchain --min-version` (Windows -defaults to `1.0.3` for bundled zlib). Generate/rebuild still need Python 3 +`RETCOMM_TOOLCHAIN_MIN_VERSION` / `ensure-toolchain --min-version` (defaults to +`1.0.4` for Linux LTO deps + Windows zlib). Generate/rebuild still need Python 3 for `psxrecomp_cli.py`. ## Commands diff --git a/host/psxrecomp_codegen_host.c b/host/psxrecomp_codegen_host.c index ddb67e96..8a4933ba 100644 --- a/host/psxrecomp_codegen_host.c +++ b/host/psxrecomp_codegen_host.c @@ -588,6 +588,23 @@ static void activate_toolchain_path(void) { if (pref[0]) setenv("CMAKE_PREFIX_PATH", pref, 1); } + /* Linux packs 1.0.4+: bundled libxml2.so.2 for lld / thin LTO. */ + { + char libdir[1500]; + if (join_path(libdir, sizeof(libdir), pack_root, "lib") && + path_is_dir(libdir)) { + const char* prev = getenv("LD_LIBRARY_PATH"); + char llp[8192]; + if (prev && prev[0] && !strstr(prev, libdir)) + snprintf(llp, sizeof(llp), "%s:%s", libdir, prev); + else if (!prev || !prev[0]) + snprintf(llp, sizeof(llp), "%s", libdir); + else + llp[0] = '\0'; + if (llp[0]) + setenv("LD_LIBRARY_PATH", llp, 1); + } + } #endif } } @@ -969,8 +986,9 @@ static int run_cli_posix(char* const argv[], /* ---- Host-native toolchain install (no Store Python AppData redirect) ---- */ static const char* k_tc_repo = "TechnicallyComputers/retcomm-toolchains"; -/* Default floor for Windows zlib-in-pack; override with RETCOMM_TOOLCHAIN_MIN_VERSION. */ -static const char* k_tc_min_version_default = "1.0.3"; +/* Floor: Linux 1.0.4+ ships libxml2 + clang.cfg (-fuse-ld=lld) for IPO; + * Windows 1.0.3+ ships static zlib. Override with RETCOMM_TOOLCHAIN_MIN_VERSION. */ +static const char* k_tc_min_version_default = "1.0.4"; static const char* toolchain_zip_asset_name(void) { #if defined(_WIN32) @@ -986,13 +1004,7 @@ static const char* toolchain_min_version(void) { const char* env = getenv("RETCOMM_TOOLCHAIN_MIN_VERSION"); if (env && env[0]) return env; -#if defined(_WIN32) - /* Windows packs from 1.0.3 ship static zlib for find_package(ZLIB). */ return k_tc_min_version_default; -#else - (void)k_tc_min_version_default; - return ""; -#endif } /* Parse leading dotted integers from a version / tag (optional leading 'v'). */ diff --git a/tools/toolchain_pack.py b/tools/toolchain_pack.py index 3dcd457d..63ad1db8 100644 --- a/tools/toolchain_pack.py +++ b/tools/toolchain_pack.py @@ -184,10 +184,9 @@ def default_min_version() -> str: env = (os.environ.get("RETCOMM_TOOLCHAIN_MIN_VERSION") or "").strip() if env: return env - # Windows packs from 1.0.3 ship static zlib for find_package(ZLIB). - if sys_platform_is_windows(): - return "1.0.3" - return "" + # 1.0.4+: Linux libxml2 + clang.cfg (-fuse-ld=lld) for IPO; Windows zlib + # since 1.0.3. Keep one floor so ensure-toolchain refreshes stale caches. + return "1.0.4" def pack_satisfies_min(root: Path, min_version: str = "") -> bool: @@ -340,6 +339,15 @@ def activate_toolchain_bin(bin_dir: Path, log=None) -> None: os.environ["CMAKE_PREFIX_PATH"] = pack_s elif pack_s not in prev_prefix.split(os.pathsep): os.environ["CMAKE_PREFIX_PATH"] = pack_s + os.pathsep + prev_prefix + lib_dir = pack_root / "lib" + if lib_dir.is_dir() and not sys_platform_is_windows(): + lib_s = str(lib_dir) + prev_llp = os.environ.get("LD_LIBRARY_PATH", "") + parts = prev_llp.split(os.pathsep) if prev_llp else [] + if lib_s not in parts: + os.environ["LD_LIBRARY_PATH"] = lib_s + ( + os.pathsep + prev_llp if prev_llp else "" + ) for name, env_key in ( ("clang", "CC"), ("clang++", "CXX"), @@ -352,7 +360,6 @@ def activate_toolchain_bin(bin_dir: Path, log=None) -> None: if log: log(f"Using toolchain: {bin_dir}") - def unpack_zip_to(zip_path: Path, dest: Path) -> Path: """Extract *zip_path* into *dest* (replaced) and return usable pack root.""" if dest.exists():