【FFH】 gn项目构建工具学习记录 原创
gn项目构建工具学习
我们为何要使用构建工具?
对于一个新手入门简单的helloworld程序而言,我们可以直接使用gcc命令对其进行编译。对于OpenHarmony系统而言,代码规模庞大,再想要直接使用gcc等工具链的命令进行编译自然是不可能的了,这时就出现了项目构建工具间接地调用工具链,使用构建工具定义编译规则便可以简单高效地进行开发。
-
gn 即 Generate ninja,是一种元构建系统(meta build system),用于生成ninja文件。由于ninja文件编写过于繁琐,所以需要借助gn自动生成ninja文件。
-
ninja则是一个GNU make项目构建工具,ninja文件中的描述便是目标构建的具体方案,ninja根据描述使用gcc等工具链构建系统。
graph LR
gn-->ninja-->gcc等工具链-->编译
对于我们平时用的比较多的cmake和make,gn就相当于cmake,ninja就相当于make。cmake根据CMakeLists.txt文件自动生成工程的makefile文件,make根据makefile文件进行编译构建系统。
graph LR
cmake-->make-->gcc等工具链-->编译
下面将介绍OpenHarmony常用的一些gn命令:
基础学习
字符串
a="hello"
b="GPIO_demo"
列表
p=["hello"]
p+=["world"]
#p=["hello","world"]
模板
定义模板,即类似于C语言的头文件,我们可以在模板中定义一些常用的API函数,便于我们后面的调用
模板文件的后缀为.gni
#引用模板
import("//include/import_file.gni")
遍历
list=["xiaoming","lihua","zhangsan"]
foreach(i,list)
{
print(i)
}
输出结果:
a
b
c
目标
静态库
static_library("hello")
{
sources=[
"hello.c",
]
include_dirs=[
"include",
"//device/include",
]
}
上面这一步便是将hello.c
构建成一个名为hello
的静态库,
其中include_dirs
函数便表示着目标文件hello.c
所需要的头文件所在目录
生成可执行文件
executable("hello_world")
{
sources=[
"hello_world.c",
]
deps=[
"//home/oh/Document/src:hello",
]
}
根据单词意思简单易懂,executable可执行的、sources 来源
deps
则表示该组所包含的依赖,格式为:静态库所在目录:静态库名称
上面这句话表达了:我们告诉编译器我们需要将目标hello_world.c文件进行编译,生成可执行文件
- 测试命令
ninja -C <编译目录>
- -C 作用:在执行操作之前,切换到编译目录
依赖关系组
group("app")
{
deps=[
"//home/oh/Document/src:hello_world",
]
}
group将数个编译目标集合成一个组,生成一个依赖关系组
而这里的deps
所包含的依赖则是引用了hello_world
的可执行文件工程
defines
类似C语言的宏定义,可以为C/C++文件预编译宏定义,若定义的变量需要有值,用=
赋值
static_library("hello")
{
sources=[
"hello.c",
"GPIO_demo.c"
]
include_dirs=[
"include",
"//device/include",
]
defines=[
"GPIO8=8",
]
}
configs
配置文件是命名对象,用于指定标志集,包含目录和定义。他们可以被应用到一个目标,并推到相关的目标。
hello
静态库里面的两个源文件都会被配置config_demo
内的内容
这个地方需要使用+=,而不是=,因为每个目标工程构建编译的都有一系列的默认配置。你要做是将新的配置添加到默认的配置中,而不是全部重写它。如果需要查看默认的配置,你可以在编译文件(BUILD.gn)中使用print函数或者desc命令行子命令。
config("config_demo")
{
defines=[
"GPIO8=8",
"GPIO7=7",
"AWESOME_FEATURE",
]
}
static_library("hello")
{
sources=[
"hello.c",
"GPIO_demo",
]
include_dirs=[
"include",
"//device/include",
]
configs+=[
"config_demo",
]
}
依赖配置
上面configs只能对自己工程hello静态库
使用,我们要是想要让所有依赖到hello
静态库的工程都自动获取此配置,便可以使用到all_dependent_configs
来进行配置.
这表达了其他工程只要引用了hello
静态库,那便会自动加载config_demo
配置文件,无需再次configs
static_library("hello")
{
sources=[
"hello.c",
]
include_dirs=[
"include",
"//device/include",
]
all_dependent_configs=[
"config_demo",
]
}
Cflags
cflags 表示用于 C 编译器的选项,
cppflags 表示用于 C++ 编译器的选项。
这两个变量实际上涵盖了编译和汇编两个步骤。
选项 | 说明 |
---|---|
-S | 只是编译不汇编,生成汇编代码 |
-E | 只进行预编译,不做其他处理 |
-g | 在可执行程序中包含标准调试信息 |
-o file | 把输出文件输出到file里 |
-v | 打印出编译器内部编译各过程的命令行信息和编译器的版本 |
-I dir | 在头文件的搜索路径列表中添加dir目录 |
-L dir | 在库文件的搜索路径列表中添加dir目录 |
-static | 链接静态库 |
-llibrary | 连接名为library的库文件 |
-c | 用于把源码文件编译成 .o 对象文件,不进行链接过程 |
-o | 用于连接生成可执行文件,在其后可以指定输出文件的名称 |
-g | 用于在生成的目标可执行文件中,添加调试信息,可以使用GDB进行调试 |
-Wall | 生成常见的所有告警信息,且停止编译。 |
-w | 关闭所有告警信息 |
-O | 表示编译优化选项,其后可跟优化等级0\1\2\3,默认是0,不优化 |
-v | (在标准错误)显示执行编译阶段的命令,同时显示编译器驱动程序,预处理器,编译器的版本号 |
解决未使用变量警告
当我们在函数中定义了一个变量,但并没有使用到该变量时,编译器便会对此进行报错,返回:unused-but-set-variable
.
当我们不想见到此类报错时,可以在BUILD.gn里面加入以下代码
cflags = [ "-Wno-unused-variable" ]
不错不错,挺好