【FFH】 gn项目构建工具学习记录 原创

X丶昕雪
发布于 2023-1-21 20:33
浏览
2收藏

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" ]

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2023-1-23 13:24:06修改
4
收藏 2
回复
举报
1条回复
按时间正序
/
按时间倒序
物联风景
物联风景

不错不错,挺好

回复
2023-1-25 21:28:12
回复
    相关推荐