一个底层的构建系统。
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 Package Manager 使用的构建系统的命令行界面。 它是作为 Swift 项目构建的一部分构建的,并合并到 Swift 语言快照中。
此工具构建于 BuildSystem 库之上。
libllbuild
库公开了 llbuild 库的 C API,第三方可以直接使用它,也可以用来构建额外的语言绑定。 有关使用此库的 Swift 和 Python 绑定的示例,请参见 bindings。
例如,在 Xcode 中,此 API 被用作 Xcode 9 中引入的新构建系统的基础。
llbuild 的设计是 LLVM 理念的延续,即将基于库的设计应用于传统的开发人员工具。 Clang 遵循了这种方法,提供了一个高性能的编译器和汇编器,同时也支持了新的工具,如 clang-format 或用于代码补全和索引的 libclang 接口。 然而,传统构建系统和编译器之间僵化的命令行界面仍然限制了可以在 Clang 中实现的优化和功能。
llbuild 旨在允许构建更具特色的构建环境,这些环境使用 API 而不是命令行界面来集成外部工具(如编译器)。 通过允许构建系统和工具直接通信并进行协同设计,我们相信我们可以释放额外的优化机会,并创建更健壮、更易于使用的构建系统。
有关更多信息,请参见 2016 年 LLVM 开发者大会上的 构建软件的新架构。
从抽象的角度来看,构建系统用于执行任务,同时也是
增量的:通过利用从先前构建中保存部分输出的能力,应该能够有效地重建输出,给定对输入的少量更改。
一致的:等效的输入应始终产生与从头开始构建相同的结果。
持久的:应该存储结果,以便可以在中断后恢复构建,而无需重做完整的计算。
并行和高效的:必须能够并行执行计算的独立元素,以便尽可能有效地计算结果。
从这个角度来看,很明显,构建系统的核心技术适用于任何复杂的、长时间运行的计算,在这种计算中,用户通常只修改输入的一小部分,然后希望重新计算结果。 例如,电影编辑器应用程序通常需要重新渲染整个电影的小部分,以响应交互式编辑,以支持预览最终结果。 然而,由于正确管理计算各个部分之间依赖关系的复杂性,此类应用程序通常无法充分利用存储和部分重新计算结果的能力。
围绕通用构建引擎设计 llbuild 的部分目标是允许其在传统上不认为需要“构建系统”的上下文中使用。
技术文档可在 llbuild.readthedocs.io 上找到。
错误报告应在 GitHub 上 swift-llbuild
存储库的 issue tracker 中提交。
llbuild 正在进行中。 我们希望解决的一些更重要的开放项目是
支持使用文件签名而不是时间戳进行更改检测。
支持更丰富的数据类型,用于任务之间的通信。
任务目前仅计算单个标量值作为其结果。 我们希望支持任务结果的更丰富的数据类型,例如,任务应该能够计算结果集,并让引擎自动将集合中各个项目的添加或删除传递给下游消费者。
支持更复杂的数据库实现。
当前的实现使用 SQLite3 数据库来存储构建结果。 这对于启动来说是一个务实的选择,但它可能是某些应用程序的性能瓶颈,而且我们不需要完整 SQL 数据库的灵活性。 我们希望评估为 llbuild 设计自定义解决方案的权衡。
支持透明的分布式构建。
我们希望 llbuild 具有透明地将构建分布在worker机器阵列中的设施。
支持自动审核构建一致性。
很少有构建系统能有效地诊断问题。 通常,未声明的输入或行为不端的工具会导致不一致的构建结果。 我们希望 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。