webrtc的GN构建系统

webrtc的GN构建系统

言剑

言剑

实时音视频划水大师

5 人赞同了该文章

目录

收起

GN是什么

安装方法

建立一个GN工程

GN的命令行使用

GN的语法介绍

生成目标

编译宏定义

依赖关系

分组

配置项

public配置

依赖查找

条件分支

编译器相关配置

其他

总结

最近想单独剥离webrtc的单个模块,因此就对webrtc的编译工程感兴趣,越挖掘深入就觉得gn的确是解决了大多数人的痛点,比相较于其他的工具如cmake更简单。它在的大型工程的依赖问题中解决的非常好,而且语法简洁。

先列出一些资源,给想看第一手资料的小伙伴自己学习:

GN是什么

GN是一个用来产生ninja编译工程的工具,其定位与cmake类似(cmake也可以通过cmake -GNinja生成ninja的工程)。它是由google开发,目前已经用于chromium(包含webrtc)、fuchsia以及相关的工程。

安装方法

可以直接从官方下载二进制包: LinuxmacOS ,Windows,也可以从源码构建:

git clone https://gn.googlesource.com/gn
cd gn

# --allow-warning if you want to build with warnings.
# windows平台编译可能有warning问题导致编不过,可以通过上面的命令开启
python build/gen.py

# windows上需要能够找到cl.exe、link.exe等文件
# 默认使用x64编译
ninja -C out

# To run tests:
out/gn_unittests

建立一个GN工程

  • .gn:位于源码根目录下,这是gn搜索的根目录,一般我们需要在该目录下指定编译配置buildconfig。关于.gn文件查看gn help dotfile帮助
  • BUILD.gn:编译的脚本
  • buildconfig:包含了配置以及工具链等。
[!NOTE] 在chrome里,build目录( chromium/src/build)包含了GN的核心模版和配置以及一些python脚本,可以帮助我们更快地配置工程。一般来说,build是独立的不依赖其他工程,webrtc的构建也是依赖这个build目录。我们可以利用这里提供的工具链(支持使用内置的工具链或者用户指定的)。
对于buildconfig, gn的examples里面也提供了一个例子,也可使用它的例子。不过它只提供了gcc的工具链定义。

下面介绍如何借助于chrome的build来生成工程与编译(主要是自己不像重新折腾编译工具链):

mkdir gn_example
cd gn_examples

# 创建gn基本的结构
git clone https://chromium.googlesource.com/chromium/src/build build
touch .gn
touch BUILD.gn

# 使用chrome的build,需要这个override默认配置
mkdir build_overrides
touch build.gni

touch main.cc

代码如下:

# 使用我们自己的工具链
set DEPOT_TOOLS_WIN_TOOLCHAIN=0

# 指定vs2022以及windows sdk目录
set vs2022_install=D:\Program Files\Microsoft Visual Studio\2022\Community
set WINDOWSSDKDIR=D:\Windows Kits\10

# 需要在msvc的命令行下运行,否则找不到cl.exe等

# 默认是使用clang,这里我们禁用,windows使用msvc
# 使用gn gen 目标目录来生成工程到目标目录,可以指定参数
..\gn\out\gn.exe gen out --args="is_clang=false"

# 编译
ninja -C out

# 运行
out\gn_example.exe

GN的命令行使用

GN的帮助非常详细,可以使用gn --help查看,gn主要有几个命令:

  analyze: Analyze which targets are affected by a list of files.
  args: Display or configure arguments declared by the build.
  check: Check header dependencies.
  clean: Cleans the output directory.
  clean_stale: Cleans the stale output files from the output directory.
  desc: Show lots of insightful information about a target or config.
  format: Format .gn files.
  gen: Generate ninja files.
  help: Does what you think.
  ls: List matching targets.
  meta: List target metadata collection results.
  outputs: Which files a source/target make.
  path: Find paths between two targets.
  refs: Find stuff referencing a target or file.

常用的有:

# 生成工程到out目录,并指定参数
gn gen out --args="is_clang=false,is_debug=false,target_cpu="x86\""

查看编辑编译参数:

# 以下命令会自动打开编辑器,可以修改上面指定的参数
gn args out

查看工程介绍:

# 查看out目录中:gn_example的信息
gn desc out :gn_example

检查头文件依赖:

gn check out :gn_example

以上的命令使用还有很多参数可以设置,需要根据自己的需求慢慢摸索。建议多使用--help来学习。

GN的语法介绍

以下就重点介绍下,gn中场景的语法和使用,这些主要位于BUILD.gn文件。

生成目标

gn的生成目标一般主要有3个,可执行程序、静态库、动态库,分别使用executablestatic_libraryshared_library来创建,如下:

使用executable创建二进制程序,程序名为tutorial,源码tutorial.cc

executable("tutorial") {
  sources = [
    "tutorial.cc",
  ]
}

创建静态库:

static_library("hello_static") {
  sources = [
    "hello_static.cc",
    "hello_static.h",
  ]
}

创建动态库:

shared_library("hello_shared") {
  sources = [
    "hello_shared.cc",
    "hello_shared.h",
  ]

  defines = [ "HELLO_SHARED_IMPLEMENTATION" ]
}

编译宏定义

可以给编译器指定一些定义:

defines = [
  "HELLO_SHARED_IMPLEMENTATION",
  "ENABLE_DOOM_MELON=0",
]

依赖关系

创建一个hello二进制,依赖动态库hello_shared和静态库hello_static,gn的依赖关系通过deps数组指定:

executable("hello") {
  sources = [
    "hello.cc",
  ]

  deps = [
    ":hello_shared",
    ":hello_static",
  ]
}

分组

可以对编译产物、配置等分组,这个分组只是形式上的,不会影响编译:

group("tools") {
  deps = [
    # This will expand to the name "//tutorial:tutorial" which is the full name
    # of our new target. Run "gn help labels" for more.
    "//tutorial",
  ]
}

配置项

可以创建一个配置如下,配置中包含了定义以及头文件包含目录,当前文件中其他地方可以通过":my_lib_config"来引用配置:

config("my_lib_config") {
  defines = [ "ENABLE_DOOM_MELON" ]
  include_dirs = [ "//third_party/something" ]
}

如下引用:

static_library("hello_shared") {
  configs += [
    ":my_lib_config",
  ]
}

配置可以动态更新,比如这里移出了一个配置,增加了一个配置,这里的配置语法非常清晰:

executable("hello") {
  ...
  configs -= [ "//build:no_exceptions" ]  # Remove global default.
  configs += [ "//build:exceptions" ]  # Replace with a different one.
}

public配置

public_config表示,如果有其他库依赖本库,都会应用这个配置:

static_library("hello_shared") {
  ...
  public_configs = [
    ":my_lib_config",
  ]
}

依赖查找

我们的编译目标可以依赖其他的目标,比如一个可执行文件可以依赖一个静态库或者动态库。目标格式一般是路径:目标,如//chrome/browser:version表示依赖chrome/browser这里的version。

路径可以使用完整路径,如//chrome/browser:version(根目录包含.gn),如果在当前文件中,则可以使用:foo,表示依赖当前文件的foo目标。如果一个文件中只有一个目标,也可以省略目标,如//base//base:base的简写。

  • group:可以将一系列target分组
  • copy
  • action
  • action_foreach
  • bundle_deta、create_bundle:仅mac和ios

条件分支

component(“base”) {
  sources = [
    “a.cc”,
    “b.cc”,
  ]

  if (is_win || is_linux) {
    sources += [ “win_helper.cc” ]
  } else {
    sources -= [ “a.cc” ]
  }
}

编译器相关配置

可以指定clfags、宏定义、头文件包含目录等:

executable(“doom_melon”) {
  sources = [ “doom_melon.cc” ]
  
  cflags = [ “-Wall” ]
  defines = [ “EVIL_BIT=1” ]
  include_dirs = [ “.” ]

}

其他

gn也支持模版,可以定义一个新的target类型:

template("wtf") {

}

wtf("xxxx") {

}

action可以用来运行脚本:

action("myaction") {
	script = "myscript.py"
	inputs = [ "input.txt" ]
	outputs = [ ]
}

总结

以上就是对gn的入门介绍。可以帮助大家快速了解gn,并完成一个gn的工程构建。如果需要深入了解gn,当然还是推荐大家多使用帮助或者看下官方文档

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值