PAYATHON 2026

如何为本地 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:

  1. 停止当前正在进行的构建或 Archive。
  2. 在 Xcode 中执行 File > Packages > Reset Package Caches。
  3. 执行 File > Packages > Resolve Package Versions。
  4. 确认 Package.resolved 已经解析到预期的 Sentry 版本。
  5. 选择发布使用的 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 中出现的第一条错误,后面的错误可能只是连锁反应。然后依次检查:

  1. CommonUtilities 的源码是否使用 import Sentry。
  2. target dependency 是否写成 .product(name: "Sentry", package: "sentry-cocoa")。
  3. package URL 是否以不同形式重复添加,例如同时使用 HTTPS 和 SSH。
  4. iOS 和 watchOS deployment target 是否满足所选 Sentry SDK 版本的最低平台要求。
  5. 当前 Xcode 附带的 Swift 工具链是否支持 swift-tools-version: 6.3。如果不支持,需要改为该工具链实际支持的 tools version。
  6. 每个直接导入 Sentry 的 app、extension 或 package target 是否都声明了自己的依赖。

需要修正的是 package identity 与 product 名的对应关系:依赖包是 sentry-cocoa,target 依赖的产品是 Sentry。

备注:内容仅供参考。