Ninja是一个小巧、高效的构建系统,专注于快速执行构建规则
它不负责生成构建规则,而是执行已有规则,规则通常由CMake之类的工具生成,Ninja本身只关注如何根据描述的依赖关系来执行命令
Make是既要写规则,又要执行;Ninja是只管执行,生成规则交给别的工具\
Ninja的核心特点
- 极快:它的目标就是比
make快很多,特别是在增量构建时;相比于传统的make,Ninja在启动开销、依赖检查、任务调度等方面都进行了极致优化 - 并行化:天生支持多核运行(
ninja -j N控制线程数) - 最小化I/O:Ninja避免过度扫描文件,依赖检查逻辑很轻量
- 专注单一目标:不像CMake或Make那样很多花哨功能,Ninja只有一个任务:尽快跑完编译命令;Ninja的构建文件(
build.ninja)由高级生成器(如CMake)输出。这意味着依赖关系显式且精确,避免了make中可能因隐式导致的错误构建 - 设计简单:Ninja的语法和功能极其简单,它不包含复杂的逻辑(如条件判断、函数调用)。所有复杂逻辑都留给上一级的生成器,Ninja只负责执行。这使得它非常稳定和可预测
使用
- 使用CMake生成Ninja构建文件
在配置CMake项目时,使用
-G Ninja参数指定生成器未Ninja
# 在项目构建目录中
mkdir build && cd build
cmake -G Ninja .. -DCMAKE_BUILD_TYPE=Release
这条命令会读取上一级目录(..)的CMakeLists.txt,并根据其内容生成build.ninja文件和各种.ninja片段,而不是Makefile
- 使用Ninja进行构建
在上一步的
build目录中,直接运行ninja命令
ninja
Ninja会读取build.ninja文件,开始编译项目。会看到它的输出非常简洁,直接显示正在进行的任务和进度,没有冗余信息
- 常用Ninja命令
ninja:构建默认目标(通常是all)ninja target_name:构建指定的目标(例如ninja hello_world)ninja -j N:指定并行编译的任务数(例如ninja -j 8使用8个线程)。Ninja会自动检测CPU核心数,但有时手动指定可以获得更好性能ninja -C builddir:指定在builddir目录下执行构建(等价于cd builddir && ninja)ninja clean:清理所有构建处的文件ninja -t clean:这是Ninja自带的清理命令,有时比生成器生成的clean规则更高效ninja -t targets:列出所有可构建的目标ninja -t graph:以graphviz格式输出所有目标的依赖图,可用于可视化依赖关系ninja -n:--dry-run,显示将要执行的命令但实际上不执行,用于调试
Ninja构建文件
虽然不推荐手写,但了解其基本语法有助于调试。build.ninja文件主要由rule(规则),build statement(构建语句)和variable(变量)组成
rule:定义了如何执行一个任务,类似于Makefile中的模式规则
# 定义一个名为'compile'的规则
rule compile
command = gcc -c -o $out $in # 要执行的命令
description = Compiling $out # 构建时显示的信息
depfile = $out.d # 用于存储头文件等依赖信息
$in代表输入文件(如.c文件)$out代表输出文件(如.o文件)build:是Ninja的核心,它定义了具体的文件依赖关系和使用的规则
# 构建语句格式:build output_file: rule_name input_file
build hello.o: compile hello.c
这表示:要构建hello.o,需要使用compile这个规则,并且它依赖于hello.c文件
variable
cflags = -Wall -O2
rule compile
command = gcc $cflags -c -o $out $in
- 默认目标
default hello
- 伪目标
build all: phony hello.exe other_target
phony表示all不是一个真实的文件,它总是需要被构建
完整示例
cflags = -Wall
rule compile
command = gcc $cflags -c -o $out $in
rule link
command = gcc -o $out $in
build main.o: compile main.c
build utils.o: compile utils.c
build myapp: link main.o utils.o
default myapp