Ninja 是最近冒出来的一个 build system,它很像 make,然而效率更高,对大项目支持更好。当然我用 Ninja 和效率无关(我又没有那种有几百个中间目标的 C++ 项目要 build),纯粹是因为 mingw-builds 里的 make.exe
对 PATH 的识别有问题而已。
Ninja 使用 build.ninja
文件来定义构建规则。和 Makefile 里的元编程不同,build.ninja
几乎是完全静态的,动态生成依赖其他工具,如 gyp 或者 CMake。下面是我用来构建 typeof.net 的文件:
forceFlags = rule generate_site command = moei.cmd ./compile.moe $forceFlags rule compile_less command = lessc.cmd $in $out rule publish_site command = git push origin master build rc/css/style.css: compile_less rc/css/style.less build style: phony rc/css/style.css build all: generate_site style build force: generate_site style forceFlags = force build publish: publish_site default all
是不是感觉有点坑爹?好吧,构建页面的过程是由一个 Moescript 脚本负责的,ninja 文件只是负责把它封装下。在 Ninja 中,每条构建规则由 build
起始,默认规则则由 default
指定。构建规则的形式为:
build 目标文件 : 转换规则 依赖文件a 依赖文件b ... 变量覆写(若有)
转换规则相当于 makefile 里缩进中的命令,但是有更好的控制。Ninja 执行的逻辑是,在希望构建 A: R B C
的时候,先构建依赖文件 B
、C
,然后计算规则 R 得到一组变量,进而执行其中 command
变量指示的命令完成构建。Ninja 的转换规则可以使用一系列的预定义变量,例如 $in
和 $out
,表示依赖文件表和输出文件的名字。
由于是优化效率的设计,Ninja 并没有提供很强大的函数功能(对比 make),相比之下 Ninja 的池(Pool)机制可以很好地管理大型项目构建时的并发编译/链接。当然作为一个写 nodejs 的,这种特性也用不上,权当了解了。