feat(sdk-flutter): add Swift Package Manager support to plugin_screeb - #19
Open
ScreebyBot wants to merge 5 commits into
Open
feat(sdk-flutter): add Swift Package Manager support to plugin_screeb#19ScreebyBot wants to merge 5 commits into
ScreebyBot wants to merge 5 commits into
Conversation
Flutter 3.44 makes SPM the default plugin package manager and CocoaPods is moving to maintenance-only, so plugin_screeb needs both to keep building for consumers. Reorganizes the iOS sources into the layout Flutter's plugin-authors guide requires (ios/plugin_screeb/Sources/plugin_screeb with public headers under include/plugin_screeb), adds the matching Package.swift wiring the native Screeb iOS SDK via its existing SPM distribution (pinned to 4.2.0, same as the podspec), and updates the podspec paths so CocoaPods installs keep working unchanged.
SwiftPM rejects mixed Swift/Objective-C targets below tools-version 6.5. The previous SPM target mixed PluginScreebPlugin.m/.h with SwiftPluginScreebPlugin.swift under swift-tools-version 5.9, so package resolution failed outright for any Flutter app on SwiftPM -- exactly the build failure this support was meant to prevent. Drops the Objective-C registration shim (which also relied on the plugin_screeb-Swift.h compatibility header SwiftPM does not generate for non-mixed targets) and renames the Swift plugin class to PluginScreebPlugin so it matches pubspec.yaml's existing ios.pluginClass directly, the same approach flutter/packages uses for its own Swift-only plugins. Also fixes scripts/sync-sdk-versions.mjs, which still pointed at the old ios/Classes/SwiftPluginScreebPlugin.swift path (broken by the prior SPM restructuring commit and failing `versions:check`), and wires the new Package.swift pin into the same release sync so the SPM and CocoaPods native SDK versions can't drift apart.
Address PR #19 review feedback: the committed example Podfile.lock still pinned Screeb 4.0.3 while the podspec/Package.swift require 4.2.0, which made `pod install` fail on a version conflict until a manual `pod update Screeb`. Bump the lockfile's PODS/SPEC CHECKSUMS to 4.2.0 (recomputed the plugin_screeb spec checksum from its current podspec; Screeb's remains whatever CocoaPods trunk publishes and self-corrects on the next install since it isn't a :path pod). Also give the SPM manifest a SCREEB_USE_LOCAL_SDK dev path so plugin authors aren't locked into CocoaPods to iterate on an unpublished native SDK change. Since a Package.swift manifest can't invoke xcodebuild the way the podspec's :path dependency can, it swaps in a local binaryTarget built ahead of time by the existing build-local-ios-xcframework.mjs script instead, documented alongside the other local-SDK flows in docs/screeb-team-release.md.
The local-SDK binaryTarget in Package.swift used a path relying on
`..` to reach a xcframework built at the monorepo root
(../../../../.local/ios/Screeb.xcframework). Flutter resolves a
plugin's Package.swift through a per-build symlink under
ios/Flutter/ephemeral/Packages/.packages/<plugin>-<version>, and
relative paths in the manifest resolve against that symlink's own
location, not the plugin's real path in this monorepo — confirmed by
reading flutter_tools' swift_package_manager.dart, which symlinks
FlutterFramework's own binaryTarget inside that same directory for
exactly this reason ("binary targets must be relative"). The old path
resolved to <app>/ios/Flutter/.local/ios/Screeb.xcframework, which the
documented build command never wrote to.
Move the artifact inside the plugin package itself
(plugin_screeb/Screeb.xcframework) and reference it with a `..`-free,
package-root-relative path, which resolves identically whether or not
it's read through the symlink. Update the documented build command and
.gitignore entry to match, and note that toggling SCREEB_USE_LOCAL_SDK
may need a `flutter clean` since SwiftPM caches manifest evaluation by
file content, not by environment. Also add a short SPM mention to the
public README, since nothing previously said the plugin supports it.
Known residual limitation carried over from the previous fix: the
Podfile.lock's Screeb (not plugin_screeb) SPEC CHECKSUM is still the
one computed for 4.0.3's podspec, not 4.2.0's — it can't be recomputed
without a real `pod install` on macOS, which isn't available here. This
doesn't block `pod install` (a stale checksum on a non-:path pod just
triggers a redownload, unlike the version conflict fixed previously),
but is a known gap to close with a real `pod install` before merge.
The Screeb SPEC CHECKSUM was still the one computed for the 4.0.3 podspec, even though the rest of the lockfile was bumped to 4.2.0, so `pod install` would still see the pod as changed and rewrite the line — the very lockfile/podspec desync the bump was meant to remove. Recomputed from the official trunk podspecs (CocoaPods/Specs, path Specs/6/8/c/Screeb/<version>/Screeb.podspec.json): 4.0.3 hashes to ddb9f7cca468c375406d607d949ffea34809d009, which is exactly the value that was committed here (and the one in example-reactnative's lockfile, which does still pin 4.0.3) — that match confirms the method — and 4.2.0 hashes to 38aabbcb171c850e1d30d4037c2a5fe7547c20ea. Every remaining checksum in the file was verified rather than assumed: plugin_screeb 27bafe69… is the sha1 of the current podspec and PODFILE CHECKSUM bbd322ee… is the sha1 of the current Podfile, both unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contexte
Flutter 3.44 (stable) fait de Swift Package Manager le gestionnaire de paquets iOS/macOS par défaut, et CocoaPods passe en maintenance avant dépréciation. Sans support SPM,
plugin_screebrisque des échecs de build sur les toolchains Flutter récentes. Demandé via l'issue GitHub #18 et une conversation Crisp (BetTube).Cette PR inclut le support SPM initial plus les corrections issues de la vérification manuelle iOS/Xcode de @MD4 et des relectures suivantes.
Changement
Support SPM (d'après le guide officiel Flutter) :
ios/plugin_screeb/Sources/plugin_screeb/, le layout attendu par l'outillage SPM, avecios/plugin_screeb/Package.swiftdéclarant le plugin en target de bibliothèque SPM, dépendant du SDK natif via sa distribution SPM existante (ScreebApp/sdk-ios-public,exact: "4.2.0"— même version que le podspec).PluginScreebPlugin.h/.m) est supprimé et la classe Swift renomméeSwiftPluginScreebPlugin→PluginScreebPluginpour matcher directement leios.pluginClassdupubspec.yaml. SwiftPM refuse les targets mixtes Swift/ObjC sous tools-version 6.5 : le target n'aurait pas pu être résolu du tout, soit exactement l'échec que ce ticket vise à éviter. C'est aussi ainsi queflutter/packageslivre ses propres plugins Swift.source_filesdu podspec mis à jour (Swift uniquement) : les installs CocoaPods continuent de fonctionner — les deux gestionnaires restent supportés pendant la transition.scripts/sync-sdk-versions.mjscorrigé (il pointait encore l'ancien cheminios/Classes/SwiftPluginScreebPlugin.swift, ce qui cassaitversions:checkdans le jobjsde la CI) et étendu pour synchroniser aussi le pinexact:duPackage.swift, afin que les versions natives SPM et CocoaPods ne puissent plus diverger.Corrections de revue :
examples/example-flutter/ios/Podfile.lockdésynchronisé (relevé par @MD4 :pod installéchouait en conflit de version). Le lockfile est maintenant exactement celui que produiraitpod install— chaque ligne vérifiée, pas supposée : versions à 4.2.0 ;plugin_screeb: 27bafe69…= sha1 du podspec courant ;PODFILE CHECKSUM: bbd322ee…= sha1 du Podfile courant ; etScreeb: 38aabbcb…recalculé depuis le podspec trunk officiel (CocoaPods/Specs,Specs/6/8/c/Screeb/4.2.0/Screeb.podspec.json). Méthode validée au passage : le podspec 4.0.3 hashe enddb9f7cc…, exactement la valeur qui était committée ici (et celle du lockfile d'example-reactnative, qui épingle bien encore la 4.0.3).Package.swifthonore le même switchSCREEB_USE_LOCAL_SDKque le podspec. Un manifeste SwiftPM ne pouvant pas invoquerxcodebuild, le chemin local passe par unbinaryTargetpointant un xcframework pré-construit via le script existantscripts/build-local-ios-xcframework.mjs(déjà utilisé par KMP/MAUI). L'artefact doit vivre dans le package (plugin_screeb/Screeb.xcframework, gitignoré), référencé par un chemin sans..: Flutter résout lePackage.swiftd'un plugin à travers un symlink par build (ios/Flutter/ephemeral/Packages/.packages/<plugin>-<version>, cf.xcode_project.dart/_createPluginSymlink), et les chemins relatifs se résolvent depuis ce symlink, pas depuis l'emplacement réel du plugin — c'est la raison pour laquelleFlutterFrameworkest lui-même symlinké dans le package (« binary targets must be relative »,swift_package_manager.dart). Documenté dansdocs/screeb-team-release.md, avec le caveat que SwiftPM met en cache l'évaluation du manifeste par contenu de fichier et non par environnement — basculerSCREEB_USE_LOCAL_SDKpeut nécessiter unflutter clean.packages/sdk-flutter/README.mdpublic (rien ne l'indiquait, hors doc interne de release).Aucun changement d'API Dart ni de
pubspec.yaml. Bump de version / entrée CHANGELOG volontairement omis : ce repo bumpe les versions liées au SDK natif via un commit de release automatisé séparé.Tests
node scripts/sync-sdk-versions.mjs --check: passe.flutter analyze(packages/sdk-flutter) : « No issues found! ».flutter test(packages/sdk-flutter) : 6/6 tests passés (comportement Dart inchangé).npm run lint(Lerna/eslint, gate du hook pre-commit) : passe — les warnings restants sont pré-existants et hors diff (sdk-browser).swift, et le jobflutterde la CI (.github/workflows/ci.yml) est Dart-only (pub get/analyze/test) — il ne build jamais iOS. En particulier, la brancheSCREEB_USE_LOCAL_SDK=trueduPackage.swiftn'est exercée par aucune gate et aucunswift build/flutter build iosn'a été lancé. Le correctif de chemin s'appuie sur la lecture directe des sourcesflutter_tools3.44.9 citées ci-dessus, et le lockfile sur des sha1 recalculés depuis les podspecs trunk officiels — mais une validation macOS/Xcode (pod installsans réécriture du lockfile + build SPM des deux modes) reste nécessaire.