Xcode如何查找隐式目标依赖关系?

22

Xcode有时会自动查找依赖项。当我自己定义关系并且变懒时,我认为这是可以的...

但更多时候,我会遇到一个已存在的(中等到大型)项目,其中包含多个目标。由于该项目是由他人创建的,因此我发现很难理解哪些目标依赖于什么,因为不是所有关系都是显式的。

Xcode用什么规则来查找这样的关系?(我希望我能理解逻辑并在脑海中运行它,并可能在将来节省一些时间)或者什么使一个目标具有另一个目标的隐式依赖关系资格?

一个目标及其创建的产品可以与另一个目标相关联。如果一个目标需要另一个目标的输出才能构建,则第一个目标被称为依赖于第二个目标。如果两个目标在同一个工作区中,则Xcode可以发现依赖关系,在这种情况下,它以所需顺序构建产品。这种关系称为隐式依赖关系。

来源:iOS开发者文库 → Xcode概念 → Xcode目标


在同一个工作区内(.proj 中还有 .workspace),或者在构建阶段中添加目标依赖。此外,如果一个目标使用另一个目标的产品,Xcode 将自动先构建另一个目标。 - Klein Mioke
我发现在构建复杂项目时,隐式目标依赖关系会失败,例如涉及多个名称类似但针对不同平台的框架/库。手动指定所有内容是唯一能让我的watchOS/tvOS/iOS项目构建成功的方法。 - DrMickeyLauer
2个回答

20

这个答案适用于Xcode 8.x,我认为也适用于Xcode 9.0。

首先,你需要确保在你要构建的Scheme的Build面板中启用了“查找隐式依赖项”。

目标“A”可以通过以下两种方式之一被“隐式”依赖于目标“B”:

  1. 目标A有一个“链接二进制文件库”构建阶段,在其列表中具有与B产品相同名称的库。该产品可以位于同一项目或工作区中的另一个项目中。请注意,我说过“同名”。仅因为您从目标A选择了libA.a,并不意味着如果您在不同目标中具有另一个libA.a产品,隐式依赖关系将构建它。有关详细信息,请参见下文。
  2. 目标A具有“复制文件”阶段,该阶段复制具有与B产品匹配的基本名称的文件。通常,“复制文件”构建阶段无法引用与其目标不在同一项目中的文件,但是如果您创建一个虚拟文件供“复制文件”阶段复制且该文件具有与B产品相同的名称,则可以设置跨项目的依赖关系。例如,如果您有包含两个项目ProjectA和ProjectB的工作区。ProjectA具有创建libA.a的TargetA,而ProjectB具有创建libB.a的TargetB。TargetA可以通过在TargetA的一部分中具有名为libB.a的“虚拟”零字节文件来让TargetB构建libB.a,这将足以使libB.a被生成,即使在“复制文件”阶段引用的libB.a与TargetB构建的产品输出完全不同。如果选中“仅在安装时复制”复选框,则Xcode实际上不会执行复制,但仍将解析依赖项。您实际上可以从驱动器中删除该虚拟文件,该文件仅用于放置在“复制文件”阶段中的内容(但必须将其保留在项目中)。

那么,为什么有人要做“2”这种可怕的事情呢?我能想出几个原因。

  1. TargetA需要通过TargetB复制/生成一些文件,但TargetB没有生成要链接的库。你可以通过让TargetB生成一个小的虚拟库来解决这个问题,但可能会因其他原因而很痛苦。
  2. 假设我有projectA、targetA和libA.a(以及项目B、C和D的等效物),libA.a依赖于需要先构建libD.a的libB.a和libC.a(可能还包括一些头文件和/或源文件)。您可以使用“Link With Libraries”阶段(即方案#1)完成所有操作,但在这种情况下,在最终链接版本的libA中会有两个副本的libD中的.o文件。如果您将其深入到足够深的程度(例如,一个具有40个项目的工作区,这些项目在彼此之间具有不同级别的依赖关系),您将很快得到巨大的库文件,其中包含几个相同的.o文件,并且链接时间将变得可怕。

如果您认为这些是人为制造的情况,那么我目前正在从一系列显式依赖项移动遗留代码到隐式依赖项中。为什么要移至隐式依赖项?因为Xcode中的显式依赖关系需要项目嵌套,一旦您拥有足够的显式依赖关系,项目浏览器就会变得非常缓慢,并且您会看到许多随机的Xcode内部等待符号。

如果您恰好在同一个工作区内有两个目标生成具有相同名称的产品,并且从第三个目标中依赖于它们,会发生什么?隐式依赖项将选择一个。它似乎是基于产品的基本名称进行匹配(因此foo/bar.a和baz/bar.a是相同的),并且将选择找到的第一个。


1
第二种方法在模拟器和设备上运行应用程序时非常好。然而,在归档时,我们一直收到错误消息:“无法运行命令'PBXCp libImplicitLibraryXX.a' - 此目标可能包含自己的产品。”我们已经勾选了“仅在安装时复制”框,但似乎它仍在尝试复制虚拟库。在归档时,它是否应该尝试复制?(XCode 9.4.1) - Tyler

6

Xcode隐式依赖

Xcode 依赖[关于]是构建所选目标所需的依赖项。

隐式依赖

  • 源代码也称为非编译依赖项。Xcode允许从整个工作区添加依赖项。一个很好的例子是来自GitHub或CocoaPods[关于]的带有源代码的项目。
  • 封闭代码也称为预编译依赖项外部 - 外部二进制文件,CocoaPodsCarthage等封闭代码

隐式依赖是构建目标所必需的依赖项,但没有明确定义。

  1. General -> Framework, Libraries, and Embedded Content 或 `Embedded Binaries and Linked Frameworks and Libraries[链接 vs 嵌入] 中指定
  2. Build Phases -> Dependencies || Target Dependencies 中没有依赖关系

要启用此功能[没有这个模块]

Edit Scheme -> Build -> Find Implicit Dependencies

[显式依赖]

[词汇表]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接