Xcode如何找到隐式目标依赖关系? [英] How does Xcode find implicit target dependencies?

查看:328
本文介绍了Xcode如何找到隐式目标依赖关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

但是我经常遇到一个有多个目标的(中到大型)项目.由于该项目是由其他人完成的,因此我发现很难理解哪些目标取决于什么,因为并非所有关系都是明确的.

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

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

来源: iOS开发人员库→Xcode概念→Xcode目标

解决方案

此答案适用于Xcode 8.x,我认为适用于Xcode 9.0.

首先,您需要确保在尝试构建的Scheme的构建"面板中启用了查找隐式依赖项".

可以通过两种方式使目标"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,从而使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依赖于libB.a和libC.a,它们都需要先构建libD.a(可能会生成一些标头和/或源).您可以使用与库链接"阶段(也称为解决方案#1)来完成所有操作,但在这种情况下,最终将得到libA最终链接版本中libD中.o文件的两个副本.如果您做得足够深(例如,一个工作空间中有40个项目,并且它们之间的依赖程度各不相同),您很快就会得到巨大的库文件,其中包含几个相同的.o文件,并且链接时间将变得很恐怖.

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

如果您在同一个工作空间中碰巧有两个目标生成具有相同名称的产品并从第三个目标中依赖它们,该怎么办?隐式依赖项将选择一个.它似乎根据产品的基本名称进行匹配(因此foo/bar.a和baz/bar.a相同),并将选择找到的第一个.

Xcode finds dependencies automatically sometimes. I think is is ok when I am the one who is defining the relationships and when I get lazy ...

But more than often I find myself facing an existent (medium to large size) project with several targets. Since the project has been made by someone else I find it very difficult to understand what targets depends on what since not all the relationships are explicit.

What are the rules Xcode use to find such relationships? ( I hope I can understand the logic so run it in my mind and maybe save me some time in the future) Or What makes a target qualifiable to be implicitly dependant of another?

A target and the product it creates can be related to another target. If a target requires the output of another target in order to build, the first target is said to depend upon the second. If both targets are in the same workspace, Xcode can discover the dependency, in which case it builds the products in the required order. Such a relationship is referred to as an implicit dependency.

Source: iOS Developer Library → Xcode Concepts → Xcode Target

解决方案

This answer applies to Xcode 8.x, and I think for Xcode 9.0.

First off, you need to be sure that "Find Implicit Dependencies" is enabled in the the Build panel of the Scheme that you are attempting to build.

A target "A" can be made "implicitly" dependent on target "B" in two ways:

  1. Target A has a "Link Binary With Libraries" build phase that has a library in its list that has the same name as a Product of B. This product can either be in the same project or another project in the workspace. Note that I said "same name". Just because you chose libA.a from target A doesn't mean that implicit dependencies will build it if you have another libA.a product in a different target. See below for details.
  2. Target A has a "Copy Files Phase" that copies a file with a base name that matches a product of B. Normally a "Copy files" build phase cannot refer to a file that isn't in the same project as its target, but you can set up a dependency across projects if you create a dummy file for the "copy file" phase to copy that has the same name as a product of B. For example, if you have a workspace that contains two projects ProjectA and ProjectB. ProjectA has TargetA that creates libA.a, and ProjectB has TargetB that creates libB.a. TargetA could get TargetB to build libB.a by having a "fake" zero byte file as part of TargetA that happened to be named libB.a, and this would be sufficient to get libB.a made, even though the libB.a referred to in the "Copy Files" phase is a totally different file than the product output of the TargetB build. If you check the "Copy Only When Installing" box, Xcode won't actually perform the copy, but will still resolve the dependency. You can actually delete the fake file off your drive that you created solely to have something to put in the "Copy Files" phase (but you must leave it in your project).

So why would anyone ever want to do the horror that is "2"? I can come up with a couple of reasons.

  1. TargetA needs some some files copied/generated by TargetB, but TargetB doesn't generate a library to link to. You could probably work around this by having TargetB generate up a small dummy library, but that may be painful for other reasons.
  2. Let's say I had projectA, targetA and libA.a (and equivalents for project B, C and D), and libA.a depended on libB.a and libC.a which both needed libD.a to be built first (possibly some headers and/or sources generated). You could do it all using the "Link With Libraries" phase (aka solution #1) but in that case you would end up with two copies of the .o files in libD in the final linked version of libA. If you do this deep enough (eg a workspace that has 40 projects that have varying levels of dependencies on one another) you will quickly end up with huge library files with several identical .o files in them, and your link times will become horrific.

If you think these are contrived situations, I'm currently hitting both of them moving some legacy code from a series of explicit dependencies to implicit dependencies. Why am I moving to implicit dependencies? Because explicit dependencies in Xcode require project nesting, and once you get enough explicit dependencies, the project browser gets extremely slow, and you will see a lot of beachballs inside of Xcode for random things.

What happens if you happen to have two targets inside the same workspace that generate products with the same name and depend upon them from a third target? Implicit dependencies will pick one. It appears to do a match based on the base name of the product (so foo/bar.a and baz/bar.a are the same), and will pick the first one it finds.

这篇关于Xcode如何找到隐式目标依赖关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆