mcpField
C
cocoapods-to-spm

cocoapods-to-spm

github.com/cap-go开发73800 次安装2 周前更新
代码仓库

关于 cocoapods-to-spm

面向 Capacitor iOS 应用从 CocoaPods 迁移到 Swift Package Manager 的技能,重点是在迁移时保留原生项目定制。它指导开发者检查依赖、选择迁移方式并验证结果。

主要功能

  1. 01检查依赖与项目定制
  2. 02核对插件的 SPM 兼容性
  3. 03选择迁移路径
  4. 04提供 CLI 和 Xcode 操作步骤
  5. 05验证迁移结果
  6. 06排查常见迁移故障

适用场景

  1. 01将现有 Capacitor iOS 应用迁移到 SPM
  2. 02找出阻碍迁移的插件或 Pod
  3. 03保留扩展和原生项目设置
  4. 04诊断迁移后缺失的插件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cap-go/capgo-skills --skill cocoapods-to-spm

安装后在 Claude Code 中输入/cocoapods-to-spm确认已加载。

附带文件metadata.jsonreferences/troubleshooting.md

详细介绍

从 CocoaPods 迁移到 Swift Package Manager

将 Capacitor iOS 应用从 CocoaPods 迁移到 SPM,同时保留原生项目自定义配置。

适用场景

在以下情况下触发:

  • 存在 ios/App/Podfile、Pods/、Podfile.lock 或 App.xcworkspace,且用户想要使用 SPM。
  • 用户询问 npx cap spm-migration-assistant、CapApp-SPM、debug.xcconfig 或 --packagemanager SPM。
  • 用户担心 CocoaPods Trunk 将变为只读(预计于 2026 年 12 月 2 日),或担心某些 Pod 将无法再发布或更新。
  • npx cap sync 警告 Some installed Capacitor plugins are not compatible with SPM 或 <plugin id> does not have a Package.swift。
  • 升级到 Capacitor 9 时,用户也想同时弃用 CocoaPods。

请勿用于:

  • 为你维护的插件添加 Package.swift / CAPBridgedPlugin → capacitor-plugin-spm-support。
  • 采用 SceneDelegate / UIScene(Capacitor 8.5+,Xcode 27 要求)→ capacitor-uiscene-migration。
  • Capacitor 主版本升级本身 → capacitor-app-upgrades、capacitor-app-upgrade-v8-to-v9。
  • 与依赖管理无关的构建或运行时故障 → debugging-capacitor。

为什么现在迁移

  • CocoaPods Trunk 预计将于 2026 年 12 月 2 日变为只读。现有 Pod 仍可解析,但不会再发布新版本,因此插件修复将越来越多地仅通过 SPM 发布。
  • Capacitor 8+ 默认使用 SPM 搭建新的 iOS 项目。升级 Capacitor 不会将现有的 CocoaPods 应用转换为 SPM。
  • Capacitor 9(目前为 next / alpha)只有在安装了 Cordova 插件时,才会添加 Cordova 产品 / CapacitorCordova Pod。未安装 Cordova 插件却导入 Cordova 的原生代码,在两种配置中都会出错。

CLI 如何判断

  • 当且仅当 ios/App/CapApp-SPM/ 存在时,CLI 才会将项目视为使用 SPM。删除或重命名该目录会悄无声息地使 npx cap sync 恢复为 CocoaPods 行为。
  • 每次运行 npx cap sync ios 都会重新生成 ios/App/CapApp-SPM/Package.swift(// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands)。请在 capacitor.config.* 中进行自定义,切勿修改该文件。
  • 只有当插件的 npm 包根目录中包含 Package.swift 时,才会纳入该插件。其他插件会被跳过并显示警告;其原生代码会在运行时悄无声息地缺失("X" plugin is not implemented on ios)。
  • 同步期间,如果插件的 Package.swift 将 capacitor-swift-pm 固定到不同的主版本,CLI 会重写 node_modules 中的该文件,并警告 <id> is built for Capacitor <N>, it might cause issues。请将此视为“升级插件”的提示,而非成功。
  • Cordova 插件会在 ios/capacitor-cordova-ios-plugins/sources/<Name> 下生成一个包。SPM 二进制目标不支持普通的 .framework 文件(警告:custom .framework files are not supported as binaryTarget in SPM);这些文件需要转换为 .xcframework。

命令策略

  • 安装依赖和运行脚本时使用仓库的包管理器;调用 Capacitor CLI 时使用 npx cap ...,以确保运行项目本地的 CLI。
  • 请从包含 capacitor.config.* 的目录运行命令。

实时项目快照

检测到的 Capacitor、iOS、Cordova 和插件依赖: !node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(name.startsWith('@capacitor/')||name.startsWith('@capgo/')||name.startsWith('@capacitor-community/')||name.startsWith('@awesome-cordova-plugins/')||name.startsWith('cordova-')||name.includes('capacitor'))out.push(section+'.'+name+'='+version)}}console.log(out.sort().join('\n'))"

相关 iOS 依赖文件: !find ios -maxdepth 5 \( -name 'Podfile' -o -name 'Podfile.lock' -o -name 'Pods' -o -name 'App.xcworkspace' -o -name 'Package.swift' -o -name 'Package.resolved' -o -name 'CapApp-SPM' -o -name 'debug.xcconfig' -o -name 'project.pbxproj' -o -name 'Info.plist' -o -name '*.entitlements' -o -name 'GoogleService-Info.plist' \) 2>/dev/null

流程

1. 检查(只读)
  1. 查看 package.json 中的 Capacitor 版本(@capacitor/ios)。支持 8.x 和 9.x;如果是 6.x/7.x,建议先升级。
  2. 检查 ios/App/Podfile 和 Podfile.lock:列出所有 pod,以及哪些不是 Capacitor 插件(Firebase、分析 SDK、手动添加的自定义 pod)。
  3. 对于每个 Capacitor/Cordova 插件:node_modules/<pkg>/Package.swift 是否存在?Cordova 插件会生成对应的包,因此只有 NO 项会造成阻碍:
    node -e "const fs=require('fs');const p=require('./package.json');for(const n of Object.keys({...p.dependencies,...p.devDependencies})){const d='node_modules/'+n;if(!fs.existsSync(d+'/ios')&&!fs.existsSync(d+'/plugin.xml'))continue;console.log((fs.existsSync(d+'/Package.swift')?'SPM     ':fs.existsSync(d+'/plugin.xml')?'CORDOVA ':'NO      ')+n)}"
    
  4. 检查 ios/App/App.xcodeproj/project.pbxproj:签名、自定义构建设置、额外目标(小组件、通知服务扩展)、构建阶段、方案。
  5. 检查 ios/App/App/:AppDelegate.swift、SceneDelegate.swift、Info.plist、entitlements、GoogleService-Info.plist、自定义 Swift/ObjC 文件。

编辑前先报告检查结果:没有 SPM 支持的插件、需要 SPM 替代方案的非插件 pod,以及可能受影响的原生自定义内容。

2. 解决阻碍

对于每个 NO 插件或非插件 pod:

  • 升级插件(大多数维护中的插件,包括 @capacitor/* 和 @capgo/*,都附带 Package.swift)。
  • 替换为维护良好且支持 SPM 的替代方案。
  • 如果项目由你维护该插件,可使用 capacitor-plugin-spm-support 转换。
  • 对于直接添加到 Podfile 的第三方 SDK pod,在迁移后将供应商的 SPM 包添加到 Xcode 中的 App 目标。

如果关键插件没有 SPM 迁移路径,请先询问用户再继续。不要保留混合使用 Podfile 和 CapApp-SPM 的配置。

3. 选择路径
路径适用情况
npx cap spm-migration-assistant适用于大多数应用;保留现有 Xcode 项目及其自定义内容。
全新脚手架ios/ 与模板接近(没有扩展,原生修改较少)。
手动修复助手仅部分运行成功,或项目经过大量自定义。
4a. 运行迁移助手

先提交更改。仍需安装 CocoaPods(或 Bundler),因为迁移会运行 pod deintegrate。

npx cap spm-migration-assistant

迁移助手会运行 pod deintegrate,删除 Podfile、Podfile.lock 和 App.xcworkspace,提取 ios/App/CapApp-SPM/,写入 ios/debug.xcconfig(CAPACITOR_DEBUG = true),并在 Info.plist 中缺少 CAPACITOR_DEBUG = $(CAPACITOR_DEBUG) 时将其添加,然后运行 iOS 更新以生成 Package.swift。最后会显示 To complete migration follow the manual steps at https://capacitorjs.com/docs/ios/spm#using-our-migration-tool。

还需在 Xcode 中手动完成两个步骤(npx cap open ios 现在会打开 App.xcodeproj):

  1. 项目 App -> Package Dependencies -> + -> Add Local... -> 选择 ios/App/CapApp-SPM -> Add Package,并将 CapApp-SPM 库关联到 App 目标。
  2. 项目 App -> Info -> Configurations -> Debug -> 将配置文件设为 debug.xcconfig。

然后运行 npx cap sync ios。

4b. 全新脚手架

先备份第 1.5 步中列出的所有内容。

rm -rf ios
npx cap add ios --packagemanager SPM
npx cap sync ios

在 Capacitor 8.5+ 中,新模板已包含 SceneDelegate.swift 和 UIApplicationSceneManifest。通过合并而非覆盖模板文件,恢复图标、Info.plist 键、权利文件、签名配置、Firebase plist、自定义源文件和扩展目标。

5. capacitor.config.* 中的可选 SPM 配置

仅在需要时配置(均位于 experimental.ios.spm 下,并确认已安装的 CLI 版本支持这些选项):

  • swiftToolsVersion(8.3+,默认为 '5.9'):生成的 Package.swift 的头部。
  • packageTraits(8.3+):{ "<plugin id>": ["TraitName", ".defaults"] };要求 swiftToolsVersion >= '6.1'。
  • packageOptions(8.4+):{ "<plugin id>": { symlink: true, moduleAliases: { "Target": "Alias" } } },用于处理软件包名称或模块冲突。
6. UIScene 检查

助手只会更改依赖管理。如果 Info.plist 中缺少 UIApplicationSceneManifest,则应用尚未使用 Capacitor 8.5+ 和 Xcode 27 要求的场景生命周期;请运行 npx cap migrate,或遵循 capacitor-uiscene-migration 中的说明。

验证

# No CocoaPods leftovers
ls ios/App | grep -E 'Podfile|Pods|xcworkspace' && echo "LEFTOVERS" || echo "clean"
# CLI sees SPM and every plugin is included
npx cap sync ios 2>&1 | grep -Ei 'Package.swift|not compatible|built for Capacitor'
grep -c '.package(name:' ios/App/CapApp-SPM/Package.swift
# Plugin classes registered for runtime
node -e "console.log(require('./ios/App/App/capacitor.config.json').packageClassList)"
# Build without Xcode UI (project, not workspace)
xcodebuild -project ios/App/App.xcodeproj -scheme App -destination 'generic/platform=iOS Simulator' build

还请在 Xcode 中确认:CapApp-SPM 已关联到 App 目标,Debug 使用 debug.xcconfig,签名、Bundle ID 和功能未发生变化。在设备上,至少运行一次每个原生插件(相机、推送、购买等)。

提交 ios/App/CapApp-SPM/ 和 ios/debug.xcconfig。对于 Package.resolved,请遵循 CapApp-SPM/.gitignore 中的规则(较新的模板会忽略它)。

错误处理

加载 references/troubleshooting.md 查看完整表格。最常见的问题:

消息 / 症状修复方法
Capacitor project is already using SPM, exiting.CapApp-SPM/ 已存在。请手动修复,不要使用助手。
CocoaPods is not installed.(助手)暂时安装 CocoaPods,或使用全新脚手架方案。
<id> does not have a Package.swift / Some installed Capacitor plugins are not compatible with SPM升级、替换或转换该插件(第 2 步)。
运行时出现 "X" plugin is not implemented on ios插件被跳过,未加入 Package.swift,或缺少 packageClassList。修复插件、重新同步并清理构建。
No such module 'Capacitor' / Missing package product 'CapApp-SPM'尚未添加或关联本地软件包;重新执行手动步骤 1,然后选择 File -> Packages -> Reset Package Caches。
仅 Debug 模式下功能不可用(无法检查 WebView、没有调试日志)未在 Debug 配置中设置 debug.xcconfig。

输出格式

规划时,请返回:当前状态(Capacitor 版本、pods、没有 SPM 的插件、面临风险的自定义配置)、选择的方案及原因、按顺序排列的步骤,以及仍需在 Xcode 或设备上执行的检查。

评论

支持 Markdown