1

[gn+ninja学习 0x02] GN入门示例

 1 year ago
source link: https://ost.51cto.com/posts/18258
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

[gn+ninja学习 0x02] GN入门示例

OpenHarmony使用gn+ninja来维护开源项目的构建。之前没有接触过gn+ninja,是时候系统性的来学习下了。边学边记录下学习过程,希望对同样需要学习gn+ninja的朋友有所帮助。

这一篇,我们通过示例来学习GN的入门知识。

1、环境配置

作为开源软件,可以自己编译,也可以直接使用现有的二进制文件,官方下载地址如下。通常外网速度慢,甚至打不开。还好,gn、ninja相关的源代码可以在OpenHarmony的third party仓库下找到,见参考资料。

https://github.com/ninja-build/ninja/releases
https://chrome-infra-packages.appspot.com/p/gn/gn

搭建OpenHarmony环境后,也会自动配置gn和ninja的构建环境,这就很方便了。下载openharmony源码,使用hb编译时会自动下载gn+ninja工具时,在目录prebuilts/build-tools/linux-x86/bin下可以找到gn+ninja。更多信息请参考OpenHarmony的环境搭建文档吧。

2、GN Quick Start guide快速入门

快速入门参考了官方文档,读者也可以去阅读下原文https://gitee.com/openharmony/third_party_gn/blob/master/docs/quick_start.md。

2.1 Running GN

搭建好环境后,就可以命令行运行gn命令。如下:

zhushangyuan@DESKTOP-RPE9R4O:~/openharmony$ gn help help
gn help <anything>

  Yo dawg, I heard you like help on your help so I put help on the help in the
  help.

  You can also use "all" as the parameter to get all help at once.

Switches

  --markdown
      Format output in markdown syntax.

Example

  gn help --markdown all
      Dump all help to stdout in markdown format.

2.2 Setting up a build

GN允许你设置专有的构建目录,不同的构建目录使用不同的参数设置。设置构建目录后,当配置文件更新时,Ninja文件会自动重新生成,而不需要重新运行GN。设置构建目录使用下述命令:

gn gen out/my_build

不是随便一个目录就可以运行上述命令的,否则会报错:

ERROR Can't find source root.
I could not find a ".gn" file in the current directory or any parent,
and the --root command-line argument was not specified.

如果想练习下设置构建目录,可以切换到gn的example目录下进行尝试,如下:

cd ~/openharmony/third_party/gn/examples/simple_build/
gn gen out/my_build

2.3 Passing build arguments传递构建参数

执行命令gn args --list out/my_build ,可以查询可用的参数列表及其他们的默认值。必须指定构建目录,可用参数在不同的构建目录下是不一样的。

执行命令gn args out/my_build可以为构建目录设置构建参数,该命令执行后,会打开一个编辑器,输入构建参数,类似下面:

is_component_build = true
is_debug = false

3、Step-by-step示例学习

3.1 Adding a build file添加构建文件

切换到目录~/openharmony/third_party/gn/examples/simple_build/,这是最小化的GN构建示例目录。在目录下有个tutorial 目录,内有一个源文件tutorial.cc,但是有利于构建之外。在tutorial 目录下创建一个BUILD.gn文件,用于构建可执行文件target:

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

然后,把构建target目标告知构建系统。simple_build目录下的BUILD.gn文件,是GN构建的入口根文件,从这里加载启动后,然后加载依赖。因此,我们在此根文件中添加引用到我们上述创建的构建target。

通常,把一个可执行文件作为另外一个可执行文件的依赖,没有意义,无法链接。我们创建一个tools组group。在GN中,group用于收集维护不会编译或者链接的依赖。如下:

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

3.2 Testing your addition验证编译

命令行进入simple_build命令,执行如下命令,可以看到会有打印输出“Hello from the tutorial.”。

gn gen out
ninja -C out tutorial
out/tutorial

3.3 Declaring dependencies 声明依赖

我们再来看下examples/simple_build/BUILD.gn中的构建target的定义,⑴处定义的可执行文件构建target依赖hello_shared和hello_static,前面的冒号表示这些依赖的target在当前文件中定义,可以在下文找到。⑵处定义了一个共享库的构建target,它定义了一个函数GetSharedText(),也演示了如何使用预处理宏。⑶处定义了一个静态库的构建target,它定义了一个函数GetStaticText()。


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

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

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

    defines = [ "HELLO_SHARED_IMPLEMENTATION" ]
    }

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

3.4 Test the binary测试运行二进制

命令行进入simple_build命令,执行如下命令,可以看到会有打印输出“Hello, world”。命令中-C指定构建目录,后面的hello也可以构建的target名称。使用命令gn ls out可以输出所有的构建target。

ninja -C out hello
out/hello

3.5 Putting settings in a config使用config配置设置

使用library库的时候,经常需要编译选项、宏定义、include头文件包含等。可以把这些设置放到一个config的命名设置集里,不能放置源文件或依赖。如下:

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

为了把一个config里面的设置应用到target里,可以加到configs列表里,如注释所示,使用+=,这样默认的设置不会被覆盖。

static_library("hello_shared") {
  ...
  # Note "+=" here is usually required, see "default configs" below.
  configs += [
    ":my_lib_config",
  ]
}

一个config也能应用到所有依赖当前target的target上,只需要把config添加到public_configs 列表里,如下。public_configs 里面的设置也会应用到当前的target,不需要重复指定。

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

构建配置一般设置一些配置项,可以默认应用到所有的targe里。例如,在文件examples\simple_build\build\BUILDCONFIG.gn中,定义了如下默认configs。可以在BUILD.gn的target里使用语句“print(configs)”打印输出默认配置。

# Apply that default list to the binary target types.
set_defaults("executable") {
  configs = _shared_binary_target_configs

  # Executables get this additional configuration.
  configs += [ "//build:executable_ldconfig" ]
}
set_defaults("static_library") {
  configs = _shared_binary_target_configs
}
set_defaults("shared_library") {
  configs = _shared_binary_target_configs
}
set_defaults("source_set") {
  configs = _shared_binary_target_configs
}

3.6 Add a new build argument添加构建参数

可以使用declare_args声明可以接受的构建参数,并提供默认值。可以使用命令查看构建参数的使用帮助gn help buildargs。

declare_args() {
  enable_teleporter = true
  enable_doom_melon = false
}

声明参数后,在生成构建目录时,可以在命令行指定构建参数:

gn gen out/FooBar --args="enable_doom_melon=true os=\"android\""

4、gn常用命令

  • gn gen out/dir [–args=“…”]:创建新的编译目录,会自动创建args.gn文件作为编译参数。
  • gn args --list out/dir:列出可选的编译参数。
  • gn ls out/dir:列出所有的target;
  • gn ls out/dir “//:hello_word*”:列出匹配的target;
  • gn desc out/dir “//:hello_word”:查看指定target的描述信息,包括src源码文件、依赖的lib、编译选项等;
  • gn refs out/dir 文件:查看依赖该文件的target;
  • gn refs out/dir //:hello_word:查看依赖该target的target

注意//代表从项目根目录开始。

我们初步了解了下构建系统、元构建系统是做什么的,了解到gn是个元构建系统,类似cmake。接下来的一篇会介绍gn入门知识、具体如何使用等等。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK