From 4f9e6cf2ffb748eb1e7d9a32e7dcd6b673280016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20P=C3=A9rez?= Date: Mon, 18 May 2026 18:02:53 -0500 Subject: [PATCH] Make iOS packaging reproducible --- tools/apply_ios_submodule_patches.sh | 23 ++++++++ tools/package_ios_ipa.sh | 21 ++++++- tools/patches/plume-ios-sdl-vulkan.patch | 72 ++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100755 tools/apply_ios_submodule_patches.sh create mode 100644 tools/patches/plume-ios-sdl-vulkan.patch diff --git a/tools/apply_ios_submodule_patches.sh b/tools/apply_ios_submodule_patches.sh new file mode 100755 index 00000000..e8d96633 --- /dev/null +++ b/tools/apply_ios_submodule_patches.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +PLUME_DIR="$ROOT/thirdparty/plume" +PATCH_FILE="$ROOT/tools/patches/plume-ios-sdl-vulkan.patch" + +if [[ ! -d "$PLUME_DIR/.git" && ! -f "$PLUME_DIR/.git" ]]; then + printf 'Missing Plume submodule. Run: git submodule update --init --recursive\n' >&2 + exit 1 +fi + +if git -C "$PLUME_DIR" apply --check "$PATCH_FILE" >/dev/null 2>&1; then + git -C "$PLUME_DIR" apply "$PATCH_FILE" + printf 'Applied Plume iOS patch.\n' +else + if git -C "$PLUME_DIR" apply --reverse --check "$PATCH_FILE" >/dev/null 2>&1; then + printf 'Plume iOS patch already applied.\n' + else + printf 'Plume iOS patch cannot be applied cleanly. Check thirdparty/plume for local changes.\n' >&2 + exit 1 + fi +fi diff --git a/tools/package_ios_ipa.sh b/tools/package_ios_ipa.sh index becb4455..aab2c222 100755 --- a/tools/package_ios_ipa.sh +++ b/tools/package_ios_ipa.sh @@ -7,6 +7,9 @@ IPA_DIR="$ROOT/out/ipa" PAYLOAD_DIR="$IPA_DIR/Payload" APP_PATH="$BUILD_DIR/Unleashed Recompiled.app" IPA_PATH="$IPA_DIR/UnleashedRecompiled.ipa" +DEFAULT_SIGNING_IDENTITY="Apple Development: aroblesalago@gmail.com (MK28YRUCCG)" + +"$ROOT/tools/apply_ios_submodule_patches.sh" missing=0 for file in \ @@ -20,6 +23,7 @@ for file in \ done if [[ "$missing" -ne 0 ]]; then + printf '\nAdd these files from your own compatible Sonic Unleashed Xbox 360 dump before building an IPA.\n' >&2 exit 1 fi @@ -35,11 +39,24 @@ rm -rf "$IPA_DIR" mkdir -p "$PAYLOAD_DIR" cp -R "$APP_PATH" "$PAYLOAD_DIR/" -if [[ -n "${MOBILEPROVISION:-}" ]]; then - cp "$MOBILEPROVISION" "$PAYLOAD_DIR/Unleashed Recompiled.app/embedded.mobileprovision" +if [[ -z "${CODESIGN_IDENTITY:-}" ]] && security find-identity -v -p codesigning | grep -q "$DEFAULT_SIGNING_IDENTITY"; then + CODESIGN_IDENTITY="$DEFAULT_SIGNING_IDENTITY" +fi + +if [[ -n "${MOBILEPROVISION:-}" && ! -f "${MOBILEPROVISION:-}" ]]; then + printf 'Provisioning profile not found: %s\n' "$MOBILEPROVISION" >&2 + exit 1 fi if [[ -n "${CODESIGN_IDENTITY:-}" ]]; then + if [[ -z "${MOBILEPROVISION:-}" ]]; then + printf 'CODESIGN_IDENTITY is set, but MOBILEPROVISION is not. Producing an unsigned IPA for sideloading tools that sign on import.\n' >&2 + else + cp "$MOBILEPROVISION" "$PAYLOAD_DIR/Unleashed Recompiled.app/embedded.mobileprovision" + fi +fi + +if [[ -n "${CODESIGN_IDENTITY:-}" && -n "${MOBILEPROVISION:-}" ]]; then codesign --force --sign "$CODESIGN_IDENTITY" \ ${ENTITLEMENTS:+--entitlements "$ENTITLEMENTS"} \ "$PAYLOAD_DIR/Unleashed Recompiled.app" diff --git a/tools/patches/plume-ios-sdl-vulkan.patch b/tools/patches/plume-ios-sdl-vulkan.patch new file mode 100644 index 00000000..e2a6e17e --- /dev/null +++ b/tools/patches/plume-ios-sdl-vulkan.patch @@ -0,0 +1,72 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6a7645a..bf336b9 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -8,10 +8,16 @@ if(APPLE) + endif() + + string(COMPARE EQUAL ${CMAKE_SYSTEM_NAME} "Linux" IS_LINUX) ++string(COMPARE EQUAL ${CMAKE_SYSTEM_NAME} "iOS" IS_IOS) ++if(IS_LINUX OR IS_IOS) ++ set(IS_SDL_VULKAN_PLATFORM ON) ++else() ++ set(IS_SDL_VULKAN_PLATFORM OFF) ++endif() + + # Project options + include(CMakeDependentOption) +-cmake_dependent_option(SDL_VULKAN_ENABLED "Enable SDL Vulkan integration" OFF IS_LINUX OFF) ++cmake_dependent_option(SDL_VULKAN_ENABLED "Enable SDL Vulkan integration" OFF IS_SDL_VULKAN_PLATFORM OFF) + cmake_dependent_option(D3D12_AGILITY_SDK_ENABLED "Enable D3D12 Agility SDK" OFF WIN32 OFF) + option(PLUME_BUILD_EXAMPLES "Build example applications" OFF) + +diff --git a/plume_vulkan.cpp b/plume_vulkan.cpp +index 9103ca8..02c3591 100644 +--- a/plume_vulkan.cpp ++++ b/plume_vulkan.cpp +@@ -2112,6 +2112,12 @@ namespace plume { + fprintf(stderr, "vkCreateXlibSurfaceKHR failed with error code 0x%X.\n", res); + return; + } ++# elif defined(__APPLE__) && defined(SDL_VULKAN_ENABLED) ++ VulkanInterface *renderInterface = commandQueue->device->renderInterface; ++ if (!SDL_Vulkan_CreateSurface(renderWindow, renderInterface->instance, &surface)) { ++ fprintf(stderr, "SDL_Vulkan_CreateSurface failed: %s.\n", SDL_GetError()); ++ return; ++ } + # elif defined(__APPLE__) + assert(renderWindow.window != 0); + assert(renderWindow.view != 0); +@@ -2443,7 +2449,7 @@ namespace plume { + // The attributes width and height members do not include the border. + dstWidth = attributes.width; + dstHeight = attributes.height; +-# elif defined(__APPLE__) ++# elif defined(__APPLE__) && !defined(SDL_VULKAN_ENABLED) + CocoaWindowAttributes attributes; + windowWrapper->getWindowAttributes(&attributes); + dstWidth = attributes.width; +diff --git a/plume_vulkan.h b/plume_vulkan.h +index 73022bb..9d89adf 100644 +--- a/plume_vulkan.h ++++ b/plume_vulkan.h +@@ -22,8 +22,10 @@ + #define VK_USE_PLATFORM_XLIB_KHR + #elif defined(__APPLE__) + #define VK_USE_PLATFORM_METAL_EXT ++#ifndef SDL_VULKAN_ENABLED + #include "plume_apple.h" + #endif ++#endif + + // For VK_KHR_portability_subset + #define VK_ENABLE_BETA_EXTENSIONS +@@ -226,7 +228,7 @@ namespace plume { + VulkanCommandQueue *commandQueue = nullptr; + VkSurfaceKHR surface = VK_NULL_HANDLE; + RenderWindow renderWindow = {}; +-#if defined(__APPLE__) ++#if defined(__APPLE__) && !defined(SDL_VULKAN_ENABLED) + std::unique_ptr windowWrapper; + #endif + uint32_t textureCount = 0;