Build Systems à la Carte: Theory and practice
Background
Build systems are awesome, terrifying and unloved.
过去针对 Shake 等单一构建系统的方法研究提供了一定的设计思路改进,然而系统性研究仍然缺位。本文提出了研究构建系统功能构造的方法,并具体分析了四个代表性的构建系统(Make, Shake, Bazel, Excel)。(是的这个 Excel 就是 MS Office Excel)
从功能上评判构建系统的若干标准:
- 高级构建特性:
- 静态/动态依赖(构建前是否能够确定构建任务,例如 Nix 启用 import-from-derivation 后,允许构建任务依赖其他构建任务的产物,导致无副作用语境下无法确定构建任务描述;Excel 也可以在构建中更改中间任务规则)
- 本地/云端构建(这里可能指的是分布式构建或大规模并行支持,以及构建系统本身的性能开销)
- 确定性/非确定性构建任务(?)
- 是否支持提前截止(原文在此处和下文描述都很不清楚,实际上说的是构建系统如何判断并忽略不必重新执行的构建任务);自追踪(检测构建中间产物?)
- 持久化构建信息/缓存内容
- 关键设计
- 如何安排构建任务的执行顺序、并行条件
- 如何判断是否应该重新执行构建任务
- 构建系统的抽象语义;如何在现行的构建系统应用并组合该语义
The Venerable Make: Static Dependencies and File Modification Times
NOTE Venerable:古老的、值得尊敬的,此处可解释为“德高望重”。 Make 标准独立于具体实现,即使绝大多数项目项目都使用 GNU Make(BSD 发行版使用 BSD Make 以规避许可证问题)。
Make 作为传统意义上的构建系统,支持通过 makefile 声明构建任务,即以下形式:
util.o: util.h util.c
gcc -c util.c
main.o: util.h main.c
gcc -c main.c
main.exe: util.o main.o
gcc util.o main.o -o main.exe
<target>: <(blank-separated) dependencies>
<recipe>
makefile 可以等价转换为依赖图,其中 target 对应图上节点,dependencies 构成其入边集合。
在任意两次构建之间,传递依赖被改变的构建任务应当仅执行一次,其他任务不执行。