Skip to content

Remove use of modulemaps in flutter/packages when using SwiftPM #148572

@vashworth

Description

@vashworth

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:

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;
#endif

Prototype

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listplatform-iosiOS applications specificallyplatform-macBuilding on or for macOS specificallyteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions