Skip to content

Commit 2ea8bca

Browse files
committed
Merge PR #141: iOS support and renderer optimisations
2 parents 7a370e4 + 4c75426 commit 2ea8bca

43 files changed

Lines changed: 2739 additions & 102 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ios.yml‎

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
name: iOS builds
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
build:
14+
name: Build for iOS arm64
15+
runs-on: macos-26
16+
env:
17+
HOMEBREW_NO_AUTO_UPDATE: 1
18+
HOMEBREW_NO_INSTALL_CLEANUP: 1
19+
steps:
20+
- uses: actions/checkout@v7
21+
with:
22+
submodules: true
23+
24+
# FFmpeg's libraries are cross-compiled with Kazarov's pinned LGPL configuration.
25+
- name: Install the toolchain and libraries
26+
run: |
27+
brew install cmake ninja glslang
28+
rustup toolchain install stable --profile minimal
29+
rustup target add aarch64-apple-ios
30+
tools/ci/prebuilt-deps.sh ios-arm64
31+
32+
# SDL3 is required by kazarov and is not shipped as an iOS framework by Homebrew,
33+
# so cross-compile it for iOS arm64 into a local prefix the CMake configure can find.
34+
- name: Build SDL3 for iOS arm64
35+
run: |
36+
curl -L https://github.com/libsdl-org/SDL/archive/refs/tags/release-3.4.0.tar.gz \
37+
| tar xz -C "$RUNNER_TEMP"
38+
cmake -S "$RUNNER_TEMP/SDL-release-3.4.0" -B "$RUNNER_TEMP/sdl-ios-build" \
39+
-DCMAKE_SYSTEM_NAME=iOS \
40+
-DCMAKE_OSX_ARCHITECTURES=arm64 \
41+
-DCMAKE_OSX_SYSROOT=iphoneos \
42+
-DCMAKE_OSX_DEPLOYMENT_TARGET=16.3 \
43+
-DCMAKE_C_COMPILER=clang \
44+
-DCMAKE_CXX_COMPILER=clang++ \
45+
-DCMAKE_BUILD_TYPE=Release \
46+
-DCMAKE_INSTALL_PREFIX="$RUNNER_TEMP/sdl-ios" \
47+
-DSDL_STATIC=ON \
48+
-DSDL_SHARED=OFF \
49+
-DSDL_TESTS=OFF \
50+
-DSDL_EXAMPLES=OFF
51+
cmake --build "$RUNNER_TEMP/sdl-ios-build" --config Release -j"$(sysctl -n hw.ncpu)"
52+
cmake --install "$RUNNER_TEMP/sdl-ios-build" --config Release
53+
echo "SDL3_PREFIX=$RUNNER_TEMP/sdl-ios" >> "$GITHUB_ENV"
54+
55+
# Homebrew's molten-vk is a macOS dylib; the iOS static library and its Vulkan headers come from the
56+
# MoltenVK release.
57+
- name: Fetch MoltenVK for iOS
58+
run: |
59+
curl -L https://github.com/KhronosGroup/MoltenVK/releases/download/v1.4.2/MoltenVK-ios.tar \
60+
| tar x -C "$RUNNER_TEMP"
61+
lib=$(find "$RUNNER_TEMP/MoltenVK" -path '*/static/MoltenVK.xcframework/ios-arm64/libMoltenVK.a' | head -n1)
62+
header=$(find "$RUNNER_TEMP/MoltenVK" -path '*/include/vulkan/vulkan.h' | head -n1)
63+
test -n "$lib" && test -n "$header"
64+
echo "MOLTENVK_LIBRARY=$lib" >> "$GITHUB_ENV"
65+
echo "VULKAN_INCLUDE_DIR=$(dirname "$(dirname "$header")")" >> "$GITHUB_ENV"
66+
67+
- name: Configure for iOS
68+
run: |
69+
cmake --preset ios-arm64-release \
70+
-DSDL3_DIR="$SDL3_PREFIX/lib/cmake/SDL3" \
71+
-DVulkan_INCLUDE_DIR="$VULKAN_INCLUDE_DIR" \
72+
-DVulkan_LIBRARY="$MOLTENVK_LIBRARY" \
73+
-DRust_CARGO_TARGET=aarch64-apple-ios \
74+
-DCT_BUILD_TESTS=OFF
75+
76+
- name: Build for iOS
77+
# Cargo's C builds (zstd, cxx, the movie muxer) otherwise target the SDK's own iOS version, not the app's.
78+
# Only here: FFmpeg's configure would build its host tools for iOS too and could not run them.
79+
env:
80+
IPHONEOS_DEPLOYMENT_TARGET: "16.3"
81+
# -k 0 reports every unit that fails, not only the first.
82+
run: cmake --build port/build/ios-arm64-release --target darkchronicle -j"$(sysctl -n hw.ncpu)" -- -k 0
83+
84+
# The .ipa is unsigned: a sideloading tool (Sideloadly, AltStore) signs it with the installer's Apple ID.
85+
# The button symbols and the gameplay seed (assets/data.zip) go inside the bundle, which is where the game
86+
# looks beside its executable.
87+
- name: Package the .ipa
88+
run: |
89+
build=port/build/ios-arm64-release
90+
mkdir -p "$RUNNER_TEMP/ipa/Payload"
91+
cp -R "$build/darkchronicle.app" "$RUNNER_TEMP/ipa/Payload/"
92+
# The split debug symbols would double the download; they are no part of the app.
93+
rm -rf "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/darkchronicle.dSYM"
94+
cp -R "$build/glyphs" "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/"
95+
# The Luau scripts the events run, which the game finds in scripts/ beside its executable.
96+
cp -R "$build/scripts" "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/"
97+
test -n "$(find "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/scripts" -name '*.luau' | head -n1)"
98+
# Each one with its bytecode, so the device does not compile them (CT_LUAU_PRECOMPILE).
99+
test -n "$(find "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/scripts" -name '*.luauc' | head -n1)"
100+
mkdir -p "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/assets"
101+
cp "$build/assets/data.zip" "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/assets/"
102+
# The home screen icon, which SideStore and LiveContainer also show.
103+
sips -z 120 120 port/assets/icon/chronicletwo-512.png --out "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/AppIcon60x60@2x.png"
104+
sips -z 180 180 port/assets/icon/chronicletwo-512.png --out "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/AppIcon60x60@3x.png"
105+
# A quick check of what sideloading and LiveContainer need: an arm64, position-independent executable.
106+
file "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/darkchronicle"
107+
otool -hv "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/darkchronicle" | grep -q PIE
108+
otool -l "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/darkchronicle" | grep -A4 LC_BUILD_VERSION
109+
# libc++ symbols newer than the minimum iOS kill the app in dyld before main. std::pmr (iOS 17) slipped in
110+
# once, and iOS 16.3.1 has no floating-point std::to_chars although the headers say 16.3.
111+
if nm -u "$RUNNER_TEMP/ipa/Payload/darkchronicle.app/darkchronicle" | grep -E '__ZNSt3__1(3pmr|8to_chars)'; then
112+
echo "the executable imports libc++ symbols that iOS 16 lacks" >&2
113+
exit 1
114+
fi
115+
(cd "$RUNNER_TEMP/ipa" && zip -qry "$GITHUB_WORKSPACE/DarkChronicle.ipa" Payload)
116+
117+
- name: Upload the .ipa
118+
uses: actions/upload-artifact@v7
119+
with:
120+
name: DarkChronicle-ios-arm64
121+
path: DarkChronicle.ipa
122+
if-no-files-found: error
123+
124+
# The symbols stay out of the .ipa but are kept to read the addresses in a device's stack reports.
125+
- name: Upload the debug symbols
126+
uses: actions/upload-artifact@v7
127+
with:
128+
name: DarkChronicle-ios-arm64-dSYM
129+
path: port/build/ios-arm64-release/darkchronicle.app/darkchronicle.dSYM
130+
if-no-files-found: warn

‎CMakePresets.json‎

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,47 @@
8080
"cacheVariables": {
8181
"CMAKE_BUILD_TYPE": "Release"
8282
}
83+
},
84+
{
85+
"name": "ios",
86+
"hidden": true,
87+
"inherits": "pc",
88+
"condition": {
89+
"type": "equals",
90+
"lhs": "${hostSystemName}",
91+
"rhs": "Darwin"
92+
},
93+
"cacheVariables": {
94+
"CMAKE_CXX_COMPILER": "clang++",
95+
"CMAKE_C_COMPILER": "clang",
96+
"CMAKE_SYSTEM_NAME": "iOS",
97+
"CMAKE_SYSTEM_PROCESSOR": "arm64",
98+
"CMAKE_OSX_ARCHITECTURES": "arm64",
99+
"CMAKE_OSX_SYSROOT": "iphoneos",
100+
"CMAKE_MACOSX_BUNDLE": "OFF",
101+
"CMAKE_OSX_DEPLOYMENT_TARGET": "16.3",
102+
"CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH": "NO",
103+
"CMAKE_CXX_FLAGS": "-D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES",
104+
"CT_BUILD_TESTS": "OFF"
105+
}
106+
},
107+
{
108+
"name": "ios-arm64",
109+
"displayName": "iOS arm64, Debug",
110+
"inherits": "ios",
111+
"binaryDir": "${sourceDir}/port/build/ios-arm64",
112+
"cacheVariables": {
113+
"CMAKE_BUILD_TYPE": "Debug"
114+
}
115+
},
116+
{
117+
"name": "ios-arm64-release",
118+
"displayName": "iOS arm64, Release",
119+
"inherits": "ios",
120+
"binaryDir": "${sourceDir}/port/build/ios-arm64-release",
121+
"cacheVariables": {
122+
"CMAKE_BUILD_TYPE": "Release"
123+
}
83124
}
84125
],
85126
"buildPresets": [
@@ -132,4 +173,4 @@
132173
"configurePreset": "macos-arm64-release"
133174
}
134175
]
135-
}
176+
}

0 commit comments

Comments
 (0)