Build Systems à la Carte: Theory and practice

def/ | a.k.a. comonad

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 构成其入边集合。

Three task-dependency graphs showing an unchanged build, a full rebuild after util.h changes, and a partial rebuild after main.c changes.
A task dependency graph and two build scenarios. Input files are shown in rectangles, and output files are shown in rounded rectangles. Modified inputs and files that are rebuilt are highlighted.

在任意两次构建之间,传递依赖被改变的构建任务应当仅执行一次,其他任务不执行。