KMP 正式支持 SwiftPM:CocoaPods 迁移配置指南

KMP 模块里 CocoaPods 如何依赖迁到 Swift Package Manager?

页面里的入口是 Junie + Kotlin AI Skill,但迁移本身仍然要回到 Gradle、Xcode 和 Kotlin imports 这几个具体文件。

SwiftPM import 现在还是 Alpha,示例要求 KMP Gradle 插件使用 2.4.0-RC2。项目里如果已经通过 CocoaPods 接了 Firebase、Google Maps 这类 iOS SDK,这个迁移就不只是替换包管理器,还会影响 iOS 侧构建方式。

先看边界

这次说的是"在 KMP 模块里引入 SwiftPM 依赖"。也就是说,Kotlin 代码可以通过 SwiftPM import 调用 Objective-C API,Kotlin/Native 编译和 framework 链接时,Gradle 插件会把 SwiftPM 依赖需要的机器码带上。

这个功能不等于把使用 SwiftPM import 的 KMP 模块再导出成一个 Swift package。文档里明确写了,这个场景还不支持,可能不能正常工作。如果你的交付方式是把 shared 模块发布成 Swift package 给 iOS 团队消费,这条限制要先确认。

另一个边界是动态 Kotlin/Native framework。遇到 Undefined symbols for architecture ...dyld: Symbol not found,或者同一个 Objective-C class 在两个 binary 里重复实现时,文档给的通用处理方式是把 framework 改成静态:

bash 复制代码
kotlin {
    listOf(
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "Shared"
            isStatic = true
        }
    }
}

这个点和 CocoaPods 迁移关系很近。以前很多项目会把 framework 配在 cocoapods.framework {} 里,迁到 SwiftPM 后,这部分要移到 Apple target 的 binaries.framework {} 下。

Junie 和 Skill

Junie 的使用方式比较直接。先安装 CLI,然后登录 JetBrains 账号,或者配置外部 LLM:

bash 复制代码
curl -fsSL https://junie.jetbrains.com/install.sh | bash
junie

项目目录下安装 Kotlin AI Skill:

bash 复制代码
npx skills add Kotlin/kotlin-agent-skills

这个命令要求 npm 不低于 5.2.0。交互里选择 kotlin-tooling-cocoapods-spm-migration,agent 选择 Junie,scope 选择 Project,这样 Skill 只落在当前项目里。

之后在项目根目录启动 Junie:

bash 复制代码
junie

输入迁移任务:

bash 复制代码
Migrate <project-name> from CocoaPods to SwiftPM

Junie 会识别刚安装的 Skill,然后开始检查项目。开始前要保证项目已经在 Git 里,因为后面要靠 diff 看它到底改了哪些文件。AI 工具会改对一部分,也可能把 Xcode 工程、Podfile 或 imports 改偏,不能把生成结果当成最终结论。

Gradle 变化

SwiftPM import 要求 Kotlin Multiplatform Gradle plugin 使用 2.4.0-RC2。如果项目用 Version Catalog,版本入口大概是这样:

bash 复制代码
[versions]
kotlin = "2.4.0-RC2"

[plugins]
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }

依赖迁移时不要一开始就删 CocoaPods。文档里的顺序是先加 swiftPMDependencies {},让 SwiftPM 和 CocoaPods 依赖短时间并存,等 SwiftPM import 能解析、Kotlin 代码也能编译,再清理 CocoaPods。

FirebaseAnalytics 为例,build.gradle.kts 里会多一个 Swift package 声明:

bash 复制代码
kotlin {
    iosArm64()
    iosSimulatorArm64()

    swiftPMDependencies {
        swiftPackage(
            url = url("https://github.com/firebase/firebase-ios-sdk.git"),
            version = from("12.5.0"),
            products = listOf(product("FirebaseAnalytics")),
        )
    }

    cocoapods {
        pod("FirebaseAnalytics") {
            version = "12.5.0"
        }
    }
}

如果 Swift package 里的 Clang module 名称和 product 名称不一致,就不能只写 product。discoverClangModulesImplicitly = false 之后,需要用 importedClangModules 明确列出来。FirebaseFirestore 的 Objective-C API 就在文档示例里的 FirebaseFirestoreInternal module 中。

bash 复制代码
kotlin {
    swiftPMDependencies {
        discoverClangModulesImplicitly = false

        swiftPackage(
            url = url("https://github.com/firebase/firebase-ios-sdk.git"),
            version = from("12.5.0"),
            products = listOf(
                product("FirebaseAnalytics"),
                product("FirebaseFirestore"),
            ),
            importedClangModules = listOf(
                "FirebaseAnalytics",
                "FirebaseFirestoreInternal",
            ),
        )
    }
}

多 Apple target 项目还要看平台约束。比如 Google Maps SDK 当前只支持 iOS target,项目里如果同时有 iosArm64()macosArm64(),产品声明要限制到 iOS:

bash 复制代码
kotlin {
    iosArm64()
    iosSimulatorArm64()
    macosArm64()

    swiftPMDependencies {
        swiftPackage(
            url = url("https://github.com/googlemaps/ios-maps-sdk.git"),
            version = exact("10.3.0"),
            products = listOf(
                product("GoogleMaps", platforms = setOf(iOS()))
            )
        )
    }
}

最后

KMP在你们的工程项目中占比多少了呢?

#Kotlin #KMP #SwiftPM #CocoaPods #AI编程

相关推荐
游戏开发爱好者84 小时前
带签名时间戳接口的重放与压力测试实战,用动态值在发送前现算签名
网络协议·计算机网络·网络安全·ios·adb·https·压力测试
启雀AI8 小时前
培训平台移动端离线学习方案设计与实现:视频缓存、断点续传与进度同步的工程实践
android·学习·缓存·音视频·企业lms
我命由我123459 小时前
RxJava - 冷数据流与热数据流
android·java·java-ee·android studio·rxjava·android-studio·android runtime
用户45989204565169 小时前
一套 KMP 多仓库版本治理工作流:用 Version Catalog + CI 把发版流水线自动化
前端·kotlin
2601_9665635211 小时前
愤怒的小鸟单机版 去广告 安卓+PC端离线纯净版 益智耐玩小游戏 不需联网 老旧手机都可以玩 怀旧手机小游戏
android·智能手机
hunterandroid11 小时前
[Android 从零到一] Retrofit 请求取消与生命周期绑定:从 Call.cancel 到协程可取消设计
android
爱跑马的程序员11 小时前
安卓专有的通信子系统-Binder IPC
android·binder·ipc·安卓间通信机制
ue星空12 小时前
【安卓逆向】为什么用Frida?
android
小驰行动派12 小时前
Camx架构全景图:从V4L2到Pipeline的完整拆解
android·camera·android camera
独隅13 小时前
KMP 全栈进化:Koog 框架打造纯 Kotlin AI Agent 实战效果
开发语言·人工智能·kotlin