Files
wiicompiled/runtime/cmake/RuntimeLibrary.cmake
T
2026-10-18 18:07:55 +02:00

181 lines
8.1 KiB
CMake

# The game-independent native runtime (runtime/src). One definition serves
# three uses: the OBJECT library the products link from source, the STATIC
# archive the native prebuilt export ships (mkw_runtime), and that archive
# imported in place of compiling it (mkw_runtime_prebuilt).
include("${CMAKE_CURRENT_LIST_DIR}/RuntimeFingerprint.cmake")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(AMD64|amd64|x86_64|X86_64)$")
set(MKW_HOST_IS_X86_64 TRUE)
else()
set(MKW_HOST_IS_X86_64 FALSE)
endif()
# Windows, Linux and Intel macOS x86_64 use the selected profile. AArch64
# builds are compiled locally for the host that will run them, so both Linux
# and Apple Silicon use the compiler's native CPU tuning rather than leaving
# target-specific performance on the table.
if(MKW_HOST_IS_X86_64)
set(MKW_BASELINE_ARCH_FLAG -march=x86-64-${MKW_X86_CPU_PROFILE})
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)$")
set(MKW_BASELINE_ARCH_FLAG -mcpu=native)
else()
set(MKW_BASELINE_ARCH_FLAG "")
endif()
if(MKW_PLATFORM_MACOS)
find_library(MKW_COREAUDIO_FRAMEWORK CoreAudio REQUIRED)
endif()
# CMake decides WHOLE_ARCHIVE's form by probing ld.lld in ELF mode, which
# accepts --push-state; the MinGW lld driver rejects it at link time.
if(MKW_PLATFORM_WINDOWS)
set(CMAKE_CXX_LINK_LIBRARY_USING_WHOLE_ARCHIVE
"LINKER:--whole-archive" "<LINK_ITEM>" "LINKER:--no-whole-archive")
endif()
function(mkw_apply_common_compile_options target)
target_compile_options(${target} PRIVATE -O3 -ffast-math -w -pipe)
endfunction()
function(mkw_apply_baseline_arch target)
if(MKW_BASELINE_ARCH_FLAG)
target_compile_options(${target} PRIVATE ${MKW_BASELINE_ARCH_FLAG})
if(MKW_X86_CPU_PROFILE STREQUAL "v2")
target_compile_definitions(${target} PRIVATE MKW_X86_CPU_PROFILE_V2=1)
endif()
endif()
endfunction()
function(mkw_configure_object_target target)
target_include_directories(${target} PRIVATE
"${MKW_RUNTIME_SOURCE_DIR}/include"
"${MKW_RUNTIME_SOURCE_DIR}/src"
# Workspace root, so translator output is spelled "generated/<x>.h"
# instead of a ../ chain whose depth depends on the includer.
"${MKW_RUNTIME_SOURCE_DIR}/.."
"${MKW_RUNTIME_SOURCE_DIR}/../aurora-main/include")
target_compile_definitions(${target} PRIVATE
TARGET_PC)
set_target_properties(${target} PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)
endfunction()
# scope is PRIVATE for a compiled target and INTERFACE for the imported archive.
function(mkw_runtime_link_dependencies target scope)
target_link_libraries(${target} ${scope}
aurora::gx aurora::pad aurora::si aurora::vi aurora::mtx)
target_link_libraries(${target} ${scope} mkw_platform mkw::pugixml mkw::toml11 mkw::cryptopp mkw::mbedtls)
if(MKW_PLATFORM_WINDOWS)
target_link_libraries(${target} ${scope} shell32 windowsapp)
elseif(MKW_PLATFORM_LINUX OR MKW_PLATFORM_MACOS_X86_64)
# ${CMAKE_DL_LIBS} for music_attenuation.cpp's dlopen of libdbus-1 (MPRIS
# media monitoring). Empty on platforms where dl* is already in libc/libSystem.
target_link_libraries(${target} ${scope} mkw::libco ${CMAKE_DL_LIBS})
endif()
if(MKW_PLATFORM_MACOS)
# CoreAudio framework is required for automatic music muting on macOS.
target_link_libraries(${target} ${scope} "${MKW_COREAUDIO_FRAMEWORK}")
if(MKW_PLATFORM_MACOS_X86_64)
# libco is used by Intel macOS. Apple Silicon uses the local
# x18-safe assembly backend and therefore does not define mkw::libco.
target_link_libraries(${target} ${scope} mkw::libco)
endif()
endif()
endfunction()
# Compiles the runtime sources as an OBJECT or STATIC library.
function(mkw_add_runtime_library target type)
set(_sources ${ARGN})
add_library(${target} ${type} ${_sources})
mkw_configure_object_target(${target})
target_compile_features(${target} PRIVATE cxx_std_20)
target_compile_definitions(${target} PRIVATE
SDL_MAIN_HANDLED
_DISABLE_STRING_ANNOTATION _DISABLE_VECTOR_ANNOTATION)
mkw_runtime_link_dependencies(${target} PRIVATE)
if(MKW_CPPWINRT_INCLUDE_DIR)
if(NOT EXISTS "${MKW_CPPWINRT_INCLUDE_DIR}/winrt/base.h")
message(FATAL_ERROR
"MKW_CPPWINRT_INCLUDE_DIR does not contain winrt/base.h: ${MKW_CPPWINRT_INCLUDE_DIR}")
endif()
target_include_directories(${target} PRIVATE "${MKW_CPPWINRT_INCLUDE_DIR}")
endif()
# Keep runtime unity units small and semantically related. The old generated-TU
# batch size put all 57 native runtime sources into one memory-heavy compiler job.
foreach(source IN LISTS _sources)
get_filename_component(source_name "${source}" NAME_WE)
string(REPLACE "\\" "/" source_normalized "${source}")
if(source_normalized MATCHES "/hle/gx/")
set(runtime_group "gx_bridge")
elseif(source_name MATCHES "network|socket|dns|dwc|ios")
set(runtime_group "network_ios")
elseif(source_name MATCHES "os_|system|memory|fiber|scheduler")
set(runtime_group "guest_system")
elseif(source_name MATCHES "debug|trace|prof")
set(runtime_group "diagnostics")
else()
string(SHA256 source_hash "${source_name}")
string(SUBSTRING "${source_hash}" 0 4 source_hash_prefix)
math(EXPR runtime_bucket "0x${source_hash_prefix} % 8")
set(runtime_group "runtime_${runtime_bucket}")
endif()
set_source_files_properties("${source}" PROPERTIES UNITY_GROUP "${runtime_group}")
endforeach()
# PPC semantic sources are excluded from unity/PCH and configured in CMakeLists.txt.
set_target_properties(${target} PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE GROUP)
target_precompile_headers(${target} PRIVATE "${MKW_RUNTIME_SOURCE_DIR}/include/mkw_pch.h")
mkw_apply_common_compile_options(${target})
mkw_apply_baseline_arch(${target})
endfunction()
function(mkw_import_prebuilt_runtime target archive)
add_library(${target} STATIC IMPORTED GLOBAL)
set_target_properties(${target} PROPERTIES IMPORTED_LOCATION "${archive}")
mkw_runtime_link_dependencies(${target} INTERFACE)
endfunction()
# Sets MKW_RUNTIME_USE_PREBUILT in the caller. The archive replaces the
# runtime's objects only when it was built from exactly this workspace's
# runtime inputs for the same x86-64 profile.
function(mkw_select_runtime_provider)
set(_archive "${MKW_NP_RUNTIME_ARCHIVE_PATH}")
set(_exists FALSE)
if(_archive AND EXISTS "${_archive}")
set(_exists TRUE)
endif()
set(_fingerprint "")
if(_exists AND MKW_USE_PREBUILT_RUNTIME AND MKW_HOST_IS_X86_64 AND
MKW_NP_RUNTIME_CPU_PROFILE STREQUAL MKW_X86_CPU_PROFILE)
mkw_runtime_fingerprint(_fingerprint "${MKW_RUNTIME_SOURCE_DIR}"
"${MKW_CPPWINRT_INCLUDE_DIR}" "${MKW_X86_CPU_PROFILE}")
endif()
mkw_runtime_prebuilt_decision(_use _reason
ARCHIVE "${_archive}"
ENABLED "${MKW_USE_PREBUILT_RUNTIME}"
X86_64 "${MKW_HOST_IS_X86_64}"
ARCHIVE_EXISTS "${_exists}"
PACKAGE_PROFILE "${MKW_NP_RUNTIME_CPU_PROFILE}"
PROFILE "${MKW_X86_CPU_PROFILE}"
PACKAGE_FINGERPRINT "${MKW_NP_RUNTIME_FINGERPRINT}"
FINGERPRINT "${_fingerprint}")
if(NOT MKW_NATIVE_PREBUILT_DIR)
set(_reason "no native prebuilt package is configured")
endif()
if(_use)
message(STATUS "Native runtime: precompiled archive ${_archive} (${_reason})")
# Any runtime edit must re-run configure so the mismatch is noticed.
mkw_runtime_fingerprint_inputs(_inputs "${MKW_RUNTIME_SOURCE_DIR}")
list(TRANSFORM _inputs PREPEND "${MKW_RUNTIME_SOURCE_DIR}/")
if(MKW_CPPWINRT_INCLUDE_DIR)
list(APPEND _inputs "${MKW_CPPWINRT_INCLUDE_DIR}/winrt/base.h")
endif()
set_property(DIRECTORY "${CMAKE_SOURCE_DIR}" APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${_inputs})
else()
message(STATUS "Native runtime: compiled from source (${_reason})")
endif()
set(MKW_RUNTIME_USE_PREBUILT ${_use} PARENT_SCOPE)
endfunction()