跪拜 Guibai
← All articles
Android · Kotlin · iOS

KMP Gets Alpha SwiftPM Support — Here's the CocoaPods Migration Path

By 黄林晴 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Teams maintaining KMP shared modules for iOS have been locked into CocoaPods for years. Alpha SwiftPM support removes a friction point that made KMP feel like a second-class citizen in Xcode-native workflows, though the inability to export as a Swift package means the shared module still can't be distributed the way pure-Swift libraries are.

Summary

The migration path keeps CocoaPods and SwiftPM dependencies coexisting in the same Gradle file until compilation succeeds, then removes the old pod declarations. JetBrains ships a Junie AI Skill that automates parts of the migration, though the generated changes still need manual review against the Git diff.

Two hard boundaries apply: KMP modules that consume SwiftPM dependencies cannot themselves be exported as Swift packages, and dynamic Kotlin/Native frameworks often need to switch to static linking to avoid symbol conflicts. Platform constraints also matter — a Swift package like Google Maps that only supports iOS must be scoped to iOS targets when the project also builds for macOS.

For Firebase and other SDKs where the Clang module name differs from the Swift product name, `discoverClangModulesImplicitly` must be set to false and the correct module names listed explicitly in `importedClangModules`.

Takeaways
SwiftPM import requires Kotlin Multiplatform Gradle plugin 2.4.0-RC2 and is still in alpha.
Add `swiftPMDependencies {}` alongside existing CocoaPods blocks first; remove CocoaPods only after SwiftPM imports resolve and Kotlin code compiles.
KMP modules using SwiftPM imports cannot be exported as Swift packages — the documentation explicitly marks this as unsupported.
Dynamic Kotlin/Native frameworks frequently cause `Undefined symbols` or duplicate class errors with SwiftPM dependencies; switching to `isStatic = true` is the documented fix.
Framework configuration previously inside `cocoapods.framework {}` must move to Apple target `binaries.framework {}` after migration.
When a Swift package's Clang module name differs from its product name, set `discoverClangModulesImplicitly = false` and list the correct module names in `importedClangModules`.
Platform-specific packages like Google Maps require scoping products to iOS targets when the project also builds for macOS.
JetBrains' Junie CLI with the `kotlin-tooling-cocoapods-spm-migration` Skill can automate parts of the migration, but generated changes need manual review via Git diff.
Conclusions

JetBrains is using its own AI tooling to smooth a migration that would otherwise be tedious and error-prone, which is a pragmatic dogfooding move — but the explicit warning not to trust the AI output keeps expectations grounded.

The coexistence strategy of running both package managers side-by-side during migration is the only safe path, because a clean cutover would leave no fallback when imports break at the Kotlin/Native linking stage.

Not being able to export a SwiftPM-consuming KMP module as a Swift package is a significant distribution gap. It means iOS teams consuming a shared KMP module still need the Gradle build, which undercuts the promise of fitting into a pure-Swift ecosystem.

Concepts & terms
SwiftPM (Swift Package Manager)
Apple's native dependency manager for Swift and Objective-C packages, integrated into Xcode. It resolves, downloads, and links package dependencies declared in a Package.swift manifest.
Kotlin/Native
A Kotlin compiler backend that produces native binaries for platforms like iOS, macOS, watchOS, and tvOS without a virtual machine. It compiles Kotlin code directly to machine code via LLVM.
Clang module
A precompiled header-like unit that describes a C, C++, or Objective-C library's API for the Clang compiler. SwiftPM packages wrapping C-family code expose their API through Clang modules, whose names may differ from the Swift product name.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗