$npx -y skills add Kotlin/kotlin-agent-skills --skill kotlin-tooling-cocoapods-spm-migrationMigrate KMP projects from CocoaPods (kotlin("native.cocoapods")) to Swift Package Manager (swiftPMDependencies DSL) — replaces pod() with swiftPackage(), transforms cocoapods.* imports to swiftPMImport.*, and reconfigures the Xcode project.
| 1 | # CocoaPods to SwiftPM Migration for KMP |
| 2 | |
| 3 | Migrate Kotlin Multiplatform projects from `kotlin("native.cocoapods")` to `swiftPMDependencies {}` DSL. |
| 4 | |
| 5 | ## Requirements |
| 6 | |
| 7 | - **Kotlin**: 2.4.0-Beta2 or later (first public release with `swiftPMDependencies` support, available on Maven Central) |
| 8 | - **Xcode**: 16.4 or 26.0+ |
| 9 | - **iOS Deployment Target**: 16.0+ recommended |
| 10 | |
| 11 | ## Migration Overview |
| 12 | |
| 13 | **IMPORTANT**: Keep the `cocoapods {}` block and plugin active until Phase 6. The migration adds `swiftPMDependencies {}` alongside the existing CocoaPods setup first, reconfigures Xcode, and only then removes CocoaPods. |
| 14 | |
| 15 | | Phase | Action | |
| 16 | |-------|--------| |
| 17 | | 1 | Analyze existing CocoaPods configuration | |
| 18 | | 2 | Update Gradle configuration (repos, Kotlin version) | |
| 19 | | 3 | Add `swiftPMDependencies {}` alongside existing `cocoapods {}` | |
| 20 | | 4 | Transform Kotlin imports | |
| 21 | | 5 | Reconfigure iOS project and deintegrate CocoaPods | |
| 22 | | 6 | Remove CocoaPods plugin from Gradle | |
| 23 | | 7 | Verify Gradle build and Xcode project build | |
| 24 | | 8 | Write MIGRATION_REPORT.md | |
| 25 | |
| 26 | --- |
| 27 | |
| 28 | ## Phase 1: Pre-Migration Analysis |
| 29 | |
| 30 | ### 1.0 Verify the project builds |
| 31 | |
| 32 | Before starting migration, identify the module to migrate and confirm it compiles successfully. |
| 33 | |
| 34 | 1. **Find the module that uses CocoaPods** — look for `build.gradle.kts` files containing `cocoapods`: |
| 35 | ```bash |
| 36 | grep -rl "cocoapods" --include="build.gradle.kts" . |
| 37 | ``` |
| 38 | Extract the module name from the path (e.g., `./shared/build.gradle.kts` → module name is `shared`). Note: multiple modules may use CocoaPods — record all of them. Typically only the module that produces the framework linked into the iOS app needs `swiftPMDependencies`; the others only need CocoaPods removed (Phase 6). |
| 39 | |
| 40 | 2. **Compile Kotlin code** — run the Kotlin compilation task for that module to verify the Kotlin source compiles: |
| 41 | ```bash |
| 42 | ./gradlew :moduleName:compileKotlinIosSimulatorArm64 |
| 43 | ``` |
| 44 | Replace `moduleName` with the directory name of the module (e.g., `:shared:compileKotlinIosSimulatorArm64`). This is faster than a full `build` (which also runs release linkage) and sufficient to verify Kotlin code correctness. |
| 45 | |
| 46 | 3. **Build the iOS app (optional)** — try to locate the Xcode project and build it to confirm the full app compiles: |
| 47 | ```bash |
| 48 | # Find the Xcode project |
| 49 | find . -name "*.xcworkspace" -not -path "*/Pods/*" -maxdepth 2 |
| 50 | # Build (replace scheme name with the actual app scheme) |
| 51 | cd /path/to/iosApp |
| 52 | xcodebuild -workspace *.xcworkspace -scheme "<AppScheme>" -destination 'generic/platform=iOS Simulator' ARCHS=arm64 |
| 53 | ``` |
| 54 | If the user wants to skip the Xcode build or no Xcode project is found, proceed without it — the Kotlin compilation from step 2 is sufficient to continue. |
| 55 | |
| 56 | 4. **If the Kotlin compilation fails**, ask the user to either: |
| 57 | - Provide the correct Gradle command to verify the module builds, or |
| 58 | - Confirm the module is in a working state and it's safe to proceed |
| 59 | |
| 60 | If the user confirms without providing a build command, **record that the pre-migration build could not be verified** and warn about this at the end of migration (Phase 7). |
| 61 | |
| 62 | ### 1.0a Confirm Kotlin version with Swift Import support |
| 63 | |
| 64 | Read the current Kotlin version from `gradle/libs.versions.toml` (or `build.gradle.kts`). |
| 65 | |
| 66 | **If the project already uses Kotlin 2.4.0-Beta2 or later** → record the version and skip Phase 2.1 (no version change needed). |
| 67 | |
| 68 | **If the project uses an older Kotlin version** → Phase 2.1 will upgrade it to `2.4.0-Beta2` (the first public release with `swiftPMDependencies` support, available on Maven Central — no custom repository needed). Warn the user: "⚠️ Kotlin version jump — upgrading across minor versions can introduce breaking changes unrelated to this migration. Recommended: update first, verify it builds, then re-run this migration." If the user confirms, proceed. |
| 69 | |
| 70 | ### 1.1 Check for deprecated CocoaPods workaround property |
| 71 | |
| 72 | Search `gradle.properties` for the deprecated property: |
| 73 | |
| 74 | ```properties |
| 75 | kotlin.apple.deprecated.allowUsingEmbedAndSignWithCocoaPodsDependencies=true |
| 76 | ``` |
| 77 | |
| 78 | This property was a workaround (see [KT-64096](https://youtrack.jetbrains.com/issue/KT-64096)) for projects using `embedAndSign` alongside CocoaPods dependencies. It suppresses an error about unsupported configurations that can cause runtime crashes or symbol duplication. After migrating to SwiftPM import, this property is no longer needed and **must be removed** in Phase 6. Record its presence if found. |
| 79 | |
| 80 | ### 1.2 Check for EmbedAndSign disablers |
| 81 | |
| 82 | Search all `build.gradle.kts` files for code that disables `EmbedAndSign` tasks (e.g., `TaskGraph.whenReady` fil |