创建 iOS/OSX 框架:在分发给其他开发人员之前是否有必要对它们进行代码签名?

Creating iOS/OSX Frameworks: is it necessary to codesign them before distributing to other developers?

我正在学习如何创建 iOS 和 OSX 框架。让我们以 iOS 为例,到目前为止,以下步骤对我有效:

  1. xcodebuild 框架使用 -sdk iphonesimulator 和构建操作
  2. 使用 -sdk iphoneos 和构建操作的 xcodebuild 框架
  3. 使用 lipo 工具创建通用二进制文件,以便 lipo -info 产生预期的结果:

Architectures in the fat file: Foo.framework/Foo are: i386 x86_64 armv7 arm64

问题是:

  1. 我了解到我的框架可以由使用它的开发人员重新签名:"Code Sign on Copy" 但我不明白它的先决条件是什么,即 应该在将通用二进制文件分发给其他开发人员之前,我添加了协同设计步骤以使用我的签名身份对该通用二进制文件进行协同设计?

  2. 如果前一个是肯定的 - 我应该使用我的 "iPhone Distribution: ..." 身份还是 "iPhone Developer: ..." 就足够了(这样我的框架就成为某些 iOS 项目的一部分通过各种验证尤其是 App Store 验证)?.

我回答的背景是 "CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.3'",我在许多第三方框架和 Carthage#235 or "code object is not signed at all" (one example: issue I reported on Realm#1998 上看到过。

所以我想确保我的框架的用户在使用它们时不会遇到任何代码签名问题。

P.S。当这个问题不是应用于单个开发人员而是应用于作为框架供应商的组织时,这个问题会变得更加有趣。

从阅读 Carthage 存储库上的链接线程来看,它似乎相对简单。如果您要分发二进制框架,则需要对其进行代码签名,如果您通过 carthage 或 cocoa pods 分发源代码,则不需要,因为这些工具会通过不同的方法处理此问题。

分发二进制框架时需要对其进行代码签名的原因是 Xcode 不会在没有代码签名的情况下生成框架二进制文件。如果您尝试不对二进制框架进行代码签名,您会收到此错误:

CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'

使用(iPhone 开发人员或 iPhone 发行版)对框架进行代码签名并不重要,因为正如您指出的那样,框架将使用 "code sign on copy"设置。这意味着当您的框架被复制到他们的应用程序中时,您的框架将根据来自框架消费者的开发人员配置文件的适当证书重新编码设计。这意味着 App Store 不会有任何问题,因为它只会看到来自框架消费者的最终代码签名。

归根结底,您最好对 .framework 二进制文件进行代码签名,因为您不想维护一个奇特的构建过程,而且 Xcode 只会输出您签名的框架不应偏离默认值太远。无论如何,这并不重要,因为最终消费者将重新签署它。

我打开了赏金:"Looking for an answer drawing from credible and/or official sources."但从那以后就没有收到过。

虽然@jackslash 提供的答案是正确的,但它只讲述了故事的一部分,所以我想以我问这个问题时希望看到的方式写我自己的。

这个答案的实际时间是:2015 年 7 月。很可能情况会发生变化。

首先让我们断言,框架的正确代码签名所需的操作应分为框架的开发人员必须采取的步骤和框架的消费者必须采取的步骤必须带。

TLDR;

对于 OSX 框架:开发人员可以自由分发 OSX 框架而无需对其进行代码签名,因为消费者无论如何都会对其进行重新代码设计。

对于 iOS 框架:开发人员可以自由分发 iOS 框架而无需对其进行代码签名,因为消费者无论如何都会对其进行重新代码设计,但开发人员被 Xcode 在为 iOS 设备构建时共同设计他们的框架。

因为雷达:"iOS frameworks containing simulator slices can't be submitted to the App Store" iOS 框架的消费者被迫 运行 像 "copy_frameworks" 或 "strip_frameworks" 这样的特殊脚本使用 lipo -remove 从 iOS 框架中剥离模拟器切片并重新编码设计剥离的框架,因为此时它的代码签名标识无论它是(或不是)作为 [=10= 的副作用被删除] 操纵.

下面是更长的答案。


这个答案不是 "drawing from credible and/or official sources" 而是基于大量经验观察。

经验观察 #1:消费者不关心,因为他们会重新编码设计从开发人员那里收到的框架

Github 上知名开源项目的二进制框架分发版未进行代码签名。命令 codesign -d -vvvv 给出: "code object is not signed at all" 我曾经探索过的所有二进制 iOS 和 OSX 框架。一些示例:ReactiveCocoa and Mantle, Realm, PromiseKit.

从这一观察可以清楚地看出,这些框架的作者打算由消费者代表他们共同签名,即消费者必须在 "Embed frameworks" 提供的构建阶段使用 "Code Sign on Copy" 标志 Xcode 或使用一些自定义 shell 手动执行相同操作的脚本:代表消费者的代码设计框架。

我没有找到任何相反的例子:开源框架将在其中使用代码签名身份进行分发,所以在其余的答案中,我假设这种广泛采用的方法是正确的:框架开发人员不需要将他们的框架分发给其他具有代码签名身份的开发人员,因为消费者无论如何都会重新代码设计它

经验观察 #2 仅适用于 iOS,完全是开发人员的关注点

虽然消费者不关心他们从开发者那里收到的框架是否经过了代码签名,但开发者在为 iOS 设备 因为否则 Xcode 不会构建:CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'。引用 Justin Spahr-Summers

OS X frameworks don't need to be codesigned at build... Unfortunately, Xcode does require that iOS frameworks be codesigned at build time.

这很好地回答了我的问题 #2:"iPhone Developer" 身份足以哄骗 Xcode 以便它可以为设备构建 iOS 框架。 This comment on Carthage#339 说同样的话。

经验观察 #3:lipo 工具

lipo 工具的特定行为:当应用于框架二进制文件时,它总是递归地从中删除任何代码签名身份lipo -create/-remove codesigned framework ... -> not codesigned framework

这可能是为什么观察 #1 中的所有示例根本没有进行协同签名的答案:它们的协同签名身份在应用 lipo 后被吹走了,但是根据观察 #1 消费者并不关心它很好。

此观察与关于 AppStore 的下一个观察 #4 特别相关。

经验观察 #4:iOS 包含模拟器切片的框架无法提交到 App Store

这在以下方面得到广泛讨论:Realm#1163 and Carthage#188 and radar is opened: rdar://19209161

这完全是消费者关心的问题:对于消费者在其应用程序中包含的 iOS 通用框架,在构建应用程序时,他们必须 运行 特殊脚本(自定义 运行 脚本阶段) 从该框架的二进制文件中删除模拟器切片,以便应用程序可以通过 AppStore 验证。

我在 Realm 中找到的二进制框架的好例子:strip-frameworks.sh

它使用lipo删除除${VALID_ARCHS}以外的所有架构切片,然后用消费者的身份重新编码设计它——这是观察的地方# 3 开始:由于对它进行了 lipo 操作,框架将被重新设计。

Carthage 有 CopyFrameworks.swift 脚本,它对 Consumer 包含的所有框架做同样的事情:它剥离模拟器切片并代表 Consumer 重新编码设计框架。

还有好文章:Stripping Unwanted Architectures From Dynamic Libraries In Xcode.


现在从开发人员和消费者的角度概述生成 iOS 和 OSX 所需的步骤。第一个比较简单的:

OSX

开发者:

  1. 构建OSX框架
  2. 交给消费者

开发人员不需要任何代码签名活动。

消费者:

  1. 从开发人员那里收到 OSX 框架
  2. 将框架复制到 Frameworks/ 目录,并作为 "Code Sign on Copy" 流程的一部分代表消费者自动对其进行代码签名。

iOS

开发者:

  1. 为设备构建 iOS 框架。 Xcode需要协同设计,"iPhone Developer"身份就够了。
  2. 为模拟器构建 iOS 框架。
  3. 使用从前两个生成通用 iOS 框架的 lipo。此时 1 步的代码签名身份丢失:通用框架二进制 "is not signed at all" 但这很好,因为 "Consumer does not care".
  4. 交给消费者

消费者:

  1. 从开发人员那里收到 iOS 框架
  2. 将框架复制到 Frameworks/ 目录(根据步骤 3 中的脚本,此步骤可能是多余的。)
  3. 使用特殊脚本作为构建过程的一部分:该脚本从 iOS 框架中剥离模拟器切片,然后代表消费者重新编码设计。