• [翻译转载] 快速上手GN


    GN Quick Start guide

    原文

    运行 GN

    gn 是一个命令行工具. 对于大型项目, GN 会以特定版本集成在源码中.

    • 对于 Chromium 及基于 Chromium 的项目来说, 会通过 depot_tools 脚本集成. 该脚本应在你的 PATH 中, GN 被该脚本代理成代码树中的真正二进制并运行.
    • 在 Fuchsia 开发环境中, fx gn ... 会代理正确的 GN 二进制并传递给它参数.
    • 对于其他项目, 需要查阅项目文档

    设定构建

    GN 不同于其他构建系统, 你需要设定带有你想要设置的构建文件夹, 这使得你可以同时维护多个不同类型的构建结果.

    一旦你设定好构建文件夹, Ninja 文件在开始构建时会按需被自动的重新生成, 因此不需要每次构建都重新运行 GN.

    创建构建文件夹的命令为:

    gn gen out/my_build

    传递构建命令

    设置构建文件夹的参数:

    gn args out/my_build

    该命令会启动一个编辑器. 向文件中输入k-v类型的构建参数

    is_component_build=true
    is_debug = false
    

    可用的参数取决于你构建的项目(例子中的参数来自 Chromium). 可以通过命令查看可用的参数和它们的默认值

    gn args --list out/my_build

    注意由于不同构建可能有不同参数, 需要指定构建文件夹

    Chrome 开发者可以阅读 Chrome-specific build configuration 来获得更多信息

    针对指定操作系统或架构交叉编译

    运行 gn args out/Default (替换成你的编译目录), 然后为常用的交叉编译选项提供如下参数

    target_os = "chromeos"
    target_os = "android"
    
    target_cpu = "arm"
    target_cpu = "x86"
    target_cpu = "x64"
    

    更多信息见 GN cross compiles.

    简单例子

    添加一个构建文件

    跳转到 examples/simple_build. 这是一个最小化 GN 仓库的根目录.

    (PS: 该目录在 GN 源码仓库下 )

    在该目录下有一个 tutorial 目录. 下有还没加入构建的 tutorial.cc 文件. 在该目录下创建一个新的 BUILD.gn 文件, 来为该文件生成新的可执行 target .

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

    现在我们需要加入该 target. 打开父目录(simple_build)下的BUILD.gn. GN从这个根文件进行加载, 之后加入该文件的所有依赖, 因此我们需要从该文件依赖新的 target.

    你可以将新 target 作为依赖添加到simple_build/BUILD.gn文件里现存的 target 上, 但通常将可执行 target 作为另一个可执行 target 的依赖是不合理的(它们不能被链接). 因此我们新建一个 “tools”组, 一个“组”表示一系列不被编译或链接的依赖.

    group("tools") {
      deps = [
        # 这里也可以写全名 “://tutorial:tutorial”. 
        # 更多信息可见 “gn help labels”
        "//tutorial",
      ]
    }
    

    测试添加后的效果

    simple_build 目录运行:

    gn gen out
    ninja -C out tutorial
    out/tutorial
    

    "Hello, world" 应该正确输出在命令行中

    注: GN 支持静态库的 target 名不全局唯一. 可以对 ninja 传递带有路径(不带“//”)的标签来构建:
    ninja -C out some/path/to/target:my_target

    声明依赖

    examples/simple_build/BUILD.gn定义的 target 中, 有一个被静态库定义的函数GetStaticText().

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

    共享库也定义了一个函数GetSharedText():

    shared_library("hello_stared") {
      sources = [
        "hello_shared.cc",
        "hello_shared.h",
      ]
    
      defines = [ "HELLO_SHARED_IMPLEMENTATION" ]
    }
    

    这里展示了怎样在预处理器中为 target 添加 define. 如果需要多于一个的 define 或赋值 define , 参照如下形式:

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

    现在来看依赖这两个库的可执行文件

    executable("hello") {
      sources = [
        "hello.cc",
      ]
    
      deps = [
        ":hello_shared",
        ":hello_static",
      ]
    }
    

    测试二进制

    simple_build目录运行:

    ninja -C out hello
    out/hello
    

    注意你不需要重新运行 GN, 当构建文件变化时, GN 会自动重新构建 ninja 文件. 可以通过 ninja 在执行的开始时,在命令行中的输出 [1/1] Regenerating ninja files 来确认.

    将设置放到 config 里

    库的用户通常需要 complier flags , defines 和应用它们的 include 目录. “config” 命名的设定集合(没有源文件和依赖), 通过将这些设置放到 “config” 中来达到这个目的.

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

    要把 config 加到 configs 列表里, 来使 config 中的设定在 target 中生效.

    static_library("hello_shared") {
      ...
      # 注 这里通常需要 "+=", 见下文的 "默认 configs”
      configs += [
        “:my_lib_config",
      ]
    }
    

    config 放在 public_configs 列表中则可在全部依赖它的 target 中生效.

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

    public_configs 同样会在当前 target 生效, 因此不需要在两个列表中同时声明.

    默认 configs

    构建的配置会有一些默认应用到所有 target 的设置. 它们会被设置成 configs 的默认值. 你可以使用 “print” 命令来打印它们(该命令在 debug 中非常使用).

    executable("hello") {
      print(configs)
    }
    

    运行 GN 将打印一些类似的结果

    $ gn gen out
    ["//build:compiler_defaults", "//build:executable_ldconfig"]
    Done. Made 5 targets from 5 files in 9ms
    

    target 可以修改这些默认值. 例如, 构建需要通过no_exceptions config 关闭异常, 但 target 可能需要重新启用它们, 为此需要替换默认的 configs 列表.

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

    print 命令也支持字符串差值, 它通过“$“将变量名替换成字符串

    print("The configs for the target $target_name are $configs")

    添加一个新的构建参数

    declare_args 函数中可以定义需要的参数和它的默认值.

    declare_args() {
      enable_teleporter = true
      enable_doom_melon = false
    }
    

    查看gn help buildargs来总览它是如何生效的, gn help declare_args来查看声明它们的细节.

    在一个作用域中重复定义参数是不允许的, 因此定义参数前需要考虑它的名字和作用域.

    不知道发生了什么?

    -v 使 GN 运行在详细模式, 会打印出更多的信息.

    desc 命令

    可以运行 gn desc <build_dir> <targetname> 来获取指定 target 的详细信息

    gn desc out/Default //foo/bar:say_hello

    会打印非常详细的信息. 你也可以只打印一部分, 假如你想要知道 say_hello target 中的 TWO_PEOPLE define 来源于哪里:

    $ gn desc out/Default //foo/bar:say_hello defines --blame
    ...lots of other stuff omitted...
      From //foo/bar:hello_config
           (Added by //foo/bar/BUILD.gn:12)
        TWO_PEOPLE
    

    另一个有趣的变化:

    gn desc out/Default //base:base_i18n deps --tree

    更多信息见 gn help desc

  • 相关阅读:
    190401装饰器-高阶函数-闭包
    190329迭代器-生成器-三元运算-列表解析
    OpenStack-Mitaka
    RabbitMQ
    190328文件处理
    190322函数
    190322字符串
    190321集合
    190320运算符&数据类型
    Zookeeper
  • 原文地址:https://www.cnblogs.com/xxrlz/p/15087425.html
Copyright © 2020-2023  润新知