Ninja
Ninja 原意是忍者的意思,它是一个专注于速度的小型构建工具。它是一个构建系统。 它将文件的相互依赖关系(通常是源代码和输出可执行文件)作为输入,并快速编排构建它们。
运行Ninja,默认情况下,它会在当前目录中查找名为 build.ninja 的文件并构建所有过时的目标。 您可以指定要构建的目标(文件)作为命令行参数。
还有一个特殊的语法 target^ 用于将目标指定为某个规则的第一个输出,其中包含您在命令行中输入的源(如果存在)。 例如,如果您将目标指定为 foo.c^,那么 foo.o 将被构建(假设您的构建文件中有这些目标)。
一般情况下,我们不需要手写 ninja 文件,通过 gn 或 cmake 来描述项目结构和依赖关系,再通过它们来生成 build.ninja 文件
详见Ninja 手册 - https://ninja-build.org/manual.html,
Example
byteorder.c
#include
int main(int argc, char **argv)
{
union {
short s;
char c[sizeof(short)];
}un;
un.s = 0x0102;
if (sizeof(short) == 2) {
if (un.c[0] == 1 && un.c[1] == 2)
printf("big-endian\n");
else if (un.c[0] == 2 && un.c[1] == 1)
printf("little-endian\n");
else
printf("unknown\n");
} else{
printf("sizeof(short) = %ld\n", sizeof(short));
}
return 0;
}
build.ninja
cflags = -Wall
rule cc
command = gcc $cflags -c $in -o $out
build byteorder.o: cc byteorder.c
可以通过 ninja -C build -j 20
来构建
gn
顾名思义,GN is “Generate Ninja” 一个用来生成 Ninja 的工具
用于为 Google Chrome 和相关项目(v8、node.js)以及 Google Fuchsia 生成构建文件的元构建系统。 gn 可以为 Chrome 支持的所有平台生成 Ninja 文件。
GN 有自己定义的一 套比较简单的描述性语言,详见 https://gn.googlesource.com/gn/+/main/docs/language.md
GN 中有三个重要的文件
.gn
它定义了 GN 构建树的根节点
详见命令 “gn help dotfile”
//build/config/BUILDCONFIG.gn
Exact location defined by “.gn” file
Sets up global variables and default settings
-
BUILD.gn
描述了构建目标,源码文件,及其依赖关系等
gn args
这个工具有两个作用,一是生成.ninja编译配置文件,二是查看当前编译的所有标记项。
生成.ninja
这个工具给用户提供一个接口,来对构建进行整体的配置。如在Chromium Android编译指南中,为Android版chromium做编译配置时,所执行的命令:
gn args out/Default
参数是output目录路径。这个命令启动系统默认的编辑器,创建out/Default/args.gn文件,我们在编辑器中加入我们自己特定的配置项,如:
target_os = "android"
target_cpu = "arm" # (default)
is_debug = true # (default)
# Other args you may want to set:
is_component_build = true
is_clang = true
symbol_level = 1 # Faster build with fewer symbols. -g1 rather than -g2
enable_incremental_javac = true # Much faster; experimental
gn根据创建得这个out/Default/args.gn文件的内容来产生ninja文件。
查看当前编译的所有标记项
这个工具还可以查看当前编译的所有标记配置项。chromium中用到了许许多多的标记项,对于这些标记项中的许多项,即使用户不进行配置,chromium的编译系统也会提供默认的配置。了解到当前编译的所有标记配置项,对于我们了解实际编译时所用的编译参数非常重要。
对于上面输入的参数,产生的整个编译配置环境中,所有的标记配置项如下:
$gn args --list out/Default/
gn gen
usage: gn gen [
这个工具根据当前的代码树及配置,产生ninja文件,并把它们放在给定得目录下。输出目录可以是源码库的绝对地址,比如//out/foo,也可以是相对于当前目录的地址,如:out/foo。 上面的gn args
gn clean
usage: gn clean
这个命令用于对历史编译进行清理。它会删除输出目录下除了args.gn外得内容,并创建一个可以重新产生构建配置的Ninja构建环境。
gn desc
usage: gn desc
显示关于一个给定target或config的信息。构建参数取自给出的
如我们要查看 webrtc 中 gcc 模块相关得所有信息:
$ gn desc out/Default //modules/congestion_controller/goog_cc --tree
gn ls
usage: gn ls
这个命令展示给定输出目录下,满足某个模式的所有的targets。默认情况下,只显示默认工具链的target会被匹配,除非明确地提供了工具链参数。如果没有指定标签参数,则显示所有的targets。模式不是常规的正则表达式(可以参考"gn help label_pattern")。
$ gn ls out/Default "//modules/congestion_controller/*"
//modules/congestion_controller:congestion_controller
//modules/congestion_controller:congestion_controller_unittests
//modules/congestion_controller/goog_cc:alr_detector
//modules/congestion_controller/goog_cc:delay_based_bwe
//modules/congestion_controller/goog_cc:estimators
//modules/congestion_controller/goog_cc:goog_cc
//modules/congestion_controller/goog_cc:goog_cc_unittests
//modules/congestion_controller/goog_cc:link_capacity_estimator
//modules/congestion_controller/goog_cc:loss_based_bwe_v1
//modules/congestion_controller/goog_cc:loss_based_bwe_v2
//modules/congestion_controller/goog_cc:probe_controller
//modules/congestion_controller/goog_cc:pushback_controller
//modules/congestion_controller/goog_cc:send_side_bwe
//modules/congestion_controller/goog_cc:test_goog_cc_printer
//modules/congestion_controller/pcc:bitrate_controller
//modules/congestion_controller/pcc:monitor_interval
//modules/congestion_controller/pcc:pcc
//modules/congestion_controller/pcc:pcc_controller
//modules/congestion_controller/pcc:pcc_unittests
//modules/congestion_controller/pcc:rtt_tracker
//modules/congestion_controller/pcc:utility_function
//modules/congestion_controller/rtp:congestion_controller_unittests
//modules/congestion_controller/rtp:control_handler
//modules/congestion_controller/rtp:transport_feedback
gn check
gn check
这个工具可以用来检查头文件依赖关系得有效性。
$ gn check out/Default/ net
Header dependency check OK
gn help
展示帮助信息,可以用来获取关于上面所有的gn命令,及内置得targets,内建得预定义变量的所有相关信息。如:
$ gn help
自 CMake 版本 2.8.8 起,可以在 Linux 上生成 Ninja 文件的广泛使用的元构建系统。 较新版本的 CMake 也支持在 Windows 和 Mac OS X 上生成 Ninja 文件。
通过 GN 来生成 build.ninja
以 GN 中所自带的例子 simple build 为例
- “.gn”
# The location of the build configuration file.
buildconfig = "//build/BUILDCONFIG.gn"
- build/BUILDCONFIG.gn
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
if (target_os == "") {
target_os = host_os
}
if (target_cpu == "") {
target_cpu = host_cpu
}
if (current_cpu == "") {
current_cpu = target_cpu
}
if (current_os == "") {
current_os = target_os
}
is_linux = host_os == "linux" && current_os == "linux" && target_os == "linux"
is_mac = host_os == "mac" && current_os == "mac" && target_os == "mac"
# All binary targets will get this list of configs by default.
_shared_binary_target_configs = [ "//build:compiler_defaults" ]
# Apply that default list to the binary target types.
set_defaults("executable") {
configs = _shared_binary_target_configs
# Executables get this additional configuration.
configs += [ "//build:executable_ldconfig" ]
}
set_defaults("static_library") {
configs = _shared_binary_target_configs
}
set_defaults("shared_library") {
configs = _shared_binary_target_configs
}
set_defaults("source_set") {
configs = _shared_binary_target_configs
}
set_default_toolchain("//build/toolchain:gcc")
- build/BUILD.gn
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
config("compiler_defaults") {
if (current_os == "linux") {
cflags = [
"-fPIC",
"-pthread",
]
}
}
config("executable_ldconfig") {
if (!is_mac) {
ldflags = [
"-Wl,-rpath=\$ORIGIN/",
"-Wl,-rpath-link=",
]
}
}
- BUILD.gn
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
executable("hello") {
sources = [ "hello.cc" ]
deps = [
":hello_shared",
":hello_static",
]
}
shared_library("hello_shared") {
sources = [
"hello_shared.cc",
"hello_shared.h",
]
defines = [ "HELLO_SHARED_IMPLEMENTATION" ]
}
static_library("hello_static") {
sources = [
"hello_static.cc",
"hello_static.h",
]
}
参考资料
- Ninja 手册: https://ninja-build.org/manual.html
- GN 快速上手:https://gn.googlesource.com/gn/+/main/docs/quick_start.md
- GN 参考手册:https://gn.googlesource.com/gn/+/master/docs/reference.md
- Using GN Build PPT: https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/htmlpresent
- GN Frequently asked questions
- GN Reference
注:有些连接需要