Aller au contenu principal

Spécificités Flutter iOS

Sur iOS, les politiques de sécurité du noyau XNU d'Apple interdisent le chargement dynamique de nouvelles pages mémoire exécutables non signées par Apple (MAP_JIT restreint). Pour permettre la mise à jour à chaud tout en respectant les règles de l'App Store, le moteur iOS de Shorebird/TkushPatch utilise un exécuteur hybride AOT + interpréteur (artefact de patch).

1. Architecture iOS : App.framework, diff_base et artefact de patch​

Cycle de distribution sur iOS
  1. Création de la release : Compilation de l'IPA avec tk-ota-push release -p ios et publication sur TestFlight ou l'App Store.
  2. Création d'un patch : Compilation du correctif avec tk-ota-push patch -p ios.
  3. Vérification et exécution : Le moteur Flutter charge le correctif scellé au lancement de l'application.

Ce qui se passe lors de tk-ota-push release -p ios (Publisher.releaseIos)​

  1. La CLI compile l'application en mode Release (flutter build ios --release ou flutter build ipa --release si --artifact ipa).
  2. Elle résout de manière déterministe le bundle Runner.app (dans build/ios/archive/Runner.xcarchive pour un IPA ou build/ios/iphoneos/ pour un build standard) et vérifie la présence de Frameworks/App.framework/App.
  3. Elle sauvegarde une copie locale de référence dans .ota_ios_release_cache/<version>/ :
    • Runner.app (bundle signé intact)
    • App (binaire Mach-O AOT de base)
    • supplement/ (fichiers de table de liaison App.*.link, App.*_table.json, App.dd_resolution.tsv)
  4. Elle exécute aot_tools dump_blobs avec analyze_snapshot_arm64 sur App pour extraire diff_base (les blobs de snapshot Dart), et scelle diff_base sur le serveur OTA.

Ce qui se passe lors de tk-ota-push patch -p ios (Publisher.patchIos)​

  1. Vérification anti-crash de cohérence du cache : la CLI calcule le SHA-256 de .ota_ios_release_cache/<version>/diff_base et le compare au baseSha256Hash verrouillé sur le serveur. En cas de divergence (MISMATCH DE HASH iOS), la génération est immédiatement interrompue pour éviter tout crash (Segfault) sur les iPhones.
  2. Compilation du noyau Dart (app.dill) : lance flutter build ios --release --no-codesign.
  3. Génération du snapshot ELF (out.aot) : exécute gen_snapshot_arm64 avec --deterministic --snapshot-kind=app-aot-elf et les arguments DWARF alignés (--dwarf-stack-traces, --resolve-dwarf-paths, --save-debugging-info=..., --strip).
  4. Liaison (aot_tools link) : lie le binaire de base App et le nouveau snapshot out.aot pour produire artefact de patch. Le code inchangé par rapport à la Release continue de tourner à vitesse native sur le CPU ARM64, tandis que seules les fonctions Dart modifiées sont interprétées par le moteur embarqué.
  5. Restauration du bundle signé : restaure .ota_ios_release_cache/<version>/Runner.app dans build/ios/iphoneos/Runner.app (car --no-codesign avait écrasé la signature).
Conservation du dossier .ota_ios_release_cache/<version>

Sur iOS, aot_tools link a obligatoirement besoin du binaire Mach-O App et des fichiers supplement/ générés lors de la Release initiale pour calculer les tables de dispatch de artefact de patch. Conservez ou archivez en CI/CD le répertoire .ota_ios_release_cache/<version>/ pendant toute la durée de vie de la Release en production.

2. Formats d'artefacts iOS (.ipa vs .app) et méthodes d'exportation​

La CLI supporte la génération directe d'archives .ipa signées via les options --artifact ipa, --export-method et --export-options-plist :

Option CLIValeurs supportéesUsage
--artifact ipaipa (ou ios par défaut)Exécute flutter build ipa --release et extrait Runner.app depuis build/ios/archive/Runner.xcarchive.
--export-methodapp-store, ad-hoc, enterprise, developmentTransmet --export-method=<methode> à flutter build ipa.
--export-options-plistChemin vers un fichier .plistTransmet --export-options-plist=<path> à flutter build ipa pour une configuration Xcode personnalisée.

Exemples de commandes iOS​

# Release iOS destinée à TestFlight / App Store Connect
tk-ota-push release -p ios --artifact ipa --export-method app-store

# Release iOS Ad-Hoc pour distribution interne sur iPhones de test enregistrés (UDID)
tk-ota-push release -p ios --artifact ipa --export-method ad-hoc

# Publication d'un patch iOS sur la Release active
tk-ota-push patch -p ios -m "Correctif validation biométrique"

3. Garde-fou d'intégrité native iOS (NativeIntegrityScanner.scanIosApp)​

Comme sur Android, un patch OTA iOS ne peut pas modifier le code Swift/Objective-C ni les frameworks natifs signés par Apple.

NativeIntegrityScanner.scanIosApp(Directory appDir) (lib/src/cli/native_integrity.dart) calcule une empreinte SHA-256 déterministe sur :

  • Info.plist
  • Le binaire exécutable Mach-O principal à la racine de Runner.app
  • Tous les fichiers présents sous Frameworks/, à l'exclusion stricte de Frameworks/App.framework (qui contient le code Dart).

Si une modification de Info.plist, d'un Pod CocoaPods ou du code Swift est détectée lors d'un patch, la CLI bloque la publication et demande une nouvelle Release Store.

4. Conformité Apple (App Store Review Guidelines)​

L'architecture iOS de TkushPatch respecte les exigences d'Apple :

  • Aucun code natif Mach-O exécutable n'est téléchargé ni mappé avec la permission PROT_EXEC après l'installation.
  • Les fonctions inchangées utilisent les instructions machine déjà présentes et signées par Apple dans App.framework/App lors de la soumission App Store.
  • Les fonctions modifiées dans artefact de patch sont exécutées par l'interpréteur Dart intégré au moteur C++, sans compilation JIT.
  • Toute mise à jour est signée par signature numérique et vérifiée par le moteur Rust (patch_verification: strict).