# cmake/toolchains/linux-to-win-msvc.cmake # Linux host -> Windows MSVC-ABI cross toolchain using clang-cl + lld-link # + xwin-supplied Win10 SDK/CRT. Driven by Ninja Multi-Config. set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_PROCESSOR x86_64) if(NOT DEFINED XWIN_DIR) if(DEFINED ENV{XWIN_DIR}) set(XWIN_DIR "$ENV{XWIN_DIR}") else() set(XWIN_DIR "$ENV{HOME}/.xwin/splat") endif() endif() set(XWIN_DIR "${XWIN_DIR}" CACHE PATH "xwin splat root (contains crt/ and sdk/)") if(NOT EXISTS "${XWIN_DIR}/crt/include") message(FATAL_ERROR "XWIN_DIR=${XWIN_DIR} missing crt/include - run xwin splat.") endif() set(CMAKE_C_COMPILER clang-cl) set(CMAKE_CXX_COMPILER clang-cl) set(CMAKE_LINKER lld-link) set(CMAKE_RC_COMPILER llvm-rc) set(CMAKE_AR llvm-lib) set(CMAKE_MT llvm-mt) set(CMAKE_C_COMPILER_TARGET x86_64-pc-windows-msvc) set(CMAKE_CXX_COMPILER_TARGET x86_64-pc-windows-msvc) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # Force /MD (release CRT) for every config. xenia's CMakeLists.txt does a # `string(REPLACE "/MDd" "/MD" ...)` on CMAKE_CXX_FLAGS_DEBUG, but with # clang-cl, the runtime selection comes from CMAKE_MSVC_RUNTIME_LIBRARY # (which expands to -MDd in dash form), so the substitution misses. # Pinning the policy here avoids the need for non-redistributable debug # CRT DLLs (MSVCP140D.dll etc) at runtime, which xwin doesn't ship. cmake_policy(SET CMP0091 NEW) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") # xwin's default splat is a flat layout (crt/include, sdk/include/{ucrt,um,shared,...}), # which clang-cl's /winsysroot does NOT understand. Use explicit -imsvc + -libpath: # instead. Re-running `xwin splat --use-winsysroot-style` would also work but # requires re-downloading ~600 MB. # Use SHELL: prefix so CMake doesn't deduplicate repeated -imsvc tokens. add_compile_options( "SHELL:-imsvc \"${XWIN_DIR}/crt/include\"" "SHELL:-imsvc \"${XWIN_DIR}/sdk/include/ucrt\"" "SHELL:-imsvc \"${XWIN_DIR}/sdk/include/um\"" "SHELL:-imsvc \"${XWIN_DIR}/sdk/include/shared\"" "SHELL:-imsvc \"${XWIN_DIR}/sdk/include/winrt\"" ) add_link_options( "/libpath:${XWIN_DIR}/crt/lib/x86_64" "/libpath:${XWIN_DIR}/sdk/lib/ucrt/x86_64" "/libpath:${XWIN_DIR}/sdk/lib/um/x86_64" ) # xwin pulls the latest MSVC STL which now hard-asserts Clang >= 19. Our host # has Clang 18, which works fine in practice — opt out of the version check. # (See yvals_core.h STL1000 in $XWIN_DIR/crt/include.) add_compile_definitions(_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH) # llvm-rc needs SDK headers explicitly + the resource file's own dir so the # RC's relative ICON path (../../../assets/icon/icon.ico) resolves. get_filename_component(_toolchain_dir "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) get_filename_component(_xenia_root "${_toolchain_dir}/../.." ABSOLUTE) set(CMAKE_RC_FLAGS_INIT "/I \"${XWIN_DIR}/sdk/include/um\" /I \"${XWIN_DIR}/sdk/include/shared\" /I \"${_xenia_root}/src/xenia/app\"") # Quiet MSVC-STL false positives and xenia-specific warnings that clang-cl # emits but cl.exe doesn't (treated as errors under /WX). add_compile_options( -Wno-microsoft-include -Wno-unused-command-line-argument -Wno-ignored-pragma-intrinsic -Wno-nonportable-include-path -Wno-pragma-pack -Wno-tautological-pointer-compare -Wno-microsoft-cast -Wno-deprecated-declarations # These are silenced for native Linux Clang in CMakeLists.txt's else() branch, # but the if(MSVC) branch fires under clang-cl and skips them — so re-add. -Wno-switch -Wno-attributes -Wno-deprecated-register -Wno-deprecated-volatile -Wno-deprecated-enum-enum-conversion # cl.exe accepts __pragma(optimize("s",on)); clang-cl only knows the empty # argument form. xenia gates XE_MSVC_OPTIMIZE_SMALL on _MSC_VER so the # rejected pragma still emits from the clang-cl path. Treat as no-op. -Wno-ignored-pragmas # xenia decorates several `virtual` methods with XE_FORCEINLINE; clang-cl # then complains that the inline body isn't visible in includer TUs # (definitions live in command_processor.cc). cl.exe accepts this silently. -Wno-undefined-inline -Wno-sizeof-pointer-memaccess # `'ZM'` (PE magic, stored little-endian as "MZ" in the binary) — cl.exe # accepts the multi-char constant silently; clang-cl errors under /WX. -Wno-multichar ) # _mm_cvtsi64x_si128 is an MSVC-only alias for the standard _mm_cvtsi64_si128. # Used (gated on XE_PLATFORM_WIN32) in xenia/gpu/draw_util.cc. add_compile_definitions(_mm_cvtsi64x_si128=_mm_cvtsi64_si128) # Plumb FXC for tools/build/compile_shader_dxbc.py (wine fxc auto-prepend). # Use real Win10 SDK fxc.exe 10.x (supports SM 5_1, produces vkd3d-proton- # acceptable DXBC). if(DEFINED ENV{FXC_PATH}) set(ENV_FXC "$ENV{FXC_PATH}") else() set(ENV_FXC "$ENV{HOME}/.local/share/xenia-cross/fxc/fxc.exe") endif() set(ENV{FXC_PATH} "${ENV_FXC}") set(CMAKE_FIND_ROOT_PATH "${XWIN_DIR}") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)