【问题标题】:How does Xcode find implicit target dependencies?Xcode 如何找到隐式目标依赖项?
【发布时间】:2016-10-14 03:30:58
【问题描述】:

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

但我经常发现自己面临一个存在多个目标的(大中型)项目。由于该项目是由其他人完成的,我发现很难理解什么目标取决于什么,因为并非所有关系都是明确的

Xcode 使用什么规则来查找此类关系?(我希望我能理解其中的逻辑,以便在我的脑海中运行它,也许可以节省我一些时间未来)或是什么让一个目标有资格隐式依赖于另一个目标?

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

来源:iOS Developer Library → Xcode Concepts → Xcode Target

【问题讨论】:

  • 在同一个工作区(.proj 内部也有一个 .workspace)或在构建阶段添加目标依赖项。此外,如果一个目标使用另一个目标的产品,Xcode 将自动先构建另一个目标。
  • 我发现隐式目标依赖项无法构建复杂的项目,例如当涉及用于不同平台的多个类似名称的框架/库时。手动指定所有内容是我构建 watchOS/tvOS/iOS 项目的唯一原因。

标签: ios xcode macos


【解决方案1】:

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

首先,您需要确保在您尝试构建的方案的构建面板中启用了“查找隐式依赖项”。

可以通过两种方式使目标“A”“隐式”依赖于目标“B”:

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

那么,为什么会有人想要制作“2”的恐怖呢?我可以想出几个原因。

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

如果您认为这些是人为的情况,我目前正在尝试将一些遗留代码从一系列显式依赖项转移到隐式依赖项。为什么我要转向隐式依赖?因为 Xcode 中的显式依赖项需要项目嵌套,并且一旦获得足够的显式依赖项,项目浏览器就会变得非常缓慢,并且您会在 Xcode 中看到大量随机事件。

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

【讨论】:

  • 第二种方法非常适合我们在模拟器和设备上运行应用程序时。但是,存档时我们不断收到错误消息:“无法运行命令 'PBXCp libImplicitLibraryXX.a' - 此目标可能包含其自己的产品。”我们选中了“仅在安装时复制”框,但它似乎无论如何都在尝试复制虚拟库。归档时是否应该尝试复制? (XCode 9.4.1)
【解决方案2】:

Xcode Dependency[About]构建选定目标所需的依赖项。

Implicit 依赖

  • 源代码又名Non-compiled dependencies。 Xcode 允许从整个workspace 添加一个依赖项。一个很好的例子是来自 GitHub 的项目或带有源代码的 CocoaPods[About]
  • 封闭代码 aka Precompiled dependencies aka External - 外部二进制,CocoaPodsCarthage 封闭代码

Implicit dependency 是成功构建目标所必需的依赖项,但未明确定义。

  1. General -> Framework, Libraries, and Embedded Content 或`嵌入式二进制文件和链接框架和库[Link vs Embed] 中指定
  2. Build Phases -> Dependencies || Target Dependencies 中没有依赖关系

开启此功能[No such module]

Edit Scheme -> Build -> Find Implicit Dependencies

[Explicit dependency]

[Vocabulary]

【讨论】:

    猜你喜欢
    • 2015-01-31
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 2012-07-01
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多