解决 command codesign failed with a nonzero exit code
:一步步详细教学
在 iOS 或 macOS 开发中,command codesign failed with a nonzero exit code
是一个开发者经常会遇到的令人沮丧的错误。它通常出现在尝试构建或归档(Archive)你的应用程序时。这个错误信息本身非常通用,仅仅表示 Xcode 在尝试对你的应用程序进行代码签名时,底层的 codesign
命令行工具执行失败,并返回了一个非零的退出状态码,这表明操作未能成功完成。
代码签名是 Apple 平台应用程序安全和信任机制的核心部分。它验证了应用的来源,并确保应用在发布或安装后没有被篡改。成功的代码签名依赖于一系列正确的配置:有效的开发者证书、正确的私钥、匹配的应用程序 ID (App ID) 以及有效的 provisioning profile(配置文件)。command codesign failed
错误几乎总是与这些组件中的一个或多个配置问题有关。
由于这个错误信息过于笼统,解决它通常需要进行一系列系统的排查。本文将提供一个详细、一步步的教学流程,帮助你诊断并解决这个问题。我们将从最常见的原因开始,逐步深入到更复杂的情况。
理解代码签名及其组件
在开始排查之前,先理解一下代码签名的核心要素是很有帮助的:
- 开发者证书 (Developer Certificate): 这是一个由 Apple 颁发的数字身份证明,用于验证你作为开发者。它存储在你的 Mac 上的“钥匙串访问” (Keychain Access) 应用中。常见的有 “Apple Development”(开发证书)和 “Apple Distribution”(发布证书)。
- 私钥 (Private Key): 与你的开发者证书配对生成。私钥是保密的,它允许你使用对应的证书进行签名。私钥必须存在于你的 Mac 上的钥匙串中,并且与用于签名的证书关联。
- App ID (Application Identifier): 这是一个唯一标识你的应用程序的字符串(通常是 Bundle ID 的逆序域名格式,如
com.yourcompany.yourapp
)。在 Apple Developer Portal 中创建,并与你的应用程序项目设置相匹配。 - Provisioning Profile (配置文件): 这是一个文件,将你的开发者证书、App ID 以及(对于开发和 Ad Hoc 分发)允许运行应用测试的设备列表关联起来。它授权你的应用在特定设备上运行或通过特定方式(如 App Store)分发。Provisioning Profile 也包含应用的授权信息(Entitlements),比如是否允许使用 Push Notifications、App Groups 等。
codesign
工具的工作就是验证和应用这些元素到你的应用二进制文件上。任何一个环节出现问题——证书过期、私钥丢失、App ID 不匹配、配置文件无效或缺少、甚至钥匙串权限问题——都可能导致签名失败。
排查步骤:从简单到复杂
以下是解决 command codesign failed
错误的详细步骤。请按照顺序尝试,每一步之后都尝试重新构建项目,看看问题是否解决。
步骤 1:执行一次彻底的清理和重新构建 (Clean Build Folder & Build)
这是解决 Xcode 中各种奇怪构建错误的“万能”第一步。它可以清除旧的构建产物和中间文件,这些文件有时可能损坏或包含过时的签名信息。
- 操作:
- 在 Xcode 菜单栏,选择
Product
->Clean Build Folder
。 - 等待清理完成。
- 再次选择
Product
->Build
。
- 在 Xcode 菜单栏,选择
如果问题依然存在,继续下一步。
2. 验证证书和 Provisioning Profile 的有效性和匹配性 (Verify Certificates and Provisioning Profiles)
这是导致 codesign failed
错误最常见的原因。需要检查以下几个方面:
2.1 检查 Xcode 项目设置中的签名配置
确保你的项目、Target 以及任何 Pods 项目或第三方依赖的签名设置是正确的。
- 操作:
- 选择你的项目文件(Project Navigator 顶部)。
- 选择你的 Target(通常与应用同名)。
- 导航到
Signing & Capabilities
选项卡。 - 检查
Team
是否选择了正确的 Apple Developer Team。 - 检查
Signing
部分:- 如果使用
Automatically manage signing
(自动管理签名),确保Team
选择正确,并且 Xcode 没有报告任何错误(例如 “Provisioning profile doesn’t include signing certificate” 或 “No profiles for ‘com.yourcompany.yourapp’ were found”)。如果 Xcode 报告错误,点击Enable Automatic
或按照提示修复。 - 如果手动管理签名(
Manual Signing
),确保Signing Certificate
和Provisioning Profile
选择了正确且有效的项。Provisioning Profile
下拉菜单应该显示可用的配置文件,并且与你选择的Signing Certificate
和Bundle Identifier
匹配。
- 如果使用
- 对于 Release 或 Archive 配置,通常需要选择 Distribution 证书和相应的 Provisioning Profile(如 App Store, Ad Hoc, Enterprise)。确保你在
Build Settings
->Signing
下检查了所有配置(Debug, Release, Any iOS SDK 等)。展开Code Signing Identity
和Provisioning Profile
部分,确保每个需要的配置都指向正确的证书类型和配置文件。
2.2 检查 Apple Developer Portal 中的证书和 Profile
确保你在 Apple Developer 账户中有有效且正确的证书和 Provisioning Profile。
- 操作:
- 登录 Apple Developer Portal。
- 导航到
Certificates, Identifiers & Profiles
。 - 检查 Certificates:
- 在
Certificates
部分,确认你需要使用的开发(Development)或发布(Distribution)证书存在且状态是Active
,没有过期。 - 如果你需要发布应用(Archive),确保你有 Apple Distribution 或相应的 Enterprise Distribution 证书。
- 注意证书的类型(iOS Distribution, Apple Distribution, iOS Development, Apple Development 等)。
- 在
- 检查 Identifiers:
- 在
Identifiers
部分,确认你的 App ID (Bundle ID
) 存在,并且与你的 Xcode 项目中的Bundle Identifier
精确匹配(包括大小写)。 - 检查 App ID 下配置的 Capabilities(App Services),确保它们与你的项目中的
Signing & Capabilities
选项卡下启用的功能一致。
- 在
- 检查 Profiles:
- 在
Profiles
部分,确认你需要使用的 Provisioning Profile 存在且状态是Active
,没有过期或显示Invalid
。 - 确认 Profile 的类型(iOS App Development, App Store, Ad Hoc, In House 等)与你的构建目的相符。
- 点击进入 Profile 详情,确认它包含了正确的 App ID、正确的证书以及(如果需要)正确的测试设备列表。
- 如果 Profile 显示
Invalid
或过期,或者不包含正确的证书/App ID/设备,你需要编辑或重新生成并下载它。 - 如果怀疑 Profile 有问题,即使它显示为 Active,也尝试重新生成并下载它。 下载后,双击
.mobileprovision
文件,它会被自动添加到 Xcode 中。
- 在
2.3 检查你的 Mac 上的钥匙串访问 (Keychain Access)
确保签名所需的证书和私钥存在于你的 Mac 的钥匙串中,并且被系统信任。
- 操作:
- 打开
应用程序
->实用工具
->钥匙串访问
(Keychain Access)。 - 在左侧导航栏,选择
登录
(login) 钥匙串(这是最常见存放开发者身份的地方)。 - 在底部左侧选择
证书
(Certificates)。 - 在右侧列表中搜索你的证书名称(例如 “Apple Development: Your Name (Team ID)” 或 “Apple Distribution: Your Name (Team ID)”)。
- 检查证书状态:
- 确保证书存在,并且旁边有一个小的蓝色加号图标 (+) 在一个圆圈里。这表示证书被系统信任。如果没有蓝色加号,右键点击证书,选择
显示简介
(Get Info),展开信任
(Trust) 部分,将使用此证书时
(When using this certificate) 设置为始终信任
(Always Trust)。 - 确保证书没有显示为过期或吊销。
- 确保证书存在,并且旁边有一个小的蓝色加号图标 (+) 在一个圆圈里。这表示证书被系统信任。如果没有蓝色加号,右键点击证书,选择
- 检查私钥:
- 展开你的证书旁边的箭头。你应该能看到一个与之关联的私钥。私钥的图标是一个带有黑色钥匙的方形。
- 重要: 签名需要同时有证书和与之配对的私钥。如果只有证书而没有私钥,或者私钥图标显示为灰色或有其他异常,你将无法进行签名。这通常发生在你在另一台 Mac 上生成了证书并导出了
.cer
文件,但在当前 Mac 上导入.cer
文件时没有同时导入私钥(需要导出为.p12
文件才能包含私钥)。 - 如果私钥丢失: 你可能需要回到 Apple Developer Portal 吊销 (Revoke) 该证书(如果它是个人证书)并重新生成一个新的证书(这将同时生成新的私钥)。如果是团队共享的证书,需要找到拥有原始私钥的团队成员,让他们导出
.p12
文件并分享给你。
- 在左侧导航栏,选择
登录
(login) 钥匙串,然后在底部左侧选择我的证书
(My Certificates)。这里只列出同时拥有证书和私钥的项。确保你需要用于签名的证书和私钥对在这里出现。
- 打开
2.4 重新下载 Provisioning Profiles
即使在 Developer Portal 中 Profile 看起来正常,重新下载并添加到 Xcode 也常常能解决问题。
- 操作:
- 登录 Apple Developer Portal,导航到
Profiles
。 - 找到相关的 Provisioning Profile,编辑它(可以不做任何修改,仅为触发更新)或直接下载它。
- 双击下载的
.mobileprovision
文件。它会自动导入到 Xcode 和你的 Mac 中。 - 或者,在 Xcode 中,进入
Xcode
->Preferences
->Accounts
。选择你的 Apple ID,点击Manage Certificates...
检查证书,点击Download Manual Profiles
下载与你的账户相关的 Provisioning Profiles。
- 登录 Apple Developer Portal,导航到
步骤 3:检查钥匙串访问权限和状态 (Keychain Access Permissions and Status)
有时,钥匙串本身的问题或权限设置不当会导致签名失败。
- 操作:
- 打开
钥匙串访问
。 - 确保
登录
(login) 钥匙串是解锁状态。如果它是锁着的,Xcode 在尝试访问私钥时可能会失败。你可以通过右键点击登录
钥匙串并选择解锁钥匙串 "登录"
(Unlock Keychain “login”) 来解锁。 - 尝试修复钥匙串:这不是 macOS 的一个直接功能,但在某些情况下,重启 Mac 可以解决临时的钥匙串问题。更高级的排查可能涉及使用
Keychain First Aid
工具(已在 macOS Sierra 10.12.1 中移除)。如果怀疑钥匙串损坏,可能需要重置钥匙串,但这会丢失所有保存的密码和证书,是非常极端的手段,通常不推荐。
- 打开
步骤 4:清理 Xcode 缓存和 Derived Data (Clean Xcode Cache and Derived Data)
与清理构建文件夹类似,清除 Xcode 的缓存和派生数据可以移除可能导致问题的损坏或过时文件。
- 操作:
- 关闭 Xcode。
- 手动删除 Derived Data 文件夹的内容。默认路径是
~/Library/Developer/Xcode/DerivedData/
。你可以在 Finder 中按下Shift + Command + G
,输入路径前往该文件夹,然后删除其中的所有内容(或只删除你当前项目对应的文件夹)。 - 手动删除 Xcode 的缓存文件。默认路径是
~/Library/Caches/com.apple.dt.Xcode/
。同样,前往该文件夹并删除其中的内容。 - 重新打开 Xcode。
- 再次执行
Product
->Clean Build Folder
。 - 尝试
Product
->Build
。
5. 验证 Bundle Identifier 和 App ID 的一致性 (Verify Bundle Identifier Consistency)
确保你的 Xcode 项目中的 Bundle Identifier 与你在 Provisioning Profile 和 Apple Developer Portal 中使用的 App ID 精确匹配。
- 操作:
- 在 Xcode 中,选择你的项目文件。
- 选择你的 Target。
- 导航到
General
选项卡。 - 在
Identity
部分,检查Bundle Identifier
的值。 - 登录 Apple Developer Portal,检查你的 App ID 的精确字符串。
- 检查你的 Provisioning Profile 的详情,确认其中包含正确的 App ID。
- 确保这三个地方的字符串完全一致。
6. 检查 Capabilities (Entitlements) 的匹配性
如果你使用了推送通知、App Groups、Keychain Sharing 等 Capabilities,确保它们在以下三个地方都正确配置:
- 操作:
- Xcode 项目中的
Signing & Capabilities
选项卡。 - Apple Developer Portal 中你的 App ID 的配置。
- 生成 Provisioning Profile 时,Profile 中包含了这些 Entitlements。
- Xcode 项目中的
不一致的 Capabilities 会导致 codesign
在尝试写入 Entitlements 时失败。
7. 检查 Build Settings 中的 Code Signing Identity
虽然 Signing & Capabilities
选项卡是配置签名的首选地方,但 Build Settings
下的 Code Signing Identity
和 Provisioning Profile
设置会覆盖它(特别是在配置复杂或包含多个 Build Configurations 时)。
- 操作:
- 选择你的项目或 Target。
- 导航到
Build Settings
选项卡。 - 搜索
Code Signing Identity
。 - 展开所有配置(Debug, Release, Any iOS SDK 等)。
- 确保每种配置都指向了正确的证书类型(例如,
iOS Developer
或iOS Distribution
)。通常设置为Apple Development
或Apple Distribution
,或者使用iOS Developer
/iOS Distribution
让 Xcode 自动选择。 - 搜索
Provisioning Profile
。 - 展开所有配置,确保每种配置都选择了正确或合适的 Provisioning Profile。使用
Automatic
通常是一个不错的选择,如果手动管理,确保选择了正确的 Profile UUID 或名称。
8. 检查 Xcode 版本和 Command Line Tools
确保你的 Xcode 版本与项目兼容,并且安装了正确的命令行工具。
- 操作:
- 检查你使用的 Xcode 版本是否是最新的,或者至少是支持你的操作系统和项目 SDK 的版本。
- 安装或更新命令行工具:
- 打开
终端
(Terminal)。 - 运行命令:
xcode-select --install
- 如果已经安装,它会提示。如果需要安装,按照提示操作。
- 打开
- 确保 Xcode 使用了正确的命令行工具路径:
- 在 Xcode 菜单栏,选择
Xcode
->Preferences
->Locations
。 - 检查
Command Line Tools
下拉菜单是否选择了当前安装的 Xcode 版本。
- 在 Xcode 菜单栏,选择
9. 检查项目文件和文件权限 (Project Files and Permissions)
虽然不常见,但项目文件本身损坏或特定文件权限问题有时可能干扰构建过程,包括代码签名。
- 操作:
- 检查项目文件(
.xcodeproj
或.xcworkspace
)是否存在于一个你有读写权限的目录下。 - 在 Finder 中,右键点击你的项目文件夹,选择
获取信息
(Get Info),检查底部的共享与权限
(Sharing & Permissions),确保你的用户账户有读写权限。可以尝试点击齿轮图标并选择应用到包含项...
(Apply to enclosed items…)。 - 尝试将项目复制到另一个位置(如桌面)并从那里打开和构建。
- 检查项目文件(
10. 检查第三方依赖和嵌入式框架 (Third-Party Dependencies and Embedded Frameworks)
如果你的项目使用了 CocoaPods 或手动嵌入了第三方框架,这些框架自身的签名设置可能会与你的主项目发生冲突。
- 操作:
- 对于 CocoaPods 项目 (
.xcworkspace
),进入 Pods 项目,检查每个 Library 或 Framework Target 的Build Settings
->Code Signing Identity
和Provisioning Profile
。确保它们与你的主项目设置兼容,或者至少没有设置为 Manual Signing 并指向一个无效的 Profile。通常,将它们设置为iOS Developer
/iOS Distribution
或Automatic
让 Xcode 统一管理是一个好方法。 - 对于手动嵌入的框架,确保框架本身已经被正确签名(或者你需要在构建过程中对其进行嵌入式签名)。在你的 Target 的
General
->Frameworks, Libraries, and Embedded Content
中,对于嵌入的项,Embed
选项通常应该设置为Embed & Sign
。确保你的签名配置能够覆盖并正确签发这些嵌入项。
- 对于 CocoaPods 项目 (
11. 使用命令行工具进行高级调试 (Advanced Debugging with Command Line Tools)
codesign
失败的根本原因是底层的 codesign
命令行工具返回了错误。直接运行这个工具并查看其详细输出通常能提供更具体的错误信息。
- 操作:
- 定位问题文件: 首先,你需要知道是哪个文件签名失败了。在 Xcode 的构建输出中,通常会有更详细的错误信息,指示是哪个二进制文件(例如
.app
包)或嵌入的文件签名失败。查找包含codesign
命令行的那一行。 - 获取构建路径: 构建失败后,不要清理项目。在 Finder 中找到你的构建产物(通常在 Derived Data 文件夹里,例如
DerivedData/YourApp-abcdefg/Build/Products/Debug-iphonesimulator/YourApp.app
或Release-iphoneos/YourApp.app
)。右键点击.app
文件,按住Option
键,选择将“YourApp.app”的路径拷贝为路径名称
(Copy “YourApp.app” as Pathname)。 - 运行
codesign
命令进行验证: 打开终端
。运行以下命令,将/path/to/YourApp.app
替换为你刚才复制的路径:
bash
codesign --verify --verbose=4 /path/to/YourApp.app
或者使用你的签名身份尝试签名(这更接近 Xcode 做的事情,但要小心,这可能会修改文件,最好在拷贝出来的文件上测试):
bash
codesign --force --timestamp --sign "Your Signing Identity Name" /path/to/YourApp.app --entitlements /path/to/YourApp.entitlements
你需要替换"Your Signing Identity Name"
为你在钥匙串或 Xcode build settings 中看到的完整证书名称(例如"Apple Development: Your Name (Team ID)"
)。/path/to/YourApp.entitlements
是你的项目中的 Entitlements 文件路径(通常是YourApp.entitlements
)。 - 分析输出:
codesign
命令的输出通常会更详细地说明失败的原因,例如找不到私钥、证书不受信任、Entitlements 文件问题、文件损坏等。仔细阅读这些输出,它可能会直接指出问题的根源。
- 定位问题文件: 首先,你需要知道是哪个文件签名失败了。在 Xcode 的构建输出中,通常会有更详细的错误信息,指示是哪个二进制文件(例如
12. 检查系统或软件冲突
极少数情况下,macOS 系统本身的问题、第三方安全软件、VPN 或其他系统级软件可能会干扰代码签名过程。
- 操作:
- 重启 Mac。
- 尝试在安全模式 (Safe Mode) 下构建(这将禁用一些第三方启动项和缓存)。
- 暂时禁用或卸载第三方杀毒软件或防火墙,看是否解决问题(请谨慎操作并确保了解风险)。
- 确保没有 VPN 或网络代理配置干扰到与 Apple 服务器的通信(在下载证书、Profile 或验证状态时可能需要)。
13. 寻求帮助并提供信息
如果以上步骤都无法解决问题,你可能需要向社区或 Apple Support 寻求帮助。在提问时,提供尽可能多的背景信息至关重要:
- 你遇到的具体错误信息(完整的 Xcode 构建输出)。
- 你的 Xcode 版本和 macOS 版本。
- 你尝试的构建类型(Debug, Release, Archive)。
- 你正在使用的签名方法(Automatic 或 Manual)。
- 你在 Apple Developer Portal、钥匙串访问和 Xcode 项目设置中看到的证书和 Provisioning Profile 状态。
- 你已经尝试过的排查步骤。
预防未来的 codesign failed
错误
- 使用自动管理签名 (Automatically manage signing): 对于大多数项目,让 Xcode 自动处理证书和 Provisioning Profile 是最简单且最不容易出错的方法。
- 定期检查证书和 Profile 的有效期: 在 Apple Developer Portal 中设置提醒或定期登录检查。
- 保持 Xcode 和 macOS 更新: 新版本通常修复了签名相关的 Bug。
- 维护干净的钥匙串: 定期清理过期或重复的证书和私钥。
- 理解团队签名: 如果在团队中工作,确保团队成员之间共享必要的 Distribution 证书和私钥(通常通过
.p12
文件),并确保所有人使用相同的 Provisioning Profiles。
总结
command codesign failed with a nonzero exit code
是一个信号,表明应用程序的代码签名过程未能成功完成。尽管错误信息本身不具体,但通过系统地检查证书、私钥、App ID、Provisioning Profile 以及相关的 Xcode 和系统配置,通常可以找到问题的根源。从简单的清理和重新构建开始,逐步检查签名设置、钥匙串、Developer Portal 配置,并利用命令行工具进行深入诊断,是解决这个问题的有效路径。记住,耐心和细致是解决这类配置问题的关键。希望这篇详细的指南能帮助你成功解决 codesign failed
错误,让你的应用程序顺利通过构建和签名流程!