mixin_logger: support Swift Package Manager on iOS#487
Conversation
Add an iOS Package.swift so Swift Package Manager projects no longer fall back to CocoaPods for this plugin (fixes the "does not support Swift Package Manager" warning). mixin_logger is an FFI plugin, so the shared C++ sources in src/ are reused via a forwarding source file under Sources/ (mirroring the existing CocoaPods Classes/ forwarder), and a copy of the public header is placed under include/ so the module header search path resolves mixin_logger/mixin_logger.h. The product is built as a dynamic library. Because Flutter references plugin products with underscores replaced by hyphens, the product is named mixin-logger and SPM produces mixin-logger.framework. The Dart library loader now accepts both the SPM framework name and the CocoaPods mixin_logger.framework name. Verified by building and running the example on the iOS simulator with Swift Package Manager enabled: the plugin builds via SPM, the app launches, and the FFI logger writes to file. Closes MixinNetwork#486 Claude-Session: https://claude.ai/code/session_01HUSXFyjL8e4u3nQCvynuod
There was a problem hiding this comment.
Pull request overview
Adds Swift Package Manager (SPM) support for the mixin_logger Flutter FFI plugin on iOS by introducing an iOS Package.swift and SPM-local forwarding sources/headers, plus a small Dart-side loader tweak so the correct dynamic framework name is found under both CocoaPods and SPM.
Changes:
- Add
ios/mixin_logger/Package.swiftand SPM target sources/headers to make the plugin resolvable via SPM on iOS. - Update Dart FFI loader to attempt both
mixin_logger.framework(CocoaPods) andmixin-logger.framework(SPM product naming). - Bump package version and document the change in the changelog.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/mixin_logger/pubspec.yaml | Bumps mixin_logger version to 0.1.4. |
| packages/mixin_logger/lib/src/write_to_file_ffi.dart | Tries both CocoaPods and SPM framework names when loading the iOS/macOS dynamic library. |
| packages/mixin_logger/ios/mixin_logger/Package.swift | Introduces the SPM package/product definition for iOS. |
| packages/mixin_logger/ios/mixin_logger/Sources/mixin_logger/mixin_logger.cpp | Adds an SPM-local forwarder that includes the shared implementation from src/. |
| packages/mixin_logger/ios/mixin_logger/Sources/mixin_logger/include/mixin_logger/mixin_logger.h | Adds an SPM-visible public header copy for the shared source includes. |
| packages/mixin_logger/CHANGELOG.md | Documents the new iOS SPM support in 0.1.4. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| platforms: [ | ||
| .iOS("12.0") | ||
| ], |
There was a problem hiding this comment.
Good catch — aligned the SPM minimum to iOS 11.0 to match mixin_logger.podspec. Fixed in d135200.
| for (final framework in const ['mixin_logger', 'mixin-logger']) { | ||
| try { | ||
| return DynamicLibrary.open('$framework.framework/$framework'); | ||
| } catch (_) { | ||
| continue; | ||
| } | ||
| } | ||
| throw UnsupportedError('Failed to load the $_libName dynamic library.'); |
There was a problem hiding this comment.
Agreed — the loader now preserves the last DynamicLibrary.open failure and includes the attempted framework paths in the thrown error. Fixed in d135200.
| @@ -0,0 +1,35 @@ | |||
| #include <stdint.h> | |||
There was a problem hiding this comment.
Leaving this as-is intentionally: this header is a verbatim copy of the canonical src/include/mixin_logger/mixin_logger.h, mirroring the existing ios/Classes/mixin_logger.h and macos/Classes/mixin_logger.h copies — none of which have an include guard. Adding #pragma once only to this SPM copy would make it diverge from the source of truth. Adding guards consistently would mean editing the shared canonical header used by every platform, which feels out of scope for this iOS SPM change; happy to do that in a separate PR if you'd prefer.
|
LGTM — thanks for adding Swift Package Manager support and for the thorough iOS/FFI verification! |
|
Addressed the review feedback in d135200:
Re-verified on the iOS simulator with SPM enabled after the changes: builds via SPM, app launches, and the FFI logger writes to file. |
Closes #486.
Adds an iOS
Package.swiftformixin_loggerso Swift Package Manager projects no longer fall back to CocoaPods and no longer emit:The CocoaPods podspec is left in place, so CocoaPods and SPM both work. Scope is iOS only, matching the issue; macOS is untouched.
What's included
ios/mixin_logger/Package.swift— a dynamic-library SPM package.ios/mixin_logger/Sources/mixin_logger/mixin_logger.cpp— a forwarding source that#includes the shared implementation insrc/, mirroring the existing CocoaPodsClasses/mixin_logger.cppforwarder (SPM, like CocoaPods, can't reference sources outside the package directory).ios/mixin_logger/Sources/mixin_logger/include/mixin_logger/mixin_logger.h— a copy of the public header. SPM automatically addsinclude/to the header search path, so the shared source's#include "mixin_logger/mixin_logger.h"resolves. This is the SPM equivalent of how CocoaPods' module header map resolves that include toClasses/mixin_logger.h.FFI / framework-naming note (why there's a Dart change)
mixin_loggeris an FFI plugin, and the Dart bindings load the native code from a dynamic framework, so the SPM product is built as a dynamic library.Flutter's generated
FlutterGeneratedPluginSwiftPackagereferences plugin products by the package name with underscores replaced by hyphens (.product(name: "mixin-logger", package: "mixin_logger")). The product must therefore be namedmixin-logger, and SPM names the built framework after the product —mixin-logger.framework/mixin-logger— whereas CocoaPods producesmixin_logger.framework/mixin_logger.The loader in
lib/src/write_to_file_ffi.dartpreviously hardcoded the CocoaPods name, so it now tries both framework names. The existing CocoaPods (and macOS) path is unaffected becausemixin_loggeris still tried first.Verification
Built and ran the example on the iOS simulator with SPM enabled (
flutter config --enable-swift-package-manager, Flutter 3.44.5):mixin_loggerno longer appears in the CocoaPodsPodfile.lock;mixin-logger.frameworkis produced with the FFI symbols exported (nm:T _mixin_logger_init,T _mixin_logger_write_log,T _mixin_logger_set_file_leading);[I] testinlog_0.log);flutter analyzeanddart formatare clean.https://claude.ai/code/session_01HUSXFyjL8e4u3nQCvynuod