Files
wiicompiled/runtime/CMakeLists.txt
T
Toby Fox f555de201f feature: iOS Support (#116)
* build: add an iOS arm64 target

Selects iOS before macOS, since APPLE is true for both and the macOS
branch would otherwise claim an iOS configure and pick a memory backend
that cannot compile there.

Third-party libraries are pinned static on Apple targets. aurora picks
shared ones whenever BUILD_SHARED_LIBS is merely undefined, and its
extern/ tree unsets the cache entry while working around xxhash, so
passing it on the command line only survives one configure. On iOS that
was fatal rather than untidy: libpng linked as a dylib with an @rpath
into the build tree, which dyld cannot resolve inside a bundle.

User state lives in the container's Documents rather than a name-scoped
Application Support directory, so Config.toml sits beside the game data
a relative dvd_root resolves against, and both are reachable over file
sharing.

(cherry picked from commit ad7231fca3d55c5d7d1807c5accb6874d702111f)
(cherry picked from commit 76cc9594e02d5a858c0848b4b4e4e5a585151cc0)
(cherry picked from commit 80a6b53abd699942178fde2f16010d54dba9952b)

* ios: resolve the flat guest base at runtime

No fixed base works on every device. Probing an iPhone 17 Pro and an
iPad Pro M5 with the same 24-candidate sweep gave disjoint sets of free
4 GiB windows - 448 GiB only, against 12, 16, 20, 24, 32 and 48 GiB -
and the extended-virtual-addressing entitlement changed neither map. So
iOS takes whatever the kernel offers and publishes it, while every other
target keeps its compile-time constant.

The backend is the macOS one adapted twice over: <mach/mach_vm.h> is not
in the iOS SDK, so the vm_* calls are used instead, and the backing store
is an anonymous mapping rather than a file in /tmp, which the sandbox
denies.

g_requiresCheckedAccess is set from the real page size. Apple Silicon's
16 KiB host pages are coarser than the 4 KiB guest page, so page
protection alone cannot be relied on.

(cherry picked from commit 0677b83ed45e8b59d779d37cad172c737daf08eb)
(cherry picked from commit 9a8a80ffd4c3f87652e37208fc88afd0a94e6cf8)
(cherry picked from commit 2b7707e6226ee20a6c0564c0f9bbcdd06b511061)

* ios: pick a display explicitly and survive a second scene

A bare SDL_WINDOWPOS_CENTERED does not say which display it means. With
an external screen attached that left the window sized for one display
and the surface for another, which played audio over a black screen.
The primary display is now named outright and its bounds used.

SDL calls SDL_main from scene:willConnectToSession:, once per connecting
scene, and iOS creates a second scene when a display is attached. That
re-entered main while the first call was still inside the game loop: the
data sections reloaded, no static constructors ran the second time, and
aurora then failed to create a window. Declaring
UIApplicationSupportsMultipleScenes=false does not prevent the extra
scene, so the guard belongs here.

(cherry picked from commit d8b984cfbb8521f06776ae765131452c4380e473)
(cherry picked from commit d20895a98739c11f97de1222834859e2a55e3516)
(cherry picked from commit 492f57ef5122305b0ab63258a5a4efe960f5abc9)

* ios: add on-screen touch controls

A touch device has no pad and no F10, so without these it boots to a
screen nothing can drive.

The overlay polls SDL's finger list rather than using ImGui widgets,
whose SDL backend collapses touch to one emulated mouse - steering,
accelerating and drifting all happen at once. Input merges into
PAD__Read_HLE only when port 0 has no real pad, so a controller always
wins, and the overlay hides itself while one is attached.

Positions are held as a distance from a screen edge in units of screen
height. A fraction of width lands somewhere different on a 1.45:1 iPad
and a 2.17:1 iPhone. The d-pad is one cross with the direction taken
from the dominant axis, and the stick keeps the finger that grabbed it
until that finger lifts, so sliding past the gate does not drop steering
mid-corner.

Buttons use Zacksly's GameCube icons, CC BY 3.0, with attribution beside
them in the bundle. The dark backing is each glyph's own silhouette
tinted black, so the d-pad and the triggers are not given a disc they do
not have. They are decoded up front: doing it lazily made the frame the
controls appear on pay for every decode at once.

Tapping the FPS readout opens the settings bar, which is otherwise
unreachable - and the readout's tap target is cleared before the early
return when FPS display is off, or a stale rectangle keeps swallowing
taps meant for the fallback menu button.

PADIsInputBlocked comes back to aurora; it went with the WUP-028 revert
and the overlay needs it to avoid driving the guest while the bar is up.

(cherry picked from commit 79d3de3c0b9c883ff2ec34a5964498a475e91240)
(cherry picked from commit cf7a8edb3405d4f7d7fd189d19cdb2f746b190f9)
(cherry picked from commit 360261208c95616ec81d8f8c3d69efc3c776c54b)

* ios: build an unsigned ipa

CMake bundles iOS targets with its own default Info.plist, whose
CFBundleIdentifier is empty and which carries none of the iOS keys, so
what came out of the build could not be installed. It now gets a real
plist and is packaged as an .ipa.

Unsigned on purpose: AltStore, SideStore and LiveContainer sign on the
device with the user's own Apple ID, so anything applied here would only
be replaced. WiiCompiled.entitlements is a template for signing by hand,
which those tools ignore.

Packaging runs after the asset copies rather than before, or the archive
gets the binary and nothing else. The touch directory is cleared before
it is copied, since copy_directory merges and a removed icon would
otherwise be shipped.

(cherry picked from commit 5ce43949dbf27abff6782bc41e3be0ede3ac135b)
(cherry picked from commit 633e3e0aa2f7ea116741f27ec46e9c743be9cf9a)
(cherry picked from commit a4ae6f2e8bdf11596a89dca9607aba92713184be)

* docs: document the iOS build

Covers building the .ipa, sideloading it, the one entitlement the app
needs, and where the game data goes.

The configure line is the one that works: without CMAKE_SYSTEM_PROCESSOR
the Dawn package URL comes out as dawn-ios-.tar.gz and the build fails
on a 404.

(cherry picked from commit 08eefad3fd1cb5e8f79a144ac119bc65852e33e6)
(cherry picked from commit b7cd38e07eefc8af4c1c60ca411c009eec4e212a)
(cherry picked from commit 5a1650ef194f9da4ae8a68f1a9779b16ee118ca8)

* ios: stub out Discord presence

It connects over a Unix socket to a local Discord client, which iOS does
not have, so it can only ever fail and back off. Stubbed rather than left
retrying.

(cherry picked from commit 69aa5e5c297abe65188d391748b8fb11c57337d2)

* build: keep the macOS host tests off iOS and give the audit target libpng

The macOS test executables were gated on MKW_PLATFORM_MACOS, which iOS also sets, so a full iOS build tried to compile guest_flat_memory_macos.cpp against an SDK with no <mach/mach_vm.h>. The products-off audit compile picked up the touch overlay sources without the PNG include path.

* ios: tidy the touch decode and pad merge after review

The row-pointer buffer now lives in PngReader so a libpng longjmp cannot skip its destructor. PAD__Read_HLE no longer uses the port 0 error code to decide whether touch applies; keyboard bindings report PAD_ERR_NONE with no controller attached, and TouchPad::Read already checks for a physical pad.

* docs: tag the iOS build fence as sh

* ios: pin the CPU baseline instead of tuning for the build host

-mcpu=native tuned the phone binary for whichever Mac compiled it, and upstream clang rejects the flag outright when cross-compiling. iOS 17 implies the A12 and later.

* build: cross-compile the iOS products from Linux

* use online sdk instead of mac sdk to build on linux

* build: ios platform identifier

* build: build the ios ipa on windows too

* fix: strap cover ends too early on slower devices

* ci: compile the ios runtime on a linux runner

* docs: note the entitlement needed on devices with less than 4gb ram
2026-09-05 10:12:53 +02:00

410 lines
23 KiB
CMake

cmake_minimum_required(VERSION 3.16)
project(mkw_recompiled)
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Clang|AppleClang)$" OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message(FATAL_ERROR "WiiCompiled requires a 64-bit Clang toolchain")
endif()
if(WIN32 AND MINGW AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(AMD64|amd64|x86_64|X86_64)$")
set(MKW_PLATFORM_WINDOWS TRUE)
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
# Checked before macOS: APPLE is true for iOS too, so the macOS branch would
# otherwise claim an iOS build and select a backend that cannot compile
# there (<mach/mach_vm.h> is absent from the iOS SDK) or run there (/tmp is
# outside the sandbox).
set(MKW_PLATFORM_IOS TRUE)
set(MKW_PLATFORM_MACOS TRUE) # shares the Apple arm64 substrate
elseif(APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|ARM64)$")
# The first native macOS target is Apple Silicon. Intel and universal
# binaries remain future compatibility work; do not silently claim them.
set(MKW_PLATFORM_MACOS TRUE)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(AMD64|amd64|x86_64|X86_64|aarch64|arm64|ARM64)$")
set(MKW_PLATFORM_LINUX TRUE)
else()
message(FATAL_ERROR
"WiiCompiled supports 64-bit LLVM-MinGW Clang on Windows, native Linux "
"x86_64/aarch64, or Apple Clang on macOS arm64 or iOS arm64")
endif()
if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
message(FATAL_ERROR "WiiCompiled only supports Release builds")
endif()
option(MKW_BUILD_PRODUCTS "Build translated WiiCompiled product targets" ON)
set(MKW_IOS_BUNDLE_ID_PREFIX "it.tobyfox" CACHE STRING
"Reverse-DNS prefix for the iOS bundle identifier")
# Preprocessor definitions that belong to this project's own code (the runtime,
# the translated shards and the product glue) and to nothing else. They are
# applied directory-scoped, immediately after the aurora add_subdirectory() call,
# so every target created afterwards (mkw_runtime_common, the translated shard
# libraries and the products in cmake/PublicProducts.cmake) inherits them while
# aurora-main and its third-party tree stay unaffected.
set(MKW_PROJECT_COMPILE_DEFINITIONS NOMINMAX)
if(MKW_PLATFORM_IOS)
# One project-wide answer to "is this iOS", so sources do not each pull in
# TargetConditionals.h and spell out the __APPLE__ && TARGET_OS_IPHONE dance.
list(APPEND MKW_PROJECT_COMPILE_DEFINITIONS MKW_PLATFORM_IOS=1)
endif()
set(CMAKE_CXX_STANDARD 17)
# Declared before the vendored libraries so the third-party block below can
# branch on it and so cmake/NativePrebuilt.cmake is included after the names it
# must provide are known.
set(MKW_NATIVE_PREBUILT_DIR "" CACHE PATH
"Precompiled aurora/third-party package to link instead of building aurora-main")
# Maintainer-only counterpart: describe the configured aurora build so the
# package can be harvested from it.
set(MKW_NATIVE_PREBUILT_EXPORT_DIR "" CACHE PATH
"Maintainer-only: write a description of the configured aurora build here")
# The two Crypto++ configuration macros are load-bearing for ABI: they shape the
# structs and inline code the headers generate, so a first-party TU including
# <cryptopp/...> must see exactly what the archive was compiled with. Both the
# from-source target below and the prebuilt import in cmake/NativePrebuilt.cmake
# consume this one definition.
set(MKW_CRYPTOPP_INTERFACE_DEFINITIONS CRYPTOPP_DISABLE_ASM CRYPTOPP_NO_GLOBAL_BYTE)
# Riivolution XML is parsed with pugixml, matching the parser used by Dolphin.
# The four upstream files from v1.15 (ee86beb30e4973f5feffe3ce63bfa4fbadf72f38)
# are vendored so builds remain usable with FETCHCONTENT_FULLY_DISCONNECTED.
add_library(mkw_pugixml STATIC third_party/pugixml/pugixml.cpp)
add_library(mkw::pugixml ALIAS mkw_pugixml)
target_include_directories(mkw_pugixml PUBLIC third_party/pugixml)
target_compile_features(mkw_pugixml PUBLIC cxx_std_17)
set_target_properties(mkw_pugixml PROPERTIES UNITY_BUILD OFF)
# Linux guest-fiber scheduling (runtime/src/host_context.cpp) needs a symmetric
# stackful-coroutine primitive to stand in for Win32 Fibers. libco's co_switch() transfers
# directly to any other created coroutine, matching SwitchToFiber's semantics exactly (unlike
# asymmetric resume/yield coroutine libraries, which would need every call site restructured).
# Vendored from upstream (higan-emu/libco @ e18e09d, 2019-10-16, ISC license; valgrind.h is
# separately BSD-style licensed, see third_party/libco/LICENSE). Windows keeps native Fibers
# and macOS uses the project's x18-safe AArch64 assembly backend, so this target is Linux-only.
if(MKW_PLATFORM_LINUX)
add_library(mkw_libco STATIC third_party/libco/libco.c)
add_library(mkw::libco ALIAS mkw_libco)
target_include_directories(mkw_libco PUBLIC third_party/libco)
set_target_properties(mkw_libco PROPERTIES UNITY_BUILD OFF)
endif()
# Runtime configuration is real TOML, parsed by toml11 rather than a project-
# specific line parser. Keep it header-only and vendored so disconnected release
# builds have exactly the same parser as developer builds.
add_library(mkw_toml11 INTERFACE)
add_library(mkw::toml11 ALIAS mkw_toml11)
target_include_directories(mkw_toml11 SYSTEM INTERFACE third_party/toml11)
target_compile_features(mkw_toml11 INTERFACE cxx_std_17)
# Wii ES signatures use the standard binary-field sect233r1 curve. Crypto++
# supplies that curve, SHA-1, ECDSA and an OS-seeded CSPRNG. The complete 8.9.0
# source distribution is vendored. Assembly and algorithm-specific SIMD units
# are disabled to keep the library portable and independent of the runtime's
# x86-64-v3 policy; the static linker retains only the algorithms we reference.
#
# Crypto++ is by far the most expensive vendored library to compile (~150
# translation units), and under the shipped fixed toolchain it is bit-for-bit
# identical for every user, so the prebuilt package harvests its archive and
# this block is skipped entirely in that mode (see cmake/NativePrebuilt.cmake).
if(NOT MKW_NATIVE_PREBUILT_DIR)
file(GLOB MKW_CRYPTOPP_SOURCES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_LIST_DIR}/third_party/cryptopp/*.cpp")
list(FILTER MKW_CRYPTOPP_SOURCES EXCLUDE REGEX
"/(adhoc|bench[123]|datatest|dlltest|fipsalgt|fipstest|pch|regtest[1234]|simple|test|validat[0-9]+)\\.cpp$")
list(FILTER MKW_CRYPTOPP_SOURCES EXCLUDE REGEX
"(_avx|_ppc|_simd|_sse)\\.cpp$")
add_library(mkw_cryptopp STATIC ${MKW_CRYPTOPP_SOURCES})
add_library(mkw::cryptopp ALIAS mkw_cryptopp)
target_include_directories(mkw_cryptopp SYSTEM PUBLIC third_party)
target_compile_features(mkw_cryptopp PUBLIC cxx_std_17)
target_compile_definitions(mkw_cryptopp PUBLIC ${MKW_CRYPTOPP_INTERFACE_DEFINITIONS})
target_compile_options(mkw_cryptopp PRIVATE -w)
set_target_properties(mkw_cryptopp PROPERTIES UNITY_BUILD OFF)
endif()
set(MKW_TRANSLATED_COMPILE_JOBS 0 CACHE STRING
"Cap on concurrently compiling translated shard TUs via a Ninja job pool (0 = uncapped). \
Scheduling only - never affects output bytes, so it is deliberately outside the canonical flag fingerprint.")
set(MKW_CPPWINRT_INCLUDE_DIR "" CACHE PATH "Optional self-contained C++/WinRT include directory")
# Precompiled aurora + third-party package (see launcher/Prepare-NativePrebuilt.ps1).
# Empty - the default - keeps the from-source behaviour every developer build
# uses. When set, aurora-main, its extern/ tree and the vendored Crypto++ are
# not compiled at all; imported targets with the same names are wired up from
# the package instead, so this project's own code compiles and links exactly
# as before.
set(MKW_AURORA_DIR "${CMAKE_CURRENT_LIST_DIR}/../aurora-main")
# The translator's explicit float casts are PPC single-precision rounding points.
# Fast-math may erase them and change guest-visible integer conversions.
set(MKW_TRANSLATED_PPC_FP_OPTIONS -fno-fast-math -ffp-contract=off)
# ----------------------------------------------------------------------
# Third-party: aurora-main (provides SDL3 + GPU backends)
# ----------------------------------------------------------------------
if(MKW_NATIVE_PREBUILT_DIR)
# Precompiled aurora + third-party archives. The source trees are still
# present (the runtime includes aurora headers directly), they are simply
# not compiled here.
include("${CMAKE_CURRENT_LIST_DIR}/cmake/NativePrebuilt.cmake")
else()
if(NOT EXISTS ${MKW_AURORA_DIR}/CMakeLists.txt)
message(FATAL_ERROR "Requested aurora-main but ${MKW_AURORA_DIR} is missing")
endif()
# aurora picks shared third-party libraries whenever BUILD_SHARED_LIBS is
# merely undefined, and its extern/ tree calls unset(BUILD_SHARED_LIBS CACHE)
# while working around xxhash, which deletes any -D the user passed. Defining
# it here, before aurora is added, is what actually sticks across
# reconfigures. Apple builds ship a self-contained bundle, so a dylib
# resolved from the build tree or from Homebrew cannot be allowed to leak
# into the link.
if(APPLE)
set(BUILD_SHARED_LIBS OFF)
endif()
set(DAWN_ENABLE_D3D11 OFF CACHE BOOL "" FORCE)
if(MKW_PLATFORM_WINDOWS)
set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE)
set(DAWN_ENABLE_VULKAN ON CACHE BOOL "" FORCE)
set(DAWN_ENABLE_METAL OFF CACHE BOOL "" FORCE)
set(TINT_BUILD_HLSL_WRITER ON CACHE BOOL "" FORCE)
elseif(MKW_PLATFORM_MACOS)
set(DAWN_ENABLE_D3D12 OFF CACHE BOOL "" FORCE)
set(DAWN_ENABLE_VULKAN OFF CACHE BOOL "" FORCE)
set(DAWN_ENABLE_METAL ON CACHE BOOL "" FORCE)
set(TINT_BUILD_HLSL_WRITER OFF CACHE BOOL "" FORCE)
else()
set(DAWN_ENABLE_D3D12 OFF CACHE BOOL "" FORCE)
set(DAWN_ENABLE_VULKAN ON CACHE BOOL "" FORCE)
set(DAWN_ENABLE_METAL OFF CACHE BOOL "" FORCE)
set(TINT_BUILD_HLSL_WRITER OFF CACHE BOOL "" FORCE)
endif()
set(DAWN_BUILD_SAMPLES OFF CACHE BOOL "" FORCE)
set(DAWN_BUILD_TESTS OFF CACHE BOOL "" FORCE)
# Provide a tiny stub for DXProgrammableCapture when the SDK/PIX headers are
# missing (common on MinGW). Dawn only includes the header; no symbols are
# referenced when PIX isn't present.
if(MKW_PLATFORM_WINDOWS)
set(MKW_DX_STUB_DIR "${CMAKE_BINARY_DIR}/aurora_dx_stubs")
if(NOT EXISTS "${MKW_DX_STUB_DIR}/DXProgrammableCapture.h")
file(MAKE_DIRECTORY ${MKW_DX_STUB_DIR})
file(WRITE "${MKW_DX_STUB_DIR}/DXProgrammableCapture.h"
"#pragma once\n// Stubbed PIX capture header for Dawn; no functionality when PIX isn't present.\n")
endif()
endif()
# Deliberately NOT injected project-wide. Only a from-source Dawn build ever
# includes DXProgrammableCapture.h, and this tree consumes Dawn as a prebuilt
# package (AURORA_DAWN_PROVIDER=package), so the old
# include_directories()/add_compile_options(-I...) pair only added a dead
# -I to every one of the ~500 third-party and runtime compile lines. The
# aurora_* targets that do want it get it from the
# target_include_directories() call further down; a from-source Dawn build
# should add it to the Dawn targets the same way.
# Keep SDL3 lean when aurora is enabled.
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
set(SDL_STATIC ON CACHE BOOL "" FORCE)
set(SDL_TEST OFF CACHE BOOL "" FORCE)
# MinGW/WSL can choke on SDL precompiled headers; disable PCH for aurora/SDL.
set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON)
# Isolate aurora build products to a subdirectory under the main build dir.
add_subdirectory(${MKW_AURORA_DIR} ${CMAKE_BINARY_DIR}/aurora-build EXCLUDE_FROM_ALL)
set(CMAKE_DISABLE_PRECOMPILE_HEADERS OFF)
# Keep upstream Aurora split: several sources intentionally use file-local
# names that collide under this repo's aggressive unity build settings.
set(AURORA_TARGETS aurora_core aurora_gx aurora_pad aurora_si aurora_mtx aurora_vi)
foreach(t ${AURORA_TARGETS})
if(TARGET ${t})
set_target_properties(${t} PROPERTIES UNITY_BUILD OFF)
target_compile_options(${t} PRIVATE -O3 -ffast-math -w -pipe)
if(MKW_PLATFORM_WINDOWS)
target_include_directories(${t} PRIVATE ${MKW_DX_STUB_DIR})
endif()
# Aurora's own sources include Windows headers and call std::min/max;
# they relied on the old project-wide NOMINMAX that no longer leaks
# into this subtree, so the define is applied per target here.
target_compile_definitions(${t} PRIVATE NOMINMAX)
endif()
endforeach()
# Frame interpolation filters guest NaN/Inf matrices out of a std::sort
# comparator, which makes its std::isfinite guards load-bearing for memory
# safety, not just match quality. -ffinite-math-only (part of -ffast-math
# above) folds those guards to constants and poisons NaN float arguments
# via nofpclass, so this one file opts back out of the finite-math
# assumption; the file #errors if built without this. Source-scoped
# COMPILE_OPTIONS append after the target options, so this overrides the
# target's -ffast-math for exactly this TU.
if(TARGET aurora_gx)
set_source_files_properties("${MKW_AURORA_DIR}/lib/gx/frame_interpolation.cpp"
TARGET_DIRECTORY aurora_gx
PROPERTIES COMPILE_OPTIONS "-fno-finite-math-only")
endif()
if(MKW_NATIVE_PREBUILT_EXPORT_DIR)
include("${CMAKE_CURRENT_LIST_DIR}/cmake/NativePrebuiltExport.cmake")
endif()
endif()
# Everything from here down is this project's own code, so this is where the
# project definitions enter the directory scope. A directory-scoped definition
# seeds the COMPILE_DEFINITIONS of targets as they are created, which means:
# * aurora-main and its third-party tree were added above -> unaffected;
# * mkw_runtime_common, the translated shard libraries and the products in
# cmake/PublicProducts.cmake are all created below (that file is include()d,
# not add_subdirectory()d, so it shares this directory scope) -> they pick
# the definitions up exactly as before.
if(MKW_PROJECT_COMPILE_DEFINITIONS)
add_compile_definitions(${MKW_PROJECT_COMPILE_DEFINITIONS})
endif()
# Runtime sources. CONFIGURE_DEPENDS costs one glob re-check per build (measured
# at ~55 ms across the 100+ globs this build already re-verifies for SDL), and it
# buys correctness: without it, a newly added src/*.cpp that is not referenced by
# a registration file is silently never compiled and never errors. The stale-glob
# failure mode is worth far more than the milliseconds.
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS "src/*.cpp")
if(MKW_PLATFORM_MACOS)
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_LIST_DIR}/src/guest_flat_memory.cpp")
# HostContext's Apple Silicon backend is implemented in a small assembly
# companion. It must be part of the product runtime as well as the
# standalone context test; otherwise the final executable is missing
# mkw_co_init/mkw_co_switch at link time.
enable_language(ASM)
list(APPEND SOURCES "${CMAKE_CURRENT_LIST_DIR}/src/platform/macos/co_switch.S")
set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/src/platform/macos/co_switch.S"
PROPERTIES LANGUAGE ASM SKIP_UNITY_BUILD_INCLUSION ON SKIP_PRECOMPILE_HEADERS ON)
# iOS cannot use the macOS backend: <mach/mach_vm.h> is absent from that SDK
# and /tmp is outside the sandbox.
if(MKW_PLATFORM_IOS)
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_LIST_DIR}/src/guest_flat_memory_macos.cpp")
else()
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_LIST_DIR}/src/guest_flat_memory_ios.cpp")
endif()
else()
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_LIST_DIR}/src/guest_flat_memory_macos.cpp")
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_LIST_DIR}/src/guest_flat_memory_ios.cpp")
endif()
set(MKW_PLATFORM_SOURCE "${CMAKE_CURRENT_LIST_DIR}/src/platform/host_platform.cpp")
set(MKW_BASE_PRODUCT_SOURCE "${CMAKE_CURRENT_LIST_DIR}/src/product/base_product.cpp")
set(MKW_RETRO_REWIND_PRODUCT_SOURCE "${CMAKE_CURRENT_LIST_DIR}/src/product/retro_rewind_product.cpp")
# The host ISA guard is the one translation unit that must not receive the
# x86-64-v3 flags, so it gets its own object library instead of riding along in
# mkw_runtime_common. See cmake/PublicProducts.cmake and the file's own header.
set(MKW_CPU_BASELINE_SOURCE "${CMAKE_CURRENT_LIST_DIR}/src/host_cpu_baseline.cpp")
list(REMOVE_ITEM SOURCES ${MKW_BASE_PRODUCT_SOURCE} ${MKW_RETRO_REWIND_PRODUCT_SOURCE}
${MKW_CPU_BASELINE_SOURCE} ${MKW_PLATFORM_SOURCE})
# This deliberately small library contains host services that are safe to
# validate before guest memory and fiber work makes a full runtime build viable.
add_library(mkw_platform STATIC "${MKW_PLATFORM_SOURCE}")
target_include_directories(mkw_platform PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include")
target_compile_features(mkw_platform PUBLIC cxx_std_17)
set_target_properties(mkw_platform PROPERTIES UNITY_BUILD OFF)
# Keep these independent from Aurora's BUILD_TESTING option: they validate the
# project's host-platform contracts, not Aurora's third-party test suite.
enable_testing()
add_executable(mkw_platform_paths_tests "${CMAKE_CURRENT_LIST_DIR}/tests/platform_paths_tests.cpp")
target_link_libraries(mkw_platform_paths_tests PRIVATE mkw_platform)
target_compile_features(mkw_platform_paths_tests PRIVATE cxx_std_17)
add_test(NAME mkw_platform_paths_tests COMMAND mkw_platform_paths_tests)
# HostContext deliberately keeps the platform-specific context primitive out
# of fiber_manager.cpp. Exercise the Linux libco handoff directly so future
# refactors cannot silently remove its headers, implementation, or link edge.
if(MKW_PLATFORM_LINUX)
add_executable(mkw_linux_host_context_tests
"${CMAKE_CURRENT_LIST_DIR}/tests/host_context_tests.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/host_context.cpp")
target_include_directories(mkw_linux_host_context_tests PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/include"
"${CMAKE_CURRENT_LIST_DIR}/third_party/libco")
target_compile_features(mkw_linux_host_context_tests PRIVATE cxx_std_17)
target_link_libraries(mkw_linux_host_context_tests PRIVATE mkw::libco)
add_test(NAME mkw_linux_host_context_tests COMMAND mkw_linux_host_context_tests)
endif()
if(MKW_PLATFORM_MACOS AND NOT MKW_PLATFORM_IOS)
# Exercise the Apple Silicon context ABI and the public host-memory
# contracts separately from translated products. Host-only: the flat memory
# test pulls in guest_flat_memory_macos.cpp, whose <mach/mach_vm.h> does not
# exist in the iOS SDK, and none of these can run on a device anyway.
enable_language(ASM)
add_executable(mkw_macos_context_abi_tests
"${CMAKE_CURRENT_LIST_DIR}/tests/macos_context_abi_tests.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/platform/macos/co_switch.S")
target_compile_features(mkw_macos_context_abi_tests PRIVATE cxx_std_17)
add_test(NAME mkw_macos_context_abi_tests COMMAND mkw_macos_context_abi_tests)
add_executable(mkw_macos_host_context_tests
"${CMAKE_CURRENT_LIST_DIR}/tests/host_context_tests.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/host_context.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/platform/macos/co_switch.S")
target_include_directories(mkw_macos_host_context_tests PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include")
target_compile_features(mkw_macos_host_context_tests PRIVATE cxx_std_17)
add_test(NAME mkw_macos_host_context_tests COMMAND mkw_macos_host_context_tests)
add_executable(mkw_macos_guest_flat_memory_tests
"${CMAKE_CURRENT_LIST_DIR}/tests/macos_guest_flat_memory_tests.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/guest_flat_memory_macos.cpp")
target_include_directories(mkw_macos_guest_flat_memory_tests PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include")
target_compile_features(mkw_macos_guest_flat_memory_tests PRIVATE cxx_std_17)
add_test(NAME mkw_macos_guest_flat_memory_tests COMMAND mkw_macos_guest_flat_memory_tests)
endif()
# The translator emits the complete, content-addressed source graph. Consuming
# this one manifest keeps configure independent of the 28k generated function
# files and of optional Retro Rewind artifacts such as code.map.
if(MKW_BUILD_PRODUCTS)
set(MKW_TRANSLATED_SHARD_MANIFEST
"${CMAKE_CURRENT_LIST_DIR}/../generated/build_shards/shards.cmake"
CACHE FILEPATH "Translator-owned aggregate shard manifest")
# The prebuilt export only needs the aurora/third-party closure configured above, so a
# packaging machine without a translation stops here instead of failing.
if(MKW_NATIVE_PREBUILT_EXPORT_DIR AND NOT EXISTS "${MKW_TRANSLATED_SHARD_MANIFEST}")
message(STATUS "No translator shard manifest; configuring the native prebuilt export only")
return()
endif()
if(NOT EXISTS "${MKW_TRANSLATED_SHARD_MANIFEST}")
message(FATAL_ERROR
"Missing translator-owned shard manifest: ${MKW_TRANSLATED_SHARD_MANIFEST}. "
"Run Translator.Cli emit-build-shards first; see translator/README.md.")
endif()
include("${MKW_TRANSLATED_SHARD_MANIFEST}")
set(MKW_HAVE_RETRO_REWIND ${MKW_HAVE_RETRO_REWIND_SHARDS})
message(STATUS
"Translator graph: ${MKW_SHARED_BASE_FUNCTION_COUNT}/${MKW_BASE_FUNCTION_COUNT} base functions shared; "
"${MKW_PROFILE_SENSITIVE_CALLER_COUNT} profile-sensitive callers; "
"${MKW_RETRO_REWIND_FUNCTION_COUNT} Retro Rewind functions")
set(MKW_RUNTIME_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/PublicProducts.cmake")
else()
if(MKW_PLATFORM_MACOS)
# Compile-only audit of native runtime sources. It deliberately avoids
# translated products until their host dependencies are portable.
# These sources depend on generated/RuntimeConfig.h, which is emitted for
# a particular game by the translator and is intentionally unavailable
# in this platform-only configuration.
set(MKW_MACOS_NATIVE_AUDIT_SOURCES ${SOURCES})
list(REMOVE_ITEM MKW_MACOS_NATIVE_AUDIT_SOURCES
"${CMAKE_CURRENT_LIST_DIR}/src/abi_bridge.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/hle/os/os_alarm.cpp")
add_library(mkw_macos_native_compile OBJECT ${MKW_MACOS_NATIVE_AUDIT_SOURCES})
target_include_directories(mkw_macos_native_compile PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/include" "${CMAKE_CURRENT_LIST_DIR}/src"
"${CMAKE_CURRENT_LIST_DIR}/.." "${CMAKE_CURRENT_LIST_DIR}/../aurora-main/include")
target_compile_features(mkw_macos_native_compile PRIVATE cxx_std_20)
target_compile_definitions(mkw_macos_native_compile PRIVATE SDL_MAIN_HANDLED TARGET_PC)
target_link_libraries(mkw_macos_native_compile PRIVATE
aurora::gx aurora::pad aurora::si aurora::vi aurora::mtx
PNG::PNG mkw::pugixml mkw::toml11 mkw::cryptopp)
set_target_properties(mkw_macos_native_compile PROPERTIES UNITY_BUILD OFF)
endif()
add_custom_target(mkw_platform_paths_check DEPENDS mkw_platform)
message(STATUS "Translated product targets disabled (MKW_BUILD_PRODUCTS=OFF)")
endif()