WebRTC编译器GN介绍

GN

使用gn编译项目的过程:

  1. 编写.gn文件

    模块化各个模块,分别写一个build.gn,添加进主目录的build.gn的依赖中。

  2. gn gen out/Default

  3. ninja -C out/Default base

1. Ninja

ninja一个构建系统,它以文件(通常是源代码和输出可执行文件)的相互依赖性为输入,并快速地构建它们。Ninja通过将编译任务并行组织,大大提高了构建速度。

源于在Chromium浏览器项目中的工作,该项目具有30,000多个源文件,并且其其他构建系统(包括从自定义非递归Makefile构建的一个)在更改一个文件后将需要十秒钟才能开始构建。 而用ninja构建不到一秒钟。

1.1 设计目标

  1. 即使是非常大的项目,也可以非常快速(即即时)的增量构建。
  2. 关于如何构建代码的选择很少。对于不同项目,可能有不同的构建策略,ninja简化了这些选择。
  3. 让依赖正确,在一些特殊情况下Makefiles很难解决的。
  4. 速度和简单之间,选择速度。

1.2 示例

cflags = -Wall

rule cc
  command = gcc $cflags -c $in -o $out

build foo.o: cc foo.c

为字符串生成一个更可读的名字

cflags = -g

使用$符号取值

rule cc
  command = gcc $cflags -c $in -o $out

​ 定义一个叫cc的rule,然后这条rule的内容是一个可执行的命令,$in 展开为输入文件(foo.c),$out 展开为输出文件(foo.o) for the command.

​ Build语句声明输入文件和输出文件之间的关系,以build关键词开始,格式是build outputs: rulename inputs这个规则说明所有的输出文件都是从输入文件产生的。当output不存在或者input改变时,都会重新创建output。上面的例子里面out代表输出列表。

2. GN

GN是一个用来生成ninja构建文件的工具。

2.1 运行参数

生成构建目录

gn gen out/my_build

设置构建参数

gn gen out/my_build --args="..."

可以设置多个target os以及target cpugn args out/Default(或者使用--args方式)

target_os = "chromeos"
target_os = "android"

target_cpu = "arm"
target_cpu = "x86"
target_cpu = "x64"

查看所有的参数

gn args --list out/Default

2.1 Build文件

示例
static_library(“base”) {
  sources = [
    “a.cc”,
    “b.cc”,
  ]
}

加上依赖

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

  deps = [
    “//fancypants”,
    “//foo/bar:baz”,
  ]
}
设计原则
  1. 模块化

创建一个反映代码组件和子组件的目录结构,把BUILD文件放在每个目录中。

  1. 明确模块之间的关系
内置的target类型
  • executable

    定义一个可执行target

  • shared_library

    在链接器行上为目标指定共享库,该目标在“ deps”中列出了共享库。

  • static_library

    创建.a以及.lib文件

  • loadable_module

    创建一个目标文件,只能(并且只能)在运行时加载和卸载。

  • source_set:

    编译没有中间库的源文件,将其视为静态库,但没有静态库链接规则。是经过编译但未链接的一组源,相反,生成的目标文件是隐式添加到依赖源的所有目标的链接器中。

  • group

    把一些依赖合并起来并命名

  • copy

  • action, action_foreach

  • bundle_data, create_bundle: Mac & iOS

另外,我们也可以创建自定义类型。

标签说明
  • 完整标签

//chrome/browser:version

  • 隐式标签

//base, //base::base的缩写

  • 当前目录

:bar,表示当前目录下的bar文件

依赖放到一个group中

gorup是没有被编译或者依赖的集合。

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",
  ]
}
条件语句
component(“base”) {
  sources = [
    “a.cc”,
    “b.cc”,
  ]

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

Config持有flag, defines, include directories这样一些东西,但不包含源文件和依赖。

添加移除配置

executable(“doom_melon”) {
  configs -= [
    "//build/config/compiler:chromium_code",
  ]
  configs += [
    "//build/config/compiler:no_chromium_code",
  ]
}

把配置放到一个group中

config(“myconfig”) {
  defines = [ “EVIL_BIT=1” ]
}

executable(“doom_melon”) {
  ...
  configs += [ “:myconfig” ]
}

test(“doom_melon_tests”) {
  ...
  configs += [ “:myconfig” ]
}
动态加载一些外部的数据文件
shared_library(“icu”) {
  # This target is loaded @ runtime.
  data_deps = [
    “:icu_data_tables”,
  ]
}
权限控制
  • deps vs public_deps

控制依赖的可见性

  • visibility

设置当前文件可以被其他文件依赖

  • assert_no_deps

依赖项都不应该链接

  • testonly

不链接到production代码中

你可能感兴趣的:(WebRTC编译器GN介绍)