Ninja:一种简单的构建方式
你好!我偶尔会发现一款特别喜欢的软件,今天想谈谈最近喜欢的一款:Ninja!
增量构建很有用
我做了很多需要设置增量构建的小项目。例如,我正在写一本关于 Bash 的小册子,每一页都有一个 .svg 文件,需要把 SVG 转换为 PDF。之前的做法大致如下:
for i in *.svg
do
svg2pdf $i $i.pdf # or ${i/.svg/.pdf} if you want to get really fancy
done
这样能用,但我的 svg2pdf 脚本使用 Inkscape,运行有些慢。只改了一页,却要等待大约90秒重新构建全部 PDF,让人有点烦。
构建系统让人困惑
过去,我一直不太愿意给小项目使用 make 或 Bazel 这样的构建系统。Bazel 感觉是一个庞大复杂的东西,而 make 对我来说有点晦涩。我并不真正知道怎样使用它们。
因此,很长一段时间,我只是写一个 Bash 脚本之类的东西完成构建,并接受有时候要等上一分钟的现实。
Ninja 是一个极其简单的构建系统
但 Ninja 并不复杂!关于 Ninja 构建文件的语法,我知道的全部内容就是怎样创建 rule 和 build。
一个 rule 包含命令和说明。说明是给人看的,便于在构建过程中知道它正在做什么。
rule svg2pdf
command = inkscape $in --export-text-to-path --export-pdf=$out
description = svg2pdf $in $out
build 的语法是 build output_file: rule_name input_files。下面使用刚才的 svg2pdf 规则:规则中的 $out 表示输出,$in 表示输入。
build pdfs/variables.pdf: svg2pdf variables.svg
就这么多!把这两部分放进名为 build.ninja 的文件,再运行 ninja,它就会执行:
inkscape variables.svg --export-text-to-path --export-pdf=pdfs/variables.pdf
再次运行时,它不会执行任何操作,因为能判断出 pdfs/variables.pdf 已经构建完成,而且仍是最新的。
Ninja 还有其他一些功能,可以查看手册,但我还没有用到。它最初为 Chromium 而构建,因此,即使功能集较小,也能够支持大型构建。
Ninja 文件通常是自动生成的
Ninja 的妙处在于,你不必使用一种难记的构建语言,例如很少用一次的 make 语言。Ninja 语言非常简单;若要完成复杂工作,就用任何你喜欢的编程语言生成所需的构建文件。
对我来说,这容易得多,因为我会 Python,却总记不住 make 语言怎么用。
我喜欢创建一个类似下面的 build.py 文件,让它生成 Ninja 构建文件,再运行 ninja:
with open('build.ninja', 'w') as ninja_file:
# write some rules
ninja_file.write("""
rule svg2pdf
command = inkscape $in --export-text-to-path --export-pdf=$out
description = svg2pdf $in $out
""")
# some for loop with every file I need to build
for filename in things_to_convert:
ninja_file.write(f"""
build {filename.replace('svg', 'pdf')}: svg2pdf {filename}
""")
# run ninja
import subprocess
subprocess.check_call(['ninja'])
我相信 Ninja 有不少最佳实践,但我并不了解;对我的小项目来说,这种方式已经很好用了。
Meson 是一个生成 Ninja 文件的构建系统
我对 Meson 还了解不多。不过最近构建一个 C 程序 plocate——一个比 locate 更快的替代工具——时,发现构建指令与常见的 ./configure; make; make install 不一样:
meson builddir
cd builddir
ninja
看起来,Meson 是一个用于 C/C++/Java/Rust/Fortran 的构建系统,可以使用 Ninja 作为后端。
就是这些!
我已经用了几个月 Ninja,非常喜欢它。它几乎没有给我带来任何构建相关的麻烦,这种感觉很神奇。











暂无评论内容