为什么 Xcode 复制嵌入式框架 headers 的行为因目标而异?

Why does Xcode behavior of copying embedded framework headers differ across targets?

我正在开发一个有两个构建目标的 Mac 项目。我的一位用户报告无法安装其中一个目标。

好的,让我们用RB App Checker Lite.

检查一下

有意思。这个目标缺少一些资源,我们称它为 Example 2. 为了确定,我检查了另一个目标 Example 1,那个没有任何验证问题。

所以目标是不同的,因为它涉及复制 headers 嵌入在 HockeySDK/CrashReporter 框架中。代码签名期望这些 headers 存在,但它们不存在,并且签名验证失败。

我还检查了磁盘上的捆绑包。果然,示例 1 中有 headers 而示例 2 中没有。

我的下一个问题是,为什么构建的目标不同?为什么示例 1 包含 headers 而示例 2 不包含?我查看了目标的构建日志,果然,“复制框架”阶段有所不同。

示例 1 日志:

PBXCp Libraries/HockeySDK-Mac/HockeySDK.framework /Users/jaanus/Library/Developer/Xcode/DerivedData/Example-chptxdrwwlafgodccbiqclccqjkl/Build/Intermediates/ArchiveIntermediates/Example\ 1/InstallationBuildProductsLocation/Applications/Example\ 1.app/Contents/Frameworks/HockeySDK.framework
    cd /Users/jaanus/dev/Example/tool
    builtin-copy -exclude .DS_Store -exclude CVS -exclude .svn -exclude .git\
    -exclude .hg -resolve-src-symlinks /Users/jaanus/dev/Example/tool/Libraries/HockeySDK-Mac/HockeySDK.framework /Users/jaanus/Library/Developer/Xcode/DerivedData/Example-chptxdrwwlafgodccbiqclccqjkl/Build/Intermediates/ArchiveIntermediates/Example\ 1/InstallationBuildProductsLocation/Applications/Example\ 1.app/Contents/Frameworks

示例 2 日志:

PBXCp Libraries/HockeySDK-Mac/HockeySDK.framework /Users/jaanus/Library/Developer/Xcode/DerivedData/Example-chptxdrwwlafgodccbiqclccqjkl/Build/Intermediates/ArchiveIntermediates/Example\ 2/InstallationBuildProductsLocation/Applications/Example\ 2.app/Contents/Frameworks/HockeySDK.framework
    cd /Users/jaanus/dev/Example/tool
    builtin-copy -exclude .DS_Store -exclude CVS -exclude .svn -exclude .git\
    -exclude .hg -exclude Headers -exclude PrivateHeaders -resolve-src-symlinks /Users/jaanus/dev/Example/tool/Libraries/HockeySDK-Mac/HockeySDK.framework /Users/jaanus/Library/Developer/Xcode/DerivedData/Example-chptxdrwwlafgodccbiqclccqjkl/Build/Intermediates/ArchiveIntermediates/Example\ 2/InstallationBuildProductsLocation/Applications/Example\ 2.app/Contents/Frameworks

果然,示例 2 builtin-copy 命令包含额外的参数 -exclude Headers -exclude PrivateHeaders,这导致 headers 不被包含。

现在,问题是,为什么构建一个目标排除 headers 而另一个不排除?

我一遍又一遍地检查了目标的构建设置,看起来与我一样。我似乎没有办法影响 builtin-copy 的行为。但很明显,有什么在影响它。

我现在使用我不喜欢的丑陋解决方法修复了它。我真的很想了解这里发生了什么以及如何解决这个问题。

我的 Xcode 版本是 6.1.1 (6A2008a),目前可从 App Store 下载。

Xcode 非常有选择性地决定向您展示什么,因此在调查此类问题时,第一步是查看 project.pbxproj 文件 手工.

打开 Example 1.xcodeproj/project.pbxproj 并导航至复制框架的说明(我搜索 "Copy Framework Files"),您会看到如下内容:

BCAC434BC9F0E2F78087CA01 /* HockeySDK.framework in Copy Framework Files */ = {isa = PBXBuildFile; fileRef = BCAC434BC9F0E2F78087CA01 /* HockeySDK.framework */; };

Example 2.xcodeproj/project.pbxproj中的类似物:

F19543FC17EC99FB62CA62C8 /* HockeySDK.framework in Copy Framework Files */ = {isa = PBXBuildFile; fileRef = F19543FC17EC99FB62CA62C8 /* HockeySDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };

从那里,很清楚。示例 2 的复制指令后面有一些附加设置:

settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); };

因此,对于 "fix" 这个问题,您可以根据需要添加或删除 RemoveHeadersOnCopy 设置。

遗憾的是,这并未反映在 UI 中。 Xcode 的某些版本似乎只会添加它(我怀疑它与代码签名复选框有关,但我无法重现任何值得一提的内容)。