-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Use case
To support both CocoaPods and Swift Package Manager, dynamic and static linking, two different modulemaps are needed.
CocoaPods modulemap
CocoaPods seems to require the modulemap be a framework module and doesn't use relative paths.
For example,
framework module plugin_name_ios {
umbrella header "plugin_name_ios-umbrella.h"
export *
module * { export * }
explicit module Test {
header "PublicHeader_Test.h"
header "OtherPublicHeader_Test.h"
}
}SwiftPM modulemap
SwiftPM requires the modulemap to be named module.modulemap and be located within the include directory. It also doesn't seem to work if defined as a framework module and uses relative paths.
For example,
- framework module plugin_name_ios {
+ module plugin_name_ios {
explicit module Test {
- header "PublicHeader_Test.h"
+ header "plugin_name_ios/OtherPublicHeader_Test.h"The problem
The problem is that when you have two modulemaps (most likely also because one is named module.modulemap, which is the implicit modulemap file), this can cause issues:
- Lexical or Preprocessor Issue (Xcode): Redefinition of module 'image_picker_ios' #148307
- https://gist.github.com/loic-sharma/27bd8e3ea0d9ab16cd4b8de03918ec4d
Proposal
It's been pretty difficult to figure out a way to support both CocoaPods and SwiftPM modulemaps. As a result, we're leaning towards eliminating modulemaps in SwiftPM.
Instead of using a modulemap and umbrella header for the SwiftPM integration of plugins, we simply allow all public headers to be available via @import plugin_name_ios.
@import plugin_name_ios;
- @import plugin_name_ios.Test;The headers are already public and could be imported individually (like #import <plugin_name_ios/PublicHeader_Test.h>), so making them available through the module isn't much worse.
Modulemap and umbrella header should be excluded from SwiftPM target:
.target(
name: "plugin_name_ios",
dependencies: [],
+ exclude: ["cocoapods_plugin_name_ios.modulemap", "plugin_name_ios-umbrella.h"],Unit tests can also be kept compatible with both CocoaPods and SwiftPM with something like:
#if __has_include(<plugin_name_ios/plugin_name_ios-umbrella.h>)
@import plugin_name_ios.Test;
#endifPrototype
flutter/packages@main...vashworth:packages:camera_avfoundation_remove_swiftpm_modulemap
Re-adding SwiftPM .modulemaps
Once the ecosystem has migrated to SwiftPM, we will remove support for CocoaPods. At this point, we should consider re-adding module.modulemaps to the plugins' SwiftPM integration. This step might not be necessary as we plan to rewrite plugins in Swift.