首页 > 解决方案 > Xcode 11 重新编译太多

问题描述

Xcode 11 正在重新编译(几乎?)我的整个项目,即使我只是更改本地私有变量,或更改本地范围内的常量值,有时甚至在本地私有函数范围内。我有时可以按预期通过快速构建获得 2 或 3 个更改,但很快它决定再次重新编译所有内容(这需要很长时间)。

任何想法可能会发生什么?Xcode 是否无法确定发生了什么变化,为什么它要重新编译这么多其他东西(甚至是其他模块)。

任何建议都非常感谢,谢谢!

标签: iosswiftxcodexcodebuildxcode11

解决方案


我们遇到了同样的问题,我们修复了它。两次。

增量构建(相同的构建机器):

之前:~10m 之后:~35s

如何?

让我们先从我们的经验说起。我们有一个庞大的 Swift/Obj-C 项目,这是主要问题:构建时间很慢,您必须创建一个新项目来实现新功能(字面意思)。从不工作的语法突出显示的奖励积分。

理论

要真正解决这个问题,您必须真正了解构建系统的工作原理。例如,让我们试试这个代码片段:

import FacebookSDK
import RxSwift
import PinLayout

并想象您在文件中使用了所有这些导入。而且该文件还依赖于另一个文件,该文件依赖于另一个库,而另一个库又使用另一个库等。

因此,要编译您的文件,Xcode 必须编译您提到的每个库及其依赖的每个文件,因此如果您更改“核心”文件之一,Xcode 必须从字面上重建整个项目。

依赖树

Xcode 构建是多线程的,但它由许多单线程组成。

因此,在每次增量构建的第一步,Xcode 都会决定哪些文件必须重新编译并构建AST 树。如果您更改在其他文件上充当“可靠”的文件,则必须重新编译充当“依赖”的所有其他文件。

耦合

所以第一个建议是降低耦合。您的项目部分必须相互独立。

Obj-C/Swift 桥接器

如果您使用的是 Obj-C/Swift 桥,那么这些树会出现问题,Xcode 必须经历比平常更多的阶段:

完美世界:

  1. 构建 Obj-C 代码
  2. 构建 Swift 代码

Swift/Obj-C 桥接器

Obj-C/Swift 桥:

  1. [REPEATABLE STEP] 构建 Swift 代码,这是编译 Obj-C 代码所需要的
  2. [REPEATABLE STEP] 构建 Obj-C 代码,这是编译 Swift 代码所需要的
  3. 重复 1 & 2 直到你只剩下不可靠的 Swift & Obj-C 代码
  4. 构建 Obj-C 代码
  5. 构建 Swift 代码

Obj-C/Swift 桥接器

因此,如果您从第 1 步或第 2 步更改某些内容,那么您基本上就遇到了麻烦。最好的解决方案是最小化 Obj-C/Swift Bridge(并将其从您的项目中删除)。

如果您没有 Obj-C/Swift 桥接器,那就太好了,您可以进行下一步:

Swift 包管理器

是时候迁移到 SwiftPM(或者至少更好地配置你的 Cocoapods)了。

事实是,大多数具有默认 Cocoapods 配置的框架都会拖着很多你不需要的东西。

例如,为了测试这一点,请创建一个只有一个依赖项(如 PinLayout)的空项目,并尝试使用 Cocoapods(默认配置)和 SwiftPM 编写此代码。

import PinLayout

final class TestViewController: UIViewController {

}

剧透:Cocoapods 会编译这段代码,因为 Cocoapods 会导入 PinLayout(包括 UIKit)的每一个 IMPORT,而 SwiftPM 不会,因为 SwiftPM 会自动导入框架。

肮脏的黑客

你还记得 Xcode 构建是多线程的吗?

好吧,如果您能够将项目拆分为许多独立的部分并将所有这些作为独立框架导入到您的项目中,那么您可以滥用它。它确实降低了耦合度,这实际上是我们使用的第一个解决方案,但实际上并不是很有效,因为我们只能将增量构建时间减少到 ~4-5m,与第一种方法相比,这算不了什么。


推荐阅读