diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f258e14..bf83009 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,3 +34,34 @@ jobs: - name: Test run: dotnet test translator/Translator.sln -c Release --no-build --verbosity normal + + macos_substrate: + name: macOS arm64 (configure + substrate tests) + runs-on: macos-14 + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + + - name: Configure native runtime + shell: bash + run: | + test "$(uname -m)" = arm64 + cmake -S runtime -B build-macos -G Ninja \ + -DCMAKE_BUILD_TYPE=Release -DMKW_BUILD_PRODUCTS=OFF + grep -qx 'CMAKE_OSX_DEPLOYMENT_TARGET:STRING=14.0' \ + build-macos/CMakeCache.txt + + - name: Build macOS portability targets + shell: bash + run: | + cmake --build build-macos --target \ + mkw_platform_paths_tests \ + mkw_macos_native_compile \ + mkw_macos_context_abi_tests \ + mkw_macos_host_context_tests \ + mkw_macos_guest_flat_memory_tests + + - name: Test execution substrate + shell: bash + run: ctest --test-dir build-macos --output-on-failure diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 742418f..e65abd6 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -1,8 +1,8 @@ name: Package installers # Builds the per-platform installer/setup tool (WiiCompiled-Setup.exe / -# WiiCompiled-Setup-x86_64.AppImage) via Launcher/Build-Installer.ps1 and -# Launcher/build-appimage.sh respectively - the same scripts a maintainer runs by hand today to +# WiiCompiled-Setup-x86_64.AppImage / WiiCompiled-Setup.pkg) via the platform packaging scripts - +# the same scripts a maintainer runs by hand today to # produce a GitHub Release asset. This does NOT build the actual translated game executable: # that step requires the end user's own Mario Kart Wii dump (Assets/main.dol, Assets/StaticR.rel), # which is proprietary and not present in this repository or in CI. @@ -11,6 +11,11 @@ on: tags: - '*' workflow_dispatch: + inputs: + version: + description: Package version + required: true + type: string permissions: contents: read @@ -86,14 +91,99 @@ jobs: if-no-files-found: error archive: false + macos-setup-package: + name: macOS (Setup.pkg, Apple Silicon) + runs-on: macos-14 + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + + - uses: actions/setup-dotnet@v6 + with: + dotnet-version: '8.0.x' + + - name: Verify Apple Silicon runner tools + shell: bash + run: | + test "$(uname -m)" = arm64 + xcode-select -p + command -v ninja + file "$(command -v ninja)" | grep -q arm64 + + - name: Download pinned nodtool release + shell: bash + run: | + mkdir -p Launcher/artifacts/macos + nodtool_version=v2.0.0-alpha.10 + nodtool_asset=nodtool-macos-arm64 + nodtool_sha256=e23ca466999b720c55e6d29c9683fce8cc74451ba64ead2e543d50129f24528a + curl -fsSL --retry 3 \ + "https://github.com/encounter/nod/releases/download/${nodtool_version}/${nodtool_asset}" \ + -o Launcher/artifacts/macos/nodtool + printf '%s %s\n' "$nodtool_sha256" Launcher/artifacts/macos/nodtool | shasum -a 256 -c - + chmod +x Launcher/artifacts/macos/nodtool + Launcher/artifacts/macos/nodtool --version + + - name: Publish self-contained translator + shell: bash + run: | + dotnet publish translator/src/Translator.Cli/Translator.Cli.csproj \ + -c Release -r osx-arm64 --self-contained true \ + -p:PublishSingleFile=true \ + -o Launcher/artifacts/macos/translator + + - name: Download pinned portable CMake + shell: bash + run: | + cmake_version=4.4.3 + archive="cmake-${cmake_version}-macos-universal.tar.gz" + base_url="https://github.com/Kitware/CMake/releases/download/v${cmake_version}" + expected_sha256=0c5d65251c14cc884bfa16bdbed3c263ce5bffe2e21c0d0d00962cb0610464fa + curl -fsSL --retry 3 "$base_url/$archive" -o "$archive" + printf '%s %s\n' "$expected_sha256" "$archive" | shasum -a 256 -c - + tar -xzf "$archive" + mv "cmake-${cmake_version}-macos-universal/CMake.app/Contents" Launcher/artifacts/macos/cmake + + - name: Build Setup.pkg + env: + PACKAGE_VERSION: ${{ inputs.version }} + TAG_VERSION: ${{ github.ref_name }} + shell: bash + run: | + package_version="$PACKAGE_VERSION" + if [[ -z "$package_version" ]]; then package_version="${TAG_VERSION#v}"; fi + mkdir -p Launcher/dist + Launcher/macos/build-setup-pkg.command \ + --nodtool Launcher/artifacts/macos/nodtool \ + --translator Launcher/artifacts/macos/translator/Translator.Cli \ + --cmake-root Launcher/artifacts/macos/cmake \ + --ninja "$(command -v ninja)" \ + --output Launcher/dist/WiiCompiled-Setup.pkg \ + --version "$package_version" + + - name: Verify package boundary + shell: bash + run: | + pkgutil --check-signature Launcher/dist/WiiCompiled-Setup.pkg + ! pkgutil --payload-files Launcher/dist/WiiCompiled-Setup.pkg | \ + grep -E '/(Assets|generated|PulsarPacks|WiiCompiled.app|RetroRewind.app)(/|$)' + + - uses: actions/upload-artifact@v7 + with: + name: WiiCompiled-Setup-macos-arm64 + path: Launcher/dist/WiiCompiled-Setup.pkg + if-no-files-found: error + archive: false + # Publishes the packaged installers as a GitHub Release whenever a v* tag is pushed. Wheel Wizard # discovers updates from these releases, so the contract it relies on is enforced here: a full - # (non-prerelease) release whose tag is v, carrying an asset named exactly - # WiiCompiled-Setup.exe, produced by a setup host that reports that same version. + # (non-prerelease) release whose tag is v, carrying the expected platform assets, + # produced by setup hosts that report that same version. release: name: Publish GitHub Release if: startsWith(github.ref, 'refs/tags/v') - needs: [linux-appimage, windows-installer] + needs: [linux-appimage, windows-installer, macos-setup-package] runs-on: ubuntu-latest permissions: contents: write @@ -139,7 +229,7 @@ jobs: set -euo pipefail ls -lR artifacts assets=() - for name in WiiCompiled-Setup.exe WiiCompiled-Setup-x86_64.AppImage WiiCompiled-Setup-aarch64.AppImage; do + for name in WiiCompiled-Setup.exe WiiCompiled-Setup-x86_64.AppImage WiiCompiled-Setup-aarch64.AppImage WiiCompiled-Setup.pkg; do found="$(find artifacts -type f -name "$name" | head -n 1)" [ -n "$found" ] && [ -s "$found" ] || { echo "::error::missing release asset $name"; exit 1; } assets+=("$found") diff --git a/Launcher/local-build-macos.command b/Launcher/local-build-macos.command index 1f91b0c..2b2ec91 100755 --- a/Launcher/local-build-macos.command +++ b/Launcher/local-build-macos.command @@ -131,7 +131,9 @@ if (( builds_retro )); then args+=(--resolved-profile "$mod_out/resolved_dispatc step emit-build-shards 'Preparing native build shards'; translator "${args[@]}" step configure-native 'Configuring the native toolchain' -"$cmake_bin" -S "$workspace/runtime" -B "$native_build" -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_MAKE_PROGRAM="$ninja_bin" -DMKW_TRANSLATED_COMPILE_JOBS="$translated_jobs" +# Use Aurora's pinned SDL3 source on macOS. A system SDL3 can be older than +# Aurora's required API even when find_package() succeeds. +"$cmake_bin" -S "$workspace/runtime" -B "$native_build" -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_MAKE_PROGRAM="$ninja_bin" -DMKW_TRANSLATED_COMPILE_JOBS="$translated_jobs" -DAURORA_SDL3_PROVIDER=vendor targets=(); [[ "$profile" != retro-rewind ]] && targets+=(WiiCompiled); [[ "$profile" != base ]] && targets+=(RetroRewind) step compile "Compiling ${targets[*]} locally"; "$cmake_bin" --build "$native_build" --target "${targets[@]}" --parallel "$global_jobs" if [[ "$profile" != retro-rewind ]]; then "$script_dir/macos/publish-app.command" --build-dir "$native_build" --product WiiCompiled --output-dir "${base_output_dir:-$output_dir}"; fi diff --git a/Launcher/macos/build-setup-pkg.command b/Launcher/macos/build-setup-pkg.command index 50082c9..22efb2b 100755 --- a/Launcher/macos/build-setup-pkg.command +++ b/Launcher/macos/build-setup-pkg.command @@ -103,6 +103,9 @@ copy_clean "$workspace/Launcher/local-build-macos.command" "$resources/workspace copy_clean "$workspace/Launcher/macos/extract-disc.command" "$resources/workspace/Launcher/macos/extract-disc.command" copy_clean "$workspace/Launcher/macos/publish-app.command" "$resources/workspace/Launcher/macos/publish-app.command" chmod +x "$resources/workspace/Launcher/local-build-macos.command" "$resources/workspace/Launcher/macos/"*.command +# setup.command uses this marker to update source inputs in an existing user +# workspace without replacing extracted game assets or Retro Rewind files. +printf '%s\n' "$version" > "$resources/workspace/.bundle-version" mkdir -p "$resources/tools/cmake" copy_clean "$nodtool" "$resources/tools/nodtool"; chmod +x "$resources/tools/nodtool" copy_clean "$translator" "$resources/tools/Translator.Cli"; chmod +x "$resources/tools/Translator.Cli" diff --git a/Launcher/macos/setup.command b/Launcher/macos/setup.command index 8676e7a..5694a57 100755 --- a/Launcher/macos/setup.command +++ b/Launcher/macos/setup.command @@ -62,10 +62,30 @@ if ! /usr/bin/xcode-select -p >/dev/null 2>&1; then fi mkdir -p "$support_root" "$products" -if [[ ! -d "$workspace/.git" && ! -f "$workspace/projects/mkwii/recomp.yml" ]]; then +source_bundle_version="$workspace_source/.bundle-version" +workspace_bundle_version="$workspace/.bundle-version" +needs_workspace_refresh=0 +if [[ ! -f "$workspace/projects/mkwii/recomp.yml" ]]; then + needs_workspace_refresh=1 +elif [[ -f "$source_bundle_version" ]] && [[ ! -f "$workspace_bundle_version" || "$(<"$source_bundle_version")" != "$(<"$workspace_bundle_version")" ]]; then + needs_workspace_refresh=1 +fi + +if (( needs_workspace_refresh )); then printf 'Preparing the local build workspace...\n' - rm -rf "$workspace" - /usr/bin/ditto "$workspace_source" "$workspace" + if [[ ! -d "$workspace" ]]; then + /usr/bin/ditto "$workspace_source" "$workspace" + else + # Refresh only packaged source inputs. Assets and the staged Retro + # Rewind package belong to the user and stay in place. + for source in aurora-main projects runtime translator Launcher; do + /usr/bin/ditto "$workspace_source/$source" "$workspace/$source" + done + /usr/bin/ditto "$source_bundle_version" "$workspace_bundle_version" + # A dependency provider can be cached in this directory, so make the + # refreshed sources configure from a clean native build tree. + rm -rf "$workspace/native-build-macos" + fi fi profile=base diff --git a/README.md b/README.md index d616cb4..4a7be5f 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,21 @@ image under Settings, turn on **WiiCompiled (beta)**, and hit install from the H Wheel Wizard downloads the setup tool from this repo and walks you through install, updates and launching. The backend itself is deliberately command-line only, Wheel Wizard is a wrapper around it. +### macOS + +Download `WiiCompiled-Setup.pkg` from this repository's Releases page and open it. It requires an +Apple Silicon Mac because its bundled nodtool and Translator.Cli executables are arm64. It installs +**WiiCompiled Setup** in Applications; open that app, choose your clean PAL `RMCP01` disc image, +and select either the base game or Retro Rewind. For Retro Rewind, choose the `RetroRewind6` folder +or its parent folder. + +Setup verifies and extracts the image locally, then translates and compiles the native app on your +Mac. On a first run it may ask macOS to install Xcode Command Line Tools; complete Apple's installer, +then open Setup again. When the build completes, Setup asks for administrator approval once to install +`WiiCompiled.app` (and, if selected, `RetroRewind.app`) in `/Applications`. + +Setup opens Terminal while it works, so the extraction and build progress—and any error that needs +reporting—remain visible. > [!CAUTION] > Only take builds from this repository's diff --git a/aurora-main/cmake/AuroraSDL3Provider.cmake b/aurora-main/cmake/AuroraSDL3Provider.cmake index 16ce933..7f3de51 100644 --- a/aurora-main/cmake/AuroraSDL3Provider.cmake +++ b/aurora-main/cmake/AuroraSDL3Provider.cmake @@ -41,7 +41,10 @@ if (_aurora_sdl3_provider STREQUAL "auto") set(_aurora_sdl3_provider "package") else () set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL ON) - find_package(SDL3 QUIET) + # Aurora uses APIs from the SDL version pinned by AURORA_SDL3_VERSION. + # Do not silently select an older system package and fail later while + # compiling its headers. + find_package(SDL3 ${AURORA_SDL3_VERSION} QUIET) set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL OFF) if (SDL3_FOUND) set(_aurora_sdl3_provider "system") @@ -58,7 +61,7 @@ if (_aurora_sdl3_provider STREQUAL "system") message(STATUS "aurora: Using system SDL3 (provider=system)") if (NOT SDL3_FOUND) set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL ON) - find_package(SDL3 REQUIRED) + find_package(SDL3 ${AURORA_SDL3_VERSION} REQUIRED) set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL OFF) endif () _aurora_sdl3_select_target() diff --git a/aurora-main/lib/dolphin/pad/pad.cpp b/aurora-main/lib/dolphin/pad/pad.cpp index bb82c24..b06c489 100644 --- a/aurora-main/lib/dolphin/pad/pad.cpp +++ b/aurora-main/lib/dolphin/pad/pad.cpp @@ -1438,7 +1438,10 @@ void __PADWriteDeadZones(SDL_IOStream* file, // NOLINT(*-reserved-identifier) void PADSerializeMappings() { const std::filesystem::path basePath = fs_path_from_string(aurora::g_config.userPath); - for (auto& controller : aurora::input::g_GameControllers | std::views::values) { + // Avoid std::views::values here: older Apple libc++ releases implement the + // C++20 ranges algorithms we use but not this adaptor. + for (auto& entry : aurora::input::g_GameControllers) { + auto& controller = entry.second; EnsureMappingLoaded(&controller); const auto filePath = basePath / fmt::format("{}_{:04X}_{:04X}.controller", aurora::input::controller_name(controller.m_index), diff --git a/aurora-main/lib/system_info.cpp b/aurora-main/lib/system_info.cpp index 15a58d4..9197cd0 100644 --- a/aurora-main/lib/system_info.cpp +++ b/aurora-main/lib/system_info.cpp @@ -235,7 +235,7 @@ std::string GetOSVersion() { constexpr auto name = "iOS"; #elif TARGET_OS_TV constexpr auto name = "tvOS"; -#elif +#else constexpr auto name = Unknown; #endif diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index be057c7..a6d383b 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -17,6 +17,16 @@ else() message(FATAL_ERROR "WiiCompiled supports 64-bit LLVM-MinGW Clang on Windows, native Linux x86_64/aarch64, or Apple Clang on macOS arm64") endif() + +# Do not inherit the host SDK's deployment target (macOS 26 on current +# toolchains). The supported Apple Silicon release is macOS 14 and the app +# bundle advertises that same minimum. This remains arm64-only until the Intel +# support work is merged. +if(MKW_PLATFORM_MACOS) + set(CMAKE_OSX_DEPLOYMENT_TARGET "14.0" CACHE STRING + "Minimum macOS version for the Apple Silicon build" FORCE) +endif() + if(NOT CMAKE_BUILD_TYPE STREQUAL "Release") message(FATAL_ERROR "WiiCompiled only supports Release builds") endif()