我正在学习如何创建iOS和OSX框架。我们以iOS为例,到目前为止,以下步骤对我有用:
lipo -info
产生预期:胖文件中的体系结构:Foo.framework / Foo是:i386 x86_64 armv7 arm64
问题是:
我的答案的背景是“CodeSign错误:SDK'iOS 8.3'中的产品类型'Framework'需要代码签名”,我在许多第三方框架和Carthage#235上看到过,或者“代码对象根本没有签名” “(一个例子:我在Realm#1998报道的问题。
所以我想确保我的框架用户在使用它们时不会遇到任何代码签名问题。
附:当应用于单个开发人员而不是应用于作为框架供应商的组织时,此问题会变得更加有趣。
我打开了赏金:“寻找可信和/或官方消息来源的答案。”但从那时起就没有收到过。
虽然@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框架剥离模拟器切片并重新编码剥离的框架,因为此时它的代码签名身份无论它是什么(或不是)被删除作为lipo -remove
操纵的副作用。
接下来是更长的答案。
这个答案不是“来自可信和/或官方来源”,而是基于一些经验观察。
经验观察#1:消费者不关心,因为他们将重新编码他们从开发者处收到的框架
Github上众所周知的开源项目的二进制框架分布不是代码签名的。命令codesign -d -vvvv
给出了:我曾经探索过的所有二进制iOS和OSX框架上的“代码对象根本没有签名”。一些例子:ReactiveCocoa和Mantle,Realm,PromiseKit。
根据这一观察结果,很明显这些框架的作者打算由Consumer代表他们进行编码,即消费者必须使用Xcode提供的“嵌入框架”构建阶段中的“Code Sign on Copy”标记或使用一些自定义shell手动执行相同操作的脚本:代表消费者代码签署框架。
我没有找到任何相反的例子:开源框架将在其中分配代码签名身份,因此在其余的答案中我假设这种广泛采用的方法是正确的:没有必要使用框架Developer将他们的框架分发给其他具有代码签名身份的开发人员,因为消费者无论如何都会对其进行重新编码。
Empiric观察#2仅适用于iOS,完全是开发人员关心的问题
虽然Consumer不关心他们从Developer收到的框架是否已经过编码,但开发人员仍然需要将他们的iOS框架作为其构建过程的一部分进行编码,因为否则Xcode不会构建:CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'
。引用Justin Spahr-Summers:
OS X框架不需要在构建时进行编码...不幸的是,Xcode确实需要在构建时对iOS框架进行编码。
这个问题很好地回答了我的问题#2:“iPhone Developer”身份足以哄骗Xcode,以便它可以为设备构建iOS框架。 This comment on Carthage#339说同样的话。
经验观察#3:脂肪工具
lipo工具的特定行为:当应用于框架二进制时,它总是以递归方式从其中删除任何代码标识:lipo -create/-remove codesigned framework ... -> not codesigned framework
。
这可能是一个答案,为什么观察#1中的所有例子根本都没有编码:他们的代码签名身份在应用脂肪后被吹走但是因为根据观察#1消费者并不关心它是好的。
这个观察结果与下一个关于AppStore的观察#4特别相关。
经验观察#4:包含模拟器切片的iOS框架无法提交到App Store
这在以下广泛讨论:Realm#1163和Carthage#188和雷达开放:rdar://19209161。
这完全是消费者的关注点:对于Consumer在其应用程序中包含的iOS通用框架,在构建应用程序时,它们必须运行特殊脚本(自定义运行脚本阶段),从该框架的二进制文件中删除模拟器片段,以便应用程序可以通过AppStore验证。
我在Realm中找到的二进制框架的好例子:strip-frameworks.sh。
它使用lipo
删除${VALID_ARCHS}
以外的所有体系结构片段,然后用消费者的身份重新对其进行编码 - 这是观察#3开始的地方:框架由于对其进行脂肪操作而被重新编码。
Carthage有CopyFrameworks.swift脚本,它对Consumer所包含的所有框架都做同样的事情:它剥离模拟器切片并代表Consumer重新编码框架。
还有好文章:Stripping Unwanted Architectures From Dynamic Libraries In Xcode。
现在概述从开发人员和消费者的角度生成iOS和OSX所需的步骤。首先是更容易的一个:
OSX
开发商:
开发人员无需进行代码签名活动。
消费者:
iOS版
开发商:
消费者:
从阅读Carthage回购中的链接线程看起来相对简单。如果您正在分发二进制框架,则需要对其进行编码签名,如果您通过carthage或cocoa pod分发源代码,则不会因为这些工具通过不同方法处理此问题。
在分发二进制框架时,您需要对其进行编码签名的原因是Xcode不会生成框架二进制文件而不对其进行代码签名。如果您尝试不对二进制框架进行编码签名,则会收到以下错误:
CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'
使用哪个身份标识框架(iPhone Developer或iPhone Distribution)并不重要,因为正如您所指出的那样,框架将使用“代码登录复制”设置进行重新编码。这意味着当您的框架被复制到其应用程序中时,框架将由框架使用者的开发人员配置文件中的相应证书重新编码。这意味着App Store不会出现任何问题,因为它只会看到框架消费者的最终代码签名。
在一天结束的时候,您可能还需要对.framework二进制文件进行代码签名,因为您不希望维护异常的构建过程,并且由于Xcode只输出已签名的框架,因此您不应该移动太远离默认值。无论如何,这并不重要,因为最终消费者将重新签署它。
斯坦尼斯拉夫潘克维奇上面的答案是非常有效和正确的。但请注意,从Xcode 9.4开始,IDE将要求您禁用iOS Cocoa Touch Frameworks的代码签名。 Apple现在说不建议你为.framework签名。
我希望这有帮助。