Skip to content

[SwiftPM] ☂ Allow Swift Package Manager to be used with Add to App #146957

@vashworth

Description

@vashworth

Design

To support SwiftPM plugins in add-to-app, we plan to introduce a new command that creates a swift package (called FlutterPluginRegistrant) that can be added to a native iOS or macOS Xcode project.

The FlutterPluginRegistrant will have dependencies on Flutter plugins, the Flutter framework, and the Flutter App framework.

  • Flutter plugin that support SwiftPM will be copied from the pubcache to the output directory. If the plugin does not have a dependency on the Flutter framework, we'll add the dependency using swift package commands.
  • Flutter plugins that support CocoaPods only will be built into xcframeworks in the output directory.
  • The Flutter framework will be copied from the engine artifacts or use a remote url (if requested via flag).
  • The App framework will be built into an xcframework in the output directory.

To handle different frameworks per build mode, we'll utilize symlinks and build scripts to swap the correct artifacts.

Build configuration will be handled via symlinks (see Sources and Package.swift in file structure below)

├── FlutterPluginRegistrant
│   ├── Debug
│   │   ├── FlutterPluginRegistrant (module source files)
│   │   ├── Frameworks
│   │   │   ├── App.xcframework
│   │   │   ├── CocoaPods
│   │   │   │   ├── [CocoaPods-only Flutter plugins build into xcframeworks]
│   │   │   ├── Flutter.xcframework
│   │   │   ├── NativeAssets
│   │   │   │   ├── [NativeAssets Flutter plugins build into xcframeworks]
│   │   ├── Package.swift
│   │   ├── Packages
│   │   │   ├── for each plugin -> symlink to ../../../Plugins/[plugin_name]
│   │   │   ├── FlutterFramework
│   ├── Release
│   ├── Sources -> symlink to ./Debug
│   ├── Package.swift -> symlink to ./Debug/Package.swift
├── FlutterConfigurationPlugin
├── Plugins
│   ├── [Copied Flutter plugins that support SwiftPM]
├── Scripts
│   ├── pre_action.sh
│   ├── post_embed.sh
let package = Package(
    name: "FlutterPluginRegistrant",
    products: [
        .library(name: "FlutterPluginRegistrant", type: .static, targets: ["FlutterPluginRegistrant"])
    ],
    dependencies: [
        .package(name: "FlutterFramework", path: "Sources/Packages/FlutterFramework"),
        .package(name: "plugin_with_swiftpm_support", path: "Sources/Packages/plugin_with_swiftpm_support"),
        .package(name: "FlutterConfigurationPlugin", path: "../FlutterConfigurationPlugin")
    ],
    targets: [
        .target(
            name: "FlutterPluginRegistrant",
            dependencies: [
                .product(name: "FlutterFramework", package: "FlutterFramework"),
                .target(name: "App"),
                .product(name: "plugin-with-swiftpm-support", package: "plugin_with_swiftpm_support"),
                .target(name: "cocoapod_only_plugin"),
                .target(name: "native_asset_plugin")
            ]
        ),
        .binaryTarget(
            name: "App",
            path: "Sources/Frameworks/App.xcframework"
        ),
        .binaryTarget(
            name: "cocoapod_only_plugin",
            path: "Sources/Frameworks/CocoaPods/cocoapod_only_plugin.xcframework"
        ),
        .binaryTarget(
            name: "native_asset_plugin",
            path: "Sources/Frameworks/NativeAssets/native_asset_plugin.xcframework"
        )
    ]
)

When integrating into the existing Xcode project a script will need to be added to the scheme's Pre-Action to swap the FlutterPluginRegistrant/Sources and FlutterPluginRegistrant/Package.swift symlink to the appropriate build mode.

Another script will be added as a Build Phase (after embedding), which will validate that the correct artifacts are embedded for the targeted build configuration as a safeguard. It will also run flutter assemble if FLUTTER_APPLICATION_PATH is set. This will re-build the App.framework with any Dart code changes.

In addition, we will also provide a swift package plugin (FlutterConfigurationPlugin), which will allow the developer to manually switch the build mode via Xcode's GUI.

Image

Implementation Plan

See subtasks

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: existing-appsIntegration with existing apps via the add-to-app flowcustomer: castawayteam-iosOwned by iOS platform teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-iosTriaged by iOS platform team

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions