一个底层的构建系统。
llbuild 是一组用于构建构建系统的库。与大多数专注于描述构建语法的构建系统项目不同,llbuild的设计围绕着一个可重用、灵活和可扩展的通用构建引擎,能够解决许多“构建系统”类问题。该项目还包括构建引擎之上的附加库,这些库为构建定制的构建系统(如 swift build
)或从 Ninja 清单构建提供支持。
llbuild 目前包括:
一个灵活的核心引擎,能够在运行时发现新的工作。
针对达到数百万节点的依赖关系图的可扩展性。
支持构建 Ninja 清单(例如,用于构建 LLVM、Clang 和 Swift)。
一种专为可扩展性而设计的 llbuild 原生构建描述格式。
旨在支持嵌入和重用的基于库的设计。
该项目目前生成三个顶级产品:llbuild
、swift-build-tool
和 libllbuild
/ llbuild.framework
。
llbuild
工具为 llbuild 库的各种功能提供了一个命令行界面。它有几个可用的子工具,有关更多信息,请参阅 llbuild --help
。最重要的子工具是 Ninja 构建支持。
您可以使用 llbuild
构建基于 Ninja 的项目,方法是:
$ llbuild ninja build
此工具支持 Ninja 本身支持的命令行参数的子集,以便它可以作为兼容的替代品使用,即使是像 CMake 这样依赖于特定 Ninja 命令行标志的工具在其配置过程中也能使用。
为了方便起见,如果您通过名为 ninja
的符号链接调用 llbuild
,它将自动使用此子工具。这支持将 llbuild 作为 ninja
安装到您的 PATH
中,然后将其用作 Ninja 的替代方案来构建任意项目(如 LLVM、Clang 和 Swift)。这也是我们自托管 llbuild
的方式(通过 CMake Ninja 生成器)。
llbuild ninja
子工具还提供了额外的命令,这些命令主要只对对 Ninja 支持感兴趣的开发人员有用。这些命令允许独立测试词法分析器、解析器和清单加载组件,并用作测试套件的一部分。
如果您想公开展示您对 llbuild 的使用,您可以自豪地使用我们方便提供的贴纸(相邻的 PSD 版本)。😁
受 Buck 的启发,llbuild ninja
支持 --profile PATH
选项,用于生成 Chromium 跟踪,以可视化构建过程中花费的时间。例如,以下图是 llbuild 自身构建的图:
swift-build-tool
产品是 Swift 包管理器使用的构建系统的命令行界面。它是作为 Swift 项目构建的一部分构建的,并集成到 Swift 语言快照中。
此工具构建于 BuildSystem 库之上。
libllbuild
库为 llbuild 库公开了一个 C API,第三方可以直接使用它,或者构建额外的语言绑定。有关使用此库的 Swift 和 Python 绑定的示例,请参阅 bindings。
例如,Xcode 中引入的新构建系统就是使用此 API 作为基础。
llbuild 的设计是 LLVM 将基于库的设计应用于传统开发工具的理念的延续。Clang 遵循了这种方法,以提供高性能的编译器和汇编器,同时也支持了诸如 clang-format 或 libclang 接口之类的用于代码完成和索引的新工具。然而,传统构建系统和编译器之间僵化的命令行界面仍然限制了可以在 Clang 中实现的优化和功能。
llbuild 旨在允许构建更丰富的功能构建环境,该环境使用 API 而不是命令行界面来集成外部工具(如编译器)。通过允许构建系统和工具直接通信并共同设计,我们相信我们可以释放额外的优化机会并创建更强大、易于使用的构建系统。
有关更多信息,请参阅 2016 LLVM 开发者大会上的 构建软件的新架构。
从抽象的角度来看,构建系统用于执行任务,同时也是:
增量的:通过利用从先前构建中保存部分输出的能力,应该可以在对输入进行少量更改的情况下有效地重建输出。
一致的:等效的输入应该始终产生与从头开始构建相同的结果。
持久的:应该存储结果,以便可以在发生故障后中断和恢复构建,而无需重做完整的计算。
并行且高效的:必须可以并行执行计算的独立元素,以便尽可能高效地计算结果。
从这个角度来看,很明显,构建系统的核心技术适用于任何复杂的、长时间运行的计算,其中用户通常只修改一小部分输入,然后希望重新计算结果。例如,电影编辑器应用程序通常需要重新渲染整个电影的小部分,以响应交互式编辑,从而支持预览最终结果。但是,由于正确管理计算各部分之间的依赖关系的复杂性,此类应用程序通常没有充分利用存储和部分重新计算结果的能力。
围绕通用构建引擎设计 llbuild 的部分目标是允许其用于传统上不被认为需要“构建系统”的上下文中。
技术文档可在 llbuild.readthedocs.io 上找到。
Bug 报告应该在 GitHub 上的 swift-llbuild
仓库的 issue 跟踪器中提交。
llbuild 是一项正在进行的工作。我们希望解决的一些更重要的开放项目包括:
支持使用文件签名而不是时间戳进行更改检测。
支持更丰富的数据类型以进行任务之间的通信。
任务目前仅将单个标量值计算为其结果。我们希望支持任务结果的更丰富的数据类型,例如,任务应该能够计算结果集,并且引擎应自动将集合中各个项目的添加或删除传递给下游消费者。
支持更复杂的数据库实现。
当前的实现使用 SQLite3 数据库来存储构建结果。这是启动的务实选择,但对于某些应用程序而言,这可能会成为性能瓶颈,并且我们不需要完整 SQL 数据库的灵活性。我们想评估为 llbuild 设计自定义解决方案的权衡。
支持透明的分布式构建。
我们希望 llbuild 具有透明地将构建分发到一系列工作机器上的工具。
支持自动审核构建一致性。
很少有构建系统能有效地诊断问题。通常,未声明的输入或行为不端的工具会导致构建结果不一致。我们希望 llbuild 自动诊断这些问题,例如,通过定期或推测性地重建不应已更改的项目并比较结果。
核心引擎队列的性能调整。
核心构建引擎使用多个工作项队列执行其工作,并锁定支持并发操作的子集。我们希望研究将共享队列移动到使用无锁数据结构,并对队列进行微优化,以支持非常细粒度的任务细分,而不会对性能产生负面影响。
问:为什么 llbuild 包含 LLVM 的某些部分?
答:作为一个底层的、可嵌入的组件,我们希望 llbuild 本身具有一个简单的构建过程,而没有任何重要的构建时依赖项。但是,我们也希望利用为 LLVM 开发的一些数据结构和支持工具。目前,我们的解决方案是将 LLVM 的 Support 库的某些部分合并到存储库中,希望随着时间的推移,LLVM 将以一种使其更容易重用的方式分解出这些库,或者我们将开发我们自己的一组独有的支持数据结构和实用程序,并停止使用 LLVM 的数据结构和实用程序。
问:为什么 llbuild 包含 Ninja 支持?
答:llbuild 包含一个 Ninja 兼容层,允许使用 llbuild 核心引擎构建使用 Ninja 清单的项目。我们开发此支持是为了验证核心引擎的概念,并作为自举的一种方式(我们使用 CMake Ninja 生成器开发 llbuild,并使用 llbuild 构建自身)。此支持对于允许直接进行 llbuild 的基准测试比较也很有价值。
我们对 Ninja 支持的实现还包括一个单独的库,用于以编程方式加载 Ninja 清单,这可能对希望使用或操作 Ninja 文件的其他项目有用。
我们打算继续维护 Ninja 支持,以保持与主项目的兼容性。
llbuild 受诸如 Shake, Buck, 和 Ninja 之类的现代构建系统的强烈影响。我们特别要感谢 Neil Mitchell 描述 Shake 算法的工作,该算法为 llbuild 用于允许在运行时发现其他工作的机制提供了灵感。
版权所有 (c) 2014 - 2022 Apple Inc. 以及 Swift 项目的作者。在 Apache License v2.0 下获得许可,带有运行时库例外。
有关许可信息,请参阅 https://swiftlang.cn/LICENSE.txt。
有关 Swift 项目作者,请参阅 https://swiftlang.cn/CONTRIBUTORS.txt。