Entwickler

iOS-App selbst bauen mit Xcode

Die IPA des TRS Launchers für iPhone und iPad auf dem Mac bauen: Xcode-Projekt, Rust-Bibliothek, Spiel-Engine, Sideloading und Start mit eigener Apple-ID.

Die iOS-App ist dasselbe Tauri-2-Projekt wie der Launcher auf dem PC, nur für iPhone und iPad gebaut. Diese Seite ist für alle, die mitentwickeln, und für Spieler, die die IPA lieber selbst bauen als unsere zu nehmen. Wenn du nur spielen willst, installier die offizielle App – siehe iPhone/iPad: mit AltStore/SideStore installieren.

Bevor du loslegst:
  • Du brauchst einen Mac mit Xcode. Das Xcode-Projekt lässt sich nur unter macOS erzeugen und liegt deshalb nicht im Repository – ein Skript legt es an.
  • Zum Spielen braucht es die Spiel-Engine und JIT – genau wie bei der offiziellen App. Die Engine kommt in einem eigenen Schritt in die fertige App (siehe IPA bauen). Startest du die App direkt aus Xcode, fehlt die Engine: Alles andere geht, aber Spiele starten nicht.
  • Apps, die mit einer kostenlosen Apple-ID signiert sind, öffnen sich nach 7 Tagen nicht mehr und müssen neu signiert (aufgefrischt) werden. Mit einer kostenlosen Apple-ID gehen nur 3 selbst installierte Apps gleichzeitig.
  • Gebaut wird nur für echte Geräte (arm64) – einen Build für den iOS-Simulator gibt es nicht.

Die Befehle hier sind die, die das CI ausführt (.github/workflows/ci.yml Job launcher-ios, release.yml Jobs iOS und iOS engine, .github/workflows/ios-engine.yml). Das CI signiert die App nie – es baut eine unsignierte IPA, und AltStore/SideStore signieren sie beim Installieren mit der Apple-ID des Nutzers.

Was wo liegt

PfadWas es ist
scripts/ios-project.shLegt das Xcode-Projekt in src-tauri/gen/apple an (tauri ios init) und ergänzt Symbole und Info.plist-Einträge
scripts/ios-unsigned-ipa.shBaut die Rust-Bibliothek, dann ein Xcode-Archiv ohne Code-Signatur, als IPA gezippt
scripts/ios/build-engine.shBaut die Spiel-Engine (Amethyst-iOS an festem Commit, CMake, MobileGlues, Java-Teil)
scripts/ios/package-ipa.shLegt die Engine in die App und signiert sie mit ldid und den Entitlements
src-tauri/tauri.ios.conf.jsoniOS-Abweichungen der Tauri-Konfiguration (iOS 15, kein Desktop-Updater)
src-tauri/Info.ios.plistKamera-Text (QR-Code der PC-Fernbedienung) und Hintergrundabruf für Benachrichtigungen
src-tauri/plugins/tauri-plugin-trs-game/ios/Swift-Teil, Quellen der Engine, trs-game.entitlements

Voraussetzungen

WerkzeugVersion / Hinweis
macOS mit Xcodemit dem iPhoneOS-SDK. Eine Xcode-Version ist im Repository nicht festgelegt; das CI nimmt das Standard-Xcode der GitHub-Runner macos-latest (App) und macos-15 (Engine)
Homebrewfür xcodegen (installiert das Skript bei Bedarf selbst), ldid und cmake
Node.js und pnpmNode 22, pnpm in der Version aus package.json (corepack enable)
Ruststable über rustup, Target aarch64-apple-ios
JDK 8nur für die Engine (CI: Zulu 8). Es muss ein JDK 8 sein – build-engine.sh prüft das
git, python3, zipnutzen die Skripte

Die App braucht iOS 15 (minimumSystemVersion in tauri.ios.conf.json). Das CI setzt für die App IPHONEOS_DEPLOYMENT_TARGET=15.0, weil die Swift-Pakete der Plugins APIs ab iOS 14 nutzen; die Engine selbst wird für 14.0 gebaut.

IPA bauen

Code und Werkzeuge holen

git clone https://github.com/theredstonee/TRS-Launcher.git
cd TRS-Launcher
pnpm install
rustup target add aarch64-apple-ios
brew install ldid cmake

Oberfläche bauen

pnpm generate

Xcode-Projekt anlegen

bash scripts/ios-project.sh

Das Skript startet pnpm tauri ios init --ci, falls src-tauri/gen/apple noch fehlt, übernimmt Kamera-Text und Hintergrundaufgabe aus src-tauri/Info.ios.plist in die Info.plist der App und legt die App-Symbole (dazu die Event-Symbole als alternative Symbole) in den Asset-Katalog.

App ohne Signatur bauen

export IPHONEOS_DEPLOYMENT_TARGET=15.0
bash scripts/ios-unsigned-ipa.sh release build/TRS-Launcher-app.ipa

Was dabei passiert:

  1. cargo build --lib --target aarch64-apple-ios --release --features tauri/custom-protocol, mit TAURI_CONFIG = Inhalt von tauri.ios.conf.json. Das Feature custom-protocol bettet die Oberfläche ein – ohne sucht die App einen Entwicklungsserver auf localhost:3000 und schließt sich sofort wieder.
  2. Die Bibliothek libtrs_launcher_lib.a wird nach src-tauri/gen/apple/Externals/arm64/release/libapp.a kopiert.
  3. scripts/ios/disable-rust-phase.py schaltet die Xcode-Build-Phase „Build Rust Code“ (tauri ios xcode-script) ab – sie funktioniert nur innerhalb eines laufenden tauri ios build, und die Bibliothek liegt ja schon da.
  4. xcodebuild … archive mit CODE_SIGNING_ALLOWED=NO, danach wird die .app als Payload/ in die IPA gezippt.

Für einen Debug-Build nimmst du debug statt release (die Bibliothek landet dann in Externals/arm64/debug/). Für CurseForge setzt du CURSEFORGE_API_KEY oder legst den Schlüssel in ~/.tauri/curseforge-api-key – freiwillig, ohne ihn ist CurseForge ausgeblendet.

Spiel-Engine bauen

JAVA8_HOME=$(/usr/libexec/java_home -v 1.8) bash scripts/ios/build-engine.sh build/engine-ios

Das Skript holt Amethyst-iOS am festen Commit 9212a1894865e7ac0466029e25ddb0d895544c76, vergleicht die mitgelieferten Dateien damit, baut die native Engine und MobileGlues mit CMake und den Java-Teil mit dem JDK 8. Heraus kommt ein Ordner mit Frameworks/, libs/, resources/, LICENSES/ und engine.json. Die Java-Laufzeiten sind nicht dabei – die lädt die App beim ersten Spielstart.

Engine in die App legen

bash scripts/ios/package-ipa.sh build/TRS-Launcher-app.ipa build/engine-ios build/TRS-Launcher.ipa

Das kopiert die Engine in die App, ergänzt die Info.plist-Einträge für die Dateien-App, das Querformat, Maus und Controller und signiert alles mit ldid – die App mit den Entitlements aus src-tauri/plugins/tauri-plugin-trs-game/ios/trs-game.entitlements (get-task-allow für JIT, das höhere Speicherlimit und der große Adressraum). Eine andere Datei gibst du mit TRS_IOS_ENTITLEMENTS an.

Installieren

Kopier build/TRS-Launcher.ipa auf dein iPhone oder iPad und installier sie in AltStore oder SideStore über My Apps → +. Sie signieren sie mit deiner Apple-ID, wie die offizielle App. Andere Werkzeuge, die eine IPA mit deiner Apple-ID signieren, sollten auch gehen – getestet haben wir sie nicht. Zum Spielen dann JIT einschalten.

Wenn AltStore/SideStore die App mit einer kostenlosen Apple-ID neu signieren, fallen die beiden Speicher-Entitlements meist weg. Die App prüft zur Laufzeit, was sie wirklich hat, und wählt den Java-Speicher danach – das Spiel bekommt dann weniger Speicher als mit TrollStore.

Aus Xcode mit eigener Apple-ID starten

Du kannst die App auch direkt aus Xcode auf einem angeschlossenen iPhone starten und mit deinem eigenen Team signieren (eine kostenlose Apple-ID geht als „Personal Team“). Das ist praktisch, wenn du an der Oberfläche arbeitest. Zwei Dinge dazu:

  • Auf diesem Weg hat die App keine Spiel-Engine – beim Start einer Instanz meldet sie, dass die Engine fehlt. Anmeldung, Sozial, Garderobe, Modpacks und alles andere funktionieren.
  • Das CI signiert nie mit einem Team – diesen Weg haben wir nicht getestet.

Rust-Bibliothek für Debug bauen

Mach die Schritte bis Xcode-Projekt anlegen, dann:

export IPHONEOS_DEPLOYMENT_TARGET=15.0
bash scripts/ios-unsigned-ipa.sh debug build/TRS-Launcher-debug.ipa

Danach liegt die Bibliothek in src-tauri/gen/apple/Externals/arm64/debug/libapp.a, und die Rust-Build-Phase im Projekt ist abgeschaltet – Xcode kann die App also allein bauen.

Projekt öffnen

open src-tauri/gen/apple/*.xcodeproj

Wähle das Schema, das auf _iOS endet, und dein iPhone als Ziel.

Team und Bundle-ID setzen

Im App-Target unter Signing & Capabilities wählst du dein Team und änderst den Bundle Identifier in einen eigenen (zum Beispiel io.github.deinname.trslauncher) – eine Bundle-ID kann bei Apple nur ein Team verwenden.

Starten

Drück Run. Ab iOS 16 fragt das iPhone zuerst nach dem Entwicklermodus (Einstellungen → Datenschutz & Sicherheit → Entwicklermodus). Mit einer kostenlosen Apple-ID musst du eventuell noch dein Entwicklerprofil unter Einstellungen → Allgemein → VPN und Geräteverwaltung als vertrauenswürdig markieren.

Die Signatur-Einstellungen aus Xcode stehen im erzeugten Projekt. Löschst du src-tauri/gen/apple und legst es neu an, sind sie weg.

Zu deiner eigenen App machen

  • Bundle-ID: AltStore/SideStore signieren die IPA mit deiner Apple-ID – dafür musst du nichts ändern. Für Xcode änderst du die Bundle-ID dort (siehe oben).
  • identifier in src-tauri/tauri.conf.json nicht ändern. Er gilt auch für Android, wo das Kotlin-Paket und der Rust-Code daran hängen – der Android-Build bricht dann ab (siehe Android-App selbst bauen). Ein identifier nur für iOS in tauri.ios.conf.json könnte gehen, ist aber nicht getestet.
  • Die ID der Hintergrundaufgabe dev.theredstonee.trslauncher.push-poll bleibt, wie sie ist: Sie steht sowohl in src-tauri/Info.ios.plist als auch im Swift-Code des Push-Plugins, und iOS führt nur Aufgaben aus, die in der Info.plist stehen.

Was in deinem eigenen Build laut Code weiter funktioniert:

  • Microsoft-Anmeldung läuft per Gerätecode (du tippst einen Code auf der Microsoft-Seite ein) – sie hängt nicht an der Bundle-ID.
  • TRS-Dienste (Freunde, Chat, Umhänge, TRS-API) sprechen mit derselben API; App oder Signatur werden nicht geprüft.
  • Links wie trs-launcher://pack/<code> haben in jedem Build dasselbe Schema.
  • Updates: Dein Build hängt nicht an unserer AltStore-/SideStore-Quelle. Du aktualisierst ihn, indem du neu baust und installierst.

Wenn in deinem eigenen Build etwas nicht geht, melde es bitte.

Prüfungen ausführen

Dieselben Prüfungen wie im CI:

pnpm generate
cd src-tauri
IPHONEOS_DEPLOYMENT_TARGET=15.0 cargo clippy --workspace --target aarch64-apple-ios -- -D warnings
# Spiel-Plugin für iOS, Rust und sein Swift-Paket (Job „iOS engine“):
IPHONEOS_DEPLOYMENT_TARGET=14.0 cargo build -p tauri-plugin-trs-game --target aarch64-apple-ios

Probleme

„Build-Phase tauri ios xcode-script nicht gefunden“

scripts/ios-unsigned-ipa.sh schaltet diese Build-Phase beim ersten Lauf ab – ein zweiter Lauf findet sie nicht mehr und bricht mit dieser Meldung ab. Das CI fängt immer mit einem frischen Projekt an. Lokal löschst du das erzeugte Projekt und legst es neu an:

rm -rf src-tauri/gen/apple
bash scripts/ios-project.sh

Fehler zum Deployment Target oder zu iOS-14-APIs

Setz IPHONEOS_DEPLOYMENT_TARGET=15.0, bevor du die App baust (14.0 für die Prüfung des Engine-Plugins) – die Swift-Pakete brauchen mindestens iOS 14.

Die App schließt sich gleich nach dem Öffnen

Wenn du die Rust-Bibliothek von Hand gebaut hast, fehlt wahrscheinlich --features tauri/custom-protocol – dann wartet die App auf einen Entwicklungsserver auf localhost:3000. Nimm scripts/ios-unsigned-ipa.sh, das setzt es immer.

„JDK 8 fehlt (JAVA8_HOME setzen)“ oder „JAVA8_HOME ist kein JDK 8“

Der Java-Teil der Engine braucht genau ein JDK 8. Installier eins und lass JAVA8_HOME darauf zeigen.

„ldid fehlt (brew install ldid)“

package-ipa.sh signiert mit ldid: brew install ldid.

„vendored Datei weicht von Upstream ab“

Eine Datei unter ios/Engine/vendor/amethyst-ios weicht vom festen Amethyst-iOS-Commit ab. Abweichen dürfen nur die gepatchten Dateien, die in UPSTREAM.md in diesem Ordner stehen – mach deine Änderung rückgängig oder pass die Liste an.

Das Spiel schließt sich gleich nach dem Start

Fast immer ist JIT nicht an. Siehe JIT einschalten. Das Log der Engine findest du in der Dateien-App unter Auf meinem iPhone → TRS Launcher (trs-engine.log).

Minecraft 26.3 startet nicht

26.3 läuft auf iOS noch nicht (der Engine fehlt dort die SDL3-Anbindung). Nimm 26.2 oder älter.

„App kann nicht überprüft werden“ nach einer Woche

Die 7 Tage der kostenlosen Apple-ID sind um. Frisch die App in AltStore/SideStore auf oder starte sie noch einmal aus Xcode.

Lizenz und Name

Der TRS Launcher ist freie Software unter der GNU General Public License v3.0 (LICENSE, Urheberrechtshinweise in NOTICE). Du darfst die App bauen, ändern und weitergeben. Gibst du eine IPA weiter, verlangt die GPL, dass das unter derselben Lizenz passiert und du den vollständigen Quellcode genau dieses Builds samt deiner Änderungen zugänglich machst. Die iOS-Engine basiert auf Amethyst-iOS (GPL-3.0) und bringt weitere fremde Teile mit; ihre Lizenztexte liegen in der App (licenses/engine) und stehen in NOTICE – lass sie drin.

Eigene Markenregeln hat das Repository nicht. Trotzdem: Wenn du deinen Build weitergibst, gib ihm einen eigenen Namen und eine eigene Bundle-ID, damit ihn niemand für den offiziellen TRS Launcher hält, und verweise auf deinen Quellcode – nicht auf unseren Support.

Weiter geht's

Android-App selbst bauen

Die APK mit deinem eigenen Signierschlüssel – unter Windows und Linux.

iPhone & iPad

Die offizielle App mit AltStore oder SideStore installieren.