I have implemented full Swift Package Manager (SPM) support for the printing package on iOS and macOS, following the official Flutter guidelines and addressing the limitations of mixed-language targets in SPM.
I created printing/ios/Package.swift and printing/macos/Package.swift. These manifests define the library targets and dependencies.
The printing plugin originally used a mixed Objective-C (PrintingPlugin.m) and Swift (PrintingPlugin.swift) codebase in the same target.
- Problem: Swift Package Manager strictly prohibits mixed language sources in a single target unless they are separated into distinct targets with public headers, which adds complexity and potential linking issues for existing plugins.
- Solution: I utilized the
@_cdeclattribute in Swift to expose the C-compatible symbols directly from the Swift code, effectively removing the need forPrintingPlugin.mwhen building with SPM.
-
Modified
PrintingPlugin.swift(iOS & macOS):- Added
@_cdeclwrapper functions (net_nfet_printing_set_document,net_nfet_printing_set_error) at the end of the file. - Wrapped these functions in
#if SPM_BUILDto ensure they are only compiled when building with SPM. This prevents duplicate symbol errors for CocoaPods builds (which still compilePrintingPlugin.m).
- Added
-
Updated
Package.swift(iOS & macOS):- Added
exclude: ["PrintingPlugin.m"]to the target definition. This ensures the Objective-C file is ignored by SPM, allowing the target to be pure Swift. - Added
swiftSettings: [.define("SPM_BUILD")]to define the compilation flag that enables the@_cdeclwrappers.
- Added
I verified the changes locally by:
- Creating a clean Flutter app (
test_spm_app). - Configuring it to depend on the local
printingpackage path. - Enabling SPM in Flutter config (
flutter config --enable-swift-package-manager). - Successfully building the app for both iOS (
flutter build ios --no-codesign) and macOS (flutter build macos). - Verifying that
swift package describeruns successfully on the package manifests.
- The current implementation maintains full backward compatibility with CocoaPods (which uses
PrintingPlugin.mand ignores the#if SPM_BUILDblock). - Future cleanup: Once CocoaPods support is dropped (if ever),
PrintingPlugin.mcan be removed entirely, and the@_cdeclwrappers can be made unconditional.