From 483e06cefdd389c2350d574f8f7c81e780b713f8 Mon Sep 17 00:00:00 2001 From: omegakatana92 Date: Tue, 1 Sep 2026 13:01:23 -0500 Subject: [PATCH 1/2] Fix Windows lld-link CMake options --- CMakeLists.txt | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b61915b..3d835b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,17 @@ function(gbarecomp_target_link_host_stack target_name scope) if(MSVC) target_link_options(${target_name} ${scope} "/STACK:${GBARECOMP_HOST_STACK_RESERVE_BYTES}") + elseif(CMAKE_EXECUTABLE_SUFFIX STREQUAL ".exe" AND + (CMAKE_C_COMPILER_ID MATCHES "Clang" OR + CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + # Clang on Windows with lld-link: lld-link does not understand GNU + # --stack; use the Windows /STACK: form. The Clang driver only + # forwards to lld-link when the flag is prefixed with -Xlinker, so + # route through the LINKER: prefix (which CMake expands to + # "-Xlinker /STACK:"). (MSVC and GNU ld keep their existing + # branches below.) + target_link_options(${target_name} ${scope} + "LINKER:/STACK:${GBARECOMP_HOST_STACK_RESERVE_BYTES}") elseif(CMAKE_EXECUTABLE_SUFFIX STREQUAL ".exe" AND (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")) @@ -481,7 +492,16 @@ function(target_link_gbarecomp_runtime_stack target_name) # # Apple's ld64 and MSVC resolve archive cycles without help (and ld64 rejects # --start-group outright), so they take the plain list. - if(APPLE OR MSVC) + # Apple's ld64, MSVC link.exe, and Clang on Windows (lld-link) all resolve + # archive cycles without help. ld64 and lld-link also reject --start-group + # outright, so they take the plain list. MinGW GNU ld and Linux GNU ld need + # the explicit group. + set(_is_windows_clang FALSE) + if(WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR + CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) + set(_is_windows_clang TRUE) + endif() + if(APPLE OR MSVC OR _is_windows_clang) target_link_libraries(${target_name} PRIVATE gbarecomp_armv4t gbarecomp_gba gbarecomp_runtime gbarecomp_debug) else() @@ -805,11 +825,7 @@ add_test(NAME irq_tests COMMAND irq_tests) add_executable(ppu_smoke_tests tests/ppu_smoke/test_main.cpp) target_include_directories(ppu_smoke_tests PRIVATE src/runtime src/debug) target_link_libraries(ppu_smoke_tests PRIVATE gbarecomp_gba) -if(MSVC) - target_link_options(ppu_smoke_tests PRIVATE /STACK:16777216) -elseif(MINGW OR WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") - target_link_options(ppu_smoke_tests PRIVATE -Wl,--stack,16777216) -endif() +gbarecomp_target_link_host_stack(ppu_smoke_tests PRIVATE) add_test(NAME ppu_smoke_tests COMMAND ppu_smoke_tests) add_executable(save_config_tests From ed85f5a0dfd1c8a40799c56c380d76b5aa7ea837 Mon Sep 17 00:00:00 2001 From: Matthew Stanley <1379tech@gmail.com> Date: Thu, 3 Sep 2026 17:19:39 -0700 Subject: [PATCH 2/2] Fix Windows Clang linker detection --- CMakeLists.txt | 46 +++++++++++++++++++++++------------------- cmake/runtime.cmake.in | 20 +++++++++++++++++- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d835b4..c0eb664 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,19 +297,29 @@ set_property(TARGET gbarecomp_heal_gate PROPERTY POSITION_INDEPENDENT_CODE ON) set(GBARECOMP_HOST_STACK_RESERVE_BYTES "16777216" CACHE STRING "Host stack reserve for Windows game executables that link gbarecomp_runtime") +function(gbarecomp_compiler_uses_msvc_linker out_var) + if(MSVC OR + CMAKE_C_SIMULATE_ID STREQUAL "MSVC" OR + CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC" OR + CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" OR + CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + set(${out_var} TRUE PARENT_SCOPE) + else() + set(${out_var} FALSE PARENT_SCOPE) + endif() +endfunction() + function(gbarecomp_target_link_host_stack target_name scope) - if(MSVC) + gbarecomp_compiler_uses_msvc_linker(_gbarecomp_msvc_linker) + if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" OR + CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") target_link_options(${target_name} ${scope} "/STACK:${GBARECOMP_HOST_STACK_RESERVE_BYTES}") elseif(CMAKE_EXECUTABLE_SUFFIX STREQUAL ".exe" AND - (CMAKE_C_COMPILER_ID MATCHES "Clang" OR - CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - # Clang on Windows with lld-link: lld-link does not understand GNU - # --stack; use the Windows /STACK: form. The Clang driver only - # forwards to lld-link when the flag is prefixed with -Xlinker, so - # route through the LINKER: prefix (which CMake expands to - # "-Xlinker /STACK:"). (MSVC and GNU ld keep their existing - # branches below.) + _gbarecomp_msvc_linker) + # MSVC-style Clang/lld-link does not understand GNU --stack. Route + # through CMake's linker wrapper so the compiler driver forwards the + # Windows /STACK form to the linker. target_link_options(${target_name} ${scope} "LINKER:/STACK:${GBARECOMP_HOST_STACK_RESERVE_BYTES}") elseif(CMAKE_EXECUTABLE_SUFFIX STREQUAL ".exe" AND @@ -490,18 +500,12 @@ function(target_link_gbarecomp_runtime_stack target_name) # runtime_arm.cpp: undefined reference to `overlay_try_dispatch' # runtime_arm.cpp: undefined reference to `kBiosDispatchTable' # - # Apple's ld64 and MSVC resolve archive cycles without help (and ld64 rejects - # --start-group outright), so they take the plain list. - # Apple's ld64, MSVC link.exe, and Clang on Windows (lld-link) all resolve - # archive cycles without help. ld64 and lld-link also reject --start-group - # outright, so they take the plain list. MinGW GNU ld and Linux GNU ld need - # the explicit group. - set(_is_windows_clang FALSE) - if(WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR - CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) - set(_is_windows_clang TRUE) - endif() - if(APPLE OR MSVC OR _is_windows_clang) + # Apple's ld64 and MSVC-style linkers resolve archive cycles without help. + # ld64 and lld-link reject --start-group outright, so they take the plain + # list. GNU-style linkers, including MinGW Clang's GNU frontend, need the + # explicit group. + gbarecomp_compiler_uses_msvc_linker(_gbarecomp_msvc_linker) + if(APPLE OR _gbarecomp_msvc_linker) target_link_libraries(${target_name} PRIVATE gbarecomp_armv4t gbarecomp_gba gbarecomp_runtime gbarecomp_debug) else() diff --git a/cmake/runtime.cmake.in b/cmake/runtime.cmake.in index 59fd369..ebcde9d 100644 --- a/cmake/runtime.cmake.in +++ b/cmake/runtime.cmake.in @@ -21,10 +21,28 @@ set(GBARECOMP_CORE_BIN_DIR "@CMAKE_CURRENT_BINARY_DIR@" CACHE PATH "") set(GBARECOMP_HOST_STACK_RESERVE_BYTES "16777216" CACHE STRING "Host stack reserve for Windows game executables that link gbarecomp_runtime") +function(gbarecomp_compiler_uses_msvc_linker out_var) + if(MSVC OR + CMAKE_C_SIMULATE_ID STREQUAL "MSVC" OR + CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC" OR + CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" OR + CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + set(${out_var} TRUE PARENT_SCOPE) + else() + set(${out_var} FALSE PARENT_SCOPE) + endif() +endfunction() + function(gbarecomp_target_link_host_stack target_name scope) - if(MSVC) + gbarecomp_compiler_uses_msvc_linker(_gbarecomp_msvc_linker) + if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" OR + CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") target_link_options(${target_name} ${scope} "/STACK:${GBARECOMP_HOST_STACK_RESERVE_BYTES}") + elseif(CMAKE_EXECUTABLE_SUFFIX STREQUAL ".exe" AND + _gbarecomp_msvc_linker) + target_link_options(${target_name} ${scope} + "LINKER:/STACK:${GBARECOMP_HOST_STACK_RESERVE_BYTES}") elseif(CMAKE_EXECUTABLE_SUFFIX STREQUAL ".exe" AND (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang"))