Xcode 11 重新编译太多

Nik*_*iev 13 xcode xcodebuild ios swift xcode11

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

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

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

Sta*_*nov 17

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

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

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

如何?

让我们先从我们的经验开始。我们有一个庞大的 Swift/Obj-C 项目,这是主要问题:构建时间很慢,你必须创建一个新项目来实现一个新功能(字面意思)。无用语法高亮的加分点。

理论

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

import FacebookSDK
import RxSwift
import PinLayout
Run Code Online (Sandbox Code Playgroud)

并假设您在文件中使用了所有这些导入。而且这个文件依赖于另一个文件,它依赖于另一个库,而后者又使用另一个库等。

因此,要编译您的文件,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 Bridge,那就太棒了,您可以进行下一步:

Swift 包管理器

是时候转向 SwiftPM(或者至少更好地配置你的 Cocoapods)。

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

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

import PinLayout

final class TestViewController: UIViewController {

}
Run Code Online (Sandbox Code Playgroud)

剧透:Cocoapods 会编译这段代码,因为 Cocoapods 会导入 PinLayout(包括 UIKit)的 EVERY IMPORT,而 SwiftPM 不会,因为 SwiftPM 以原子方式导入框架。

肮脏的黑客

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

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


nte*_*iss 8

这里没有灵丹妙药,但有很多事情需要检查:

  • 确保您实际上在方案中使用调试配置使用调试配置的 Xcode 方案编辑器

  • 请参阅下文,了解如何确保您使用增量构建而不是按照马特的建议使用整个模块。还要确保调试版本的优化级别为无。 显示增量构建的 Xcode 构建设置

  • 如果您使用 RxSwift 等类型推断重型框架,添加显式类型注释可以加快构建时间。

  • 如果项目非常大,您可以考虑将源文件的逻辑组重构到框架中,但这可能比您希望的变化太大

如果您提供有关该项目的更多细节可能会有所帮助:您是否静态链接任何库?它是框架还是应用程序目标?您使用的有多大以及什么 swift 版本?您是否有任何有时可以跳过的自定义构建阶段,例如 linter 或代码生成?

  • @RomuloBM 不,它针对代码执行时的速度/性能进行了优化 (2认同)