如何为本地 Swift Package 添加 Sentry 依赖
结论
Package.swift 中的 product 名称写错了。sentry-cocoa 是 package identity,对应依赖包的名称;本地 target 依赖的 library product 则是 Sentry。
将:
.product(name: "sentry-cocoa", package: "sentry-cocoa")
改为:
.product(name: "Sentry", package: "sentry-cocoa")
本地 package 导入的模块名也是:
import Sentry
import sentry-cocoa 不是有效写法。product 名称区分大小写。
正确的 Package.swift 配置
依赖可以这样声明:
// swift-tools-version: 6.3
import PackageDescription
let package = Package(
name: "CommonUtilities",
products: [
.library(
name: "CommonUtilities",
targets: ["CommonUtilities"]
),
],
dependencies: [
.package(
url: "https://github.com/getsentry/sentry-cocoa",
from: "9.16.1"
),
],
targets: [
.target(
name: "CommonUtilities",
dependencies: [
.product(
name: "Sentry",
package: "sentry-cocoa"
),
]
),
],
swiftLanguageModes: [.v6]
)
这里涉及三个名称:
sentry-cocoa是 SwiftPM 用来识别依赖包的 package identity,通常根据仓库 URL 推导。Sentry是该 package 对外提供的 library product。Sentry也是源码通过import Sentry导入的模块名。
.product(name:package:) 中的 name 参数要填写依赖包实际导出的 product 名,不能直接使用 GitHub 仓库名。
为什么普通构建能通过,Archive 却失败
项目之前已经通过 Xcode 为 app target 添加了 Sentry。进行开发构建时,Xcode 生成的依赖图可能让 CommonUtilities 间接访问到 app target 引入的 Sentry,所以问题没有马上出现。
Archive 会使用 Release 配置重新解析、编译和链接完整的依赖图,对 target 之间的依赖关系要求更严格。CommonUtilities 的源码直接使用了 import Sentry,因此它自己的 target 必须显式依赖 Sentry product,不能依赖 app target 间接提供。
下面这段配置需要保留:
.target(
name: "CommonUtilities",
dependencies: [
.product(name: "Sentry", package: "sentry-cocoa"),
]
)
同时检查 app targets
如果 iOS app 或 watchOS app 中也有:
import Sentry
对应的 target 也要直接添加 Sentry product。可以在 Xcode 的 target 设置中检查:
Target
└── General
└── Frameworks, Libraries, and Embedded Content
也可以查看 target 的 Build Phases / Package Product Dependencies。只有实际导入 Sentry 的 target 才需要直接依赖它。
iOS app 和 watchOS companion app 运行在不同进程中。如果两端都要独立上报事件,通常需要分别在各自的启动流程中初始化 SDK。iOS app 中的初始化不会自动作用于 watchOS app。
修改后重新解析依赖
修正 manifest 后,让 Xcode 重新解析 package:
- 停止当前正在进行的构建或 Archive。
- 在 Xcode 中执行
File > Packages > Reset Package Caches。 - 执行
File > Packages > Resolve Package Versions。 - 确认
Package.resolved已经解析到预期的 Sentry 版本。 - 选择发布使用的 scheme 和 Generic Device,再次执行
Product > Archive。
不同 Xcode 版本的菜单位置可能略有差异。如果仍有旧错误残留,可以继续清理 Derived Data。清理缓存只能移除旧状态,无法修复错误的 product 名称。
moduleAliases 为什么没有作用
moduleAliases 用来处理模块重名。例如,依赖图中的两个不同 package 都导出了名为 Logging 的模块时,可以为其中一个模块设置别名。
它不能完成以下操作:
- 把 package identity 转换为 product 名。
- 修复不存在的 product。
- 将
sentry-cocoa自动映射为Sentry。 - 代替 target 中显式声明的 dependency。
因此,无论配置 ["Sentry": "sentry-cocoa"] 还是反向配置,都无法解决这个问题。
仍然报错时的检查顺序
先看 Archive 中出现的第一条错误,后面的错误可能只是连锁反应。然后依次检查:
CommonUtilities的源码是否使用import Sentry。- target dependency 是否写成
.product(name: "Sentry", package: "sentry-cocoa")。 - package URL 是否以不同形式重复添加,例如同时使用 HTTPS 和 SSH。
- iOS 和 watchOS deployment target 是否满足所选 Sentry SDK 版本的最低平台要求。
- 当前 Xcode 附带的 Swift 工具链是否支持
swift-tools-version: 6.3。如果不支持,需要改为该工具链实际支持的 tools version。 - 每个直接导入 Sentry 的 app、extension 或 package target 是否都声明了自己的依赖。
需要修正的是 package identity 与 product 名的对应关系:依赖包是 sentry-cocoa,target 依赖的产品是 Sentry。
备注:内容仅供参考。
