GN INTRODUCTION
-
What’s GN
1、GN
Generate Ninja,是Google为Ninja专门开发的上层编译框架,可以生成Ninja可以识别的输入文件。GN由c++编译,相比于基于python的gyp,速度快接近20倍。
2、GN Language
由于GN和GYP都可以生成Ninja,所以我们可以稍稍将GN和GYP进行对比。风格方面,GYP有Json格式的文件组成,可以将所有的GYP文件和GYPI文件看成一个大的Json格式文件。而GN是函数式风格,最后的依赖关系可以由栈式函数调用来组成。
- 变量
和大多数脚本语言一样,GN的变量种类不多,包含字符串(string),整形(int64),布尔(Boolean),列表(List),字典(dictionary)。使用方式也和脚本语言一样,不需要声明变量类型,直接对变量赋值即可,例如 a=”hello world”。
- 函数
和GYP是基于JSON格式的组织方式不同,GN使用函数来组织依赖。
例如:
a:简单函数调用:
print("hello, world")
b:复试函数调用
static_library("mylibrary") {
sources = [ "a.cc" ]
}
这种调用乍一看以为是函数定义,其实是一种函数调用,可以将函数体的返回值理解为函数的一个参数,上述例子的含义就是使用源文件a.cc编译出静态库mylibrary
- 目标
和Makefile中的目标类似,GN中的目标通常也就是一种可执行文件或者依赖库。一个目标可以依赖另一个目标,从而形成依赖树。
action: Run a script to generate a file.
action_foreach: Run a script once for each source file.
bundle_data: Declare data to go into a Mac/iOS bundle.
create_bundle: Creates a Mac/iOS bundle.
executable: Generates an executable file.
group: A virtual dependency node that refers to one or more other targets.
shared_library: A .dll or .so.
loadable_module: A .dll or .so loadable only at runtime.
source_set: A lightweight virtual static library (usually preferrable over a real static library since it will build faster).
static_library: A .lib or .a file (normally you'll want a source_set instead).
-
Example
要编译成最终可以执行文件,需要三个部分构件系统,1、GN,2、Ninja,3、GCC。GN作为编译逻辑部分,和GYP起到相同的作用,通常和实际工程的配置息息相关。Ninja作为构建中间部分,他用最简单最快速的方式将编译文件编译参数传递给编译系统。GCC作为编译部分,通常随编译系统而变化。
1,gn_test/mian/main.cc:
#include<stdio.h>
#include"lib2/libtest1.h"
int main(void)
{
printf("hello world\n");
func1();
}
2,gn_test/main/BUILD.gn
executable("main"){
sources = [
"main.c",
]
deps = [
"//lib2",
]
}
3, gn_test/lib2/ libtest1.c
#include"libtest1.h"
#include<stdio.h>
void func1()
{
printf("func1\n");
}
4, gn_test/lib2/ libtest1.h
extern void func1();
5, gn_test/lib2/ BUILD.gn
source_set("lib2"){
sources = [
"libtest1.c",
"libtest1.h",
]
public = [
"libtest1.h",
]
}
6,gn_test/.gn
buildconfig = "//build/BUILDCONFIG.gn"
7, gn_test/ BUILD.gn
group("executable"){
deps = [ "//main" ]
}
8, gn_test/build/BUILDCONFIG.gn
set_default_toolchain("//build/toolchains:gcc")
cflags_cc = [ "-std=c++14" ]
include_dirs = [ "//" ]
9, gn_test/build/ toolchains/BUILD.gn
//参考官网
toolchain("gcc") {
tool("cc") {
depfile = "{{output}}.d"
command = "gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
depsformat = "gcc"
description = "CC {{output}}"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
tool("cxx") {
depfile = "{{output}}.d"
command = "g++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
depsformat = "gcc"
description = "CXX {{output}}"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
tool("alink") {
rspfile = "{{output}}.rsp"
command = "rm -f {{output}} && ar rcs {{output}} @$rspfile"
description = "AR {{target_output_name}}{{output_extension}}"
rspfile_content = "{{inputs}}"
outputs = [
"{{target_out_dir}}/{{target_output_name}}{{output_extension}}",
]
default_output_extension = ".a"
output_prefix = "lib"
}
tool("solink") {
soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so".
rspfile = soname + ".rsp"
command = "g++ -shared {{ldflags}} -o $soname -Wl,-soname=$soname @$rspfile"
rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
description = "SOLINK $soname"
# Use this for {{output_extension}} expansions unless a target manually
# overrides it (in which case {{output_extension}} will be what the target
# specifies).
default_output_extension = ".so"
outputs = [
soname,
]
link_output = soname
depend_output = soname
output_prefix = "lib"
}
tool("link") {
outfile = "{{target_output_name}}{{output_extension}}"
rspfile = "$outfile.rsp"
command = "g++ {{ldflags}} -o $outfile @$rspfile {{solibs}} {{libs}}"
description = "LINK $outfile"
rspfile_content = "{{inputs}}"
outputs = [
outfile,
]
}
tool("stamp") {
command = "touch {{output}}"
description = "STAMP {{output}}"
}
tool("copy") {
command = "cp -af {{source}} {{output}}"
description = "COPY {{source}} {{output}}"
}
}
编译:
注意,gn生成的是ninja的输入文件,所以gn需要和ninja的版本适配。可以都从git上下载各自最新代码进行编译。
下载编译ninja
git clone https://github.com/ninja-build/ninja.git
cd ninja
./configure.py –bootstrap
下载编译gn
git clone https://gn.googlesource.com/gn
cd gn
python build/gen.py
ninja -C out
代码组织结构为
gn_test
ninja
gn
编译测试代码
cd gn_test
../gn/out/gn gen out
##可以看到out目录下有build.ninja文件生成
../ninja/ninja –C out/ main
##可以看到main文件生成了
out/main
#打印如下结果
hello world
func1
-
Reference
1)、https://blog.simplypatrick.com/posts/2016/01-23-gn/
2)、https://github.com/p47t/GN-demo
3)、https://gn.googlesource.com/gn