google gn 构建工具系统命令详解 (guozongling)

gn analyze <out_dir> <input_path> <output_path>

分析文件列表影响哪些目标。

这个命令有三个参数:

<out_dir>是构建目录的路径。

<input_path>是一个文件的路径,该文件包含一个带有三个字段的JSON对象:

    - "files": 要检查的文件名列表

    - "test_targets": 运行我们希望运行的测试所需的目标标签列表。

    - "additional_compile_targets": 我们希望重构的目标标签列表,这个不是测试必须的。这个字段和“test_targets”之间的重要区别在于,如果additional_compile_targets列表中的一个项引用了一个组,那么如果该组的任何依赖项过期了,则会返回,但是组本身不需要返回。如果依赖项本身是组,则重复相同的筛选。此筛选可用于避免重新构建不受输入文件影响的组的依赖项。列表还可能包含字符串“all”,用于引用一个伪组,该伪组包含构建图中的每个根目标。

    这种过滤行为也称为“修剪”编译目标列表。

    如果<input_path> 是 "-",就从标准输入(stdin)读取。

<out_path> 是指命令的结果写在哪里。结果是一个JSON文件,包含一个或多个下面的字段:

    - "compile_targets": 这个列表衍生自受输入文件影响的<compile_targets>。由于上面所描述的对编译目标的过滤方式,这个列表可能会包含没在输入列表中出现的目标。

    - "test_targets": 这个列表来自受输入文件影响的<test_targets>,这个列表将是输入列表的一个适当子集。

    - "invalid_targets": 输入中不存在于构建图中的任何名称的列表。如果这个列表是非空的,“error”字段也将被设置为“Invalid targets”。

    - "status": 这个字符串包含下面三个值中的一个:

        - "Found dependency"

        - "No dependency"

        - "Found dependency (all)"

        第一种情况:<compile_targets>和<test_targets>返回的目标列表会被[ninja]进行编译构建。

        第二种情况:没有受影响的东西,无需构建。

        第三种情况:[gn]不能决定正确的行为方式,安全起见,会将输入当作输出返回。

    - "error": 代表有错误,会包含描述错误的信息。错误情况可能是输入文件的格式不正确,或者包含有无效的目标。

如果<out_path>是"-",会输出到标准输出(stdout)。

 

命令将返回【1】如果不能读取输入文件或者写输出文件,或者有一些构建的错误,否则就返回【0】。

尤其是,即使<error> 不为空并且发生了非致命性错误,这时也返回【0】。换句话说,它总是尽量的去向输出的JSON文件中输出一些信息,而不是返回错误码。

 

gn args: (command-line tool)

显示或者配置由构建声明的参数

gn args <out_dir> [--list] [--short] [--args] [--overrides-only]

可以用"gn help buildargs"查看更多的概述关于构建的参数如何起作用

用法:

  gn args <out_dir>

    在编辑器中打开给定的构建目录,会在<out_dir>路径下面打开参数文件,如果<out_dir>不存在,则会创建该目录并且打开一个空的参数文件,你可以写入一些参数信息,例如:

    enable_doom_melon=false 

    os="android"

gn 会在环境变量中顺序查找指定的编辑器,顺序为 GN_EDITOR, VISUAL, EDITOR,你可以指定这三个变量的值,将值指定为你自己的编辑器。

注意: 你可以在<out_dir>路径下面为构建系统手动编辑"args.gn"中的参数,然后运行命令"gn gen <out_dir>"。

gn args <out_dir> --list[=<exact_arg>] [--short] [--overrides-only] [--json]

  列出当前配置中可用的所有构建参数,或者,如果为列表标志指定了exact_arg,则只指定一个构建参数。

  如果 --short 被指定,则只有名字和当前的值会被打印出来。

  如果 --overdides-only被指定,则只有那些被重写过的参数的名字和当前值才会被打印。

  如果 --json 被指定,则会以JSON的格式来打印输出的信息。

Examples

  gn args out/Debug

     用args命令在out/Debug路径下面打开一个默认的参数文件args.gn(一般默认是这个文件名字)。

  gn args out/Debug --list

    没有 --short 的时候,此时会以文字注释的形式输出参数的当前值,以及默认值。你可以知道默认值是什么,当前值是什么。

  gn args out/Debug --list --short

    打印带有默认值的参数。(注意,打印的不是参数的默认值,而是当前值,只不过这参数不被重写的时候也有个系统的默认值,所以这样的参数就是带有默认值的参数。比如你在args.gn中自己定义了一个新的变量"enable_my_script=true",那这个新的变量是不打印的。)

  gn args out/Debug --list --short --overrides-only

    只打印被重写过的参数。

    比如host_os = "linux"是默认值,你改成了host_os = "windows",那么就会值显示 host_os = "windows"这一个,因为host_os已经被重写了。

  gn args out/Debug --list=target_cpu

    没有 --short ,此时会打印target_cpu的当前值,以及默认值。(如果参数未被重写,那就只有默认值,也就只打印默认值)

  gn args --list --args="os=\"android\" enable_doom_melon=true"

    打印带有默认值的参数。(查看 gn args out/Debug --list --short 部分,括弧中有解释)。

    另外,--args后面的值会直接写入文件(args.gn)中,原来文件中的内容会清空。(因此可能会影响其它参数的值)  

gn check <out_dir> [<label_pattern>] [--force] [--check-generated]

这个命令和 "gn gen --check"功能是一样的,但这个命令(gn check)无法写出构建文件(类似于BUILD.gn的文件)。

这个命令的功能是检查类C(C/C++/objc/objc++/等等,也就是基于C语言的代码文件,因为要检查#include包含进来的文件)文件中用 #include 引入进来的文件是否合法有效。

<label_pattern>是一个匹配模式,如果设置了,那么只有和这个模式匹配的目标(target)才会被检查。

--check-generated

    有些文件是在编译过程中由构建系统生成的,比如Google用一些 .idl后缀的文件生成 .h和.cc文件。

    这些文件由于一开始就不存在,所以通常是不会检查的。

    但如果设置了这个选项,那些已经被生成过的文件就会被检查。

--check-system

    检查系统风格的文件,也就是除了检查双引号("")引入的文件之外,连尖括号(<>)引入的文件也会被检查。

--default-toolchain

    只检查使用默认工具链的目标。

    "//src:*" 这种通配符匹配会将src目录下面的所有目标都匹配,但如果加了 --default-toolchain 选项,那些指定了与默认工具链不同的目标就不会被匹配到,也就不会被检查。在GN构建系统中,每个目标(target)都可以被指定不同的工具链编译,指定工具链的方式就是在目标的后面添加 "([工具链路径])"。

    比如, 我构建 "//src/foo:foo"这个目标的时候,想指定"//toolchain:win32_toolchain"工具链编译它,那么写法就是:

        "//src/foo:foo(//toolchain:win32_toolchain)"

--force

    忽略目标中的"check_includes = false"设置,对所有需要检查的目标进行检查。

 

什么会被检查?

    .gn 文件可以用"check_targets"指定一个要检查的列表,也可以用"no_check_targets"指定一个不被检查的列表。而如果从命令行指定,那"check_targets"和"no_check_targets"就都不会生效。

    如果目标设置"check_includes = false",而"gn check"没有使用"--force",这个目标就不会被检查。(看上面说明,--force)

 

被检查的目标:

    GN会打开目标中的类C源文件,查看#include引入了哪些文件。

    检查双引号("")引入的文件,除非指定了 --check_system,不然不会检查尖括号(<>)引入的系统文件。

    如果 #include 行有 "nogncheck"注释,那就不会检查这个文件。比如 #include "mytest/testgn.h"  // nogncheck

    GN 会根据目标中"include_dirs"指定的路径搜寻文件,还有当前目录。

    GN不会进行预处理,因此它无法理解那些根据条件判断引入的文件(可能会都检查,可以用"nogncheck"注释)。比如:

        #if defined(TEST_GN) 

        #include "mytest/testgn.h"

        #endif

    只有匹配到已知文件的 #include才会被检查,未知路径的就会被忽略。

 

包含文件是否有效:

    被引入文件必须存在于当前目标,或者当前目标所公共依赖的目标中。

    多个目标引入同一个文件,只需要有一个目标验证被引入文件是有效的即可。

    如果一个目标中只有"sources",则这个目标中所有的东西都默认是 public 的,那么其它有效公开依赖的这个目标的目标都可以引入这个目标中的文件。(只有public的东西才可以被继承下去,查看 public 的详细说明)

    如果一个目标有 public,那这个目标中其它的东西都默认为private,包括sources也是私有的,不管依赖关系如何,只有 public 指定的文件可以被其它目标所引入。

    <action>输出的东西是被当作public处理的,所以可以被继承。

 

问题修复的建议:

    如果你有第三方的项目,而且很难修复或者不需要检查引入文件,那你可以用"check_includes = false"来避开检查。

    如果你有条件判断处理,如上面所说的 #if defined(), 你要确保构建系统和预处理时的判断条件一致,还要用 "nogncheck"来注释。

    如果你有毫不相交的目标(targets),你可以用"allow_circular_includes_from"标注。理想情况下,每个依赖项都应该具有相同的依赖项,因此从这些依赖项继承的配置是一致的。

    如果你有独立的头文件需要在几个目标之间共用,那你可以把这些头文件放入 <source_set>。 可以用 public或者只用<sources>。这样这个source set都可以被引用依赖了。

 

例子:

    gn check out/Debug

        检查所有的文件。 

    gn check out/Default //foo:bar

        只检查在 //foo:bar 目标中的文件。

    gn check out/Default "//foo/*

        只检查 //foo 目录下所有目标的文件。

gn clean <out_dir>... 

删除所有输出目录下的除了args.gn的文件。为再次编译创造干净的环境。这个路径与 gn gen <out_dir>对应。

gn desc <out_dir> <label or pattern> [<what to show>] [--blame] [--format=json]

显示所给目标或配置的信息。

<label or pattern>可以是一个目标标签,配置标签,或者一个匹配模式标签。只有匹配成功的才会显示。

<what to show> 包括如下(如果不指定,默认显示):

    all_dependent_configs

    allow_circular_includes_from

    arflags [--blame] args

    cflags [--blame]

    cflags_c [--blame]

    cflags_cc [--blame]

    check_includes

    configs [--tree] (see below)

    data_keys

    defines [--blame]

    depfile

    deps [--all] [--tree] (see below)

    framework_dirs

    frameworks

    include_dirs [--blame]

    inputs ldflags [--blame]

    lib_dirs libs

    metadata

    output_conversion

    outputs

    public_configs

    public

    rebase

    script

    sources

    testonly

    visibility

    walk_keys

    weak_frameworks

    runtime_deps

[--format=json] 以JSON的格式输出。

gn help <anything> 

可以用这个命令查看gn任意命令或者标签的用法。只要你想使用的任何标签或者函数都可以查看。

比如: gn help all_dependent_configs

gn help --markdown all 输出所有gn的用法。

 

一些次要的命令不作解释了。

gn outputs <out_dir> <list of target or file names...> 

列出所给目标或文件的输出文件。

例子:

gn outputs out/debug some/directory:some_target

      列出目标"some/directory:some_target"的输出。

gn outputs out/debug src/project/my_file.cc | xargs ninja -C out/debug

    只编译这个文件,每个工具链都会编译。(如上面所说,每个target可以用不同的工具链编译)

git diff --name-only | xargs gn outputs out/x64 | xargs ninja -C out/x64

    编译所有改动过的文件。这个前提是用git管理的代码,因为git diff是GIT命令。 

gn path <out_dir> <target_one> <target_two> 

找出两个目标直接的依赖路径。

--all 

    找到所有路径,而不是只找第一个。公共路径先被打印,并按照路径长度的顺序打印。然后是非公共路径的打印,也是按照路径长度的顺序。

--public

    只找公共路径。不能和--with-data使用。

--with-data

    找data deps。不能和--public使用。

(不知道一起使用会怎么样,没试过,~_~)

目标声明 (Target declarations)

action

    可以让你执行一次脚本生成一个或多个输出文件。 如果你想要每个文件都执行一次脚本就使用 action_foreach。

    在<action>中"sources"和"inputs"效果一样。如果你想把"sources"传递给脚本,你需要在"args"中包含它。

    由于没有对路径进行处理,GN不知道哪些参数是路径,哪些参数不是路径,所以需要用rebase_path()函数对路径进行处理,这个函数可以将路径转换成相对于root_build_dir(当前命令执行的路径)的路径。

    如果命令行的参数太长,你可以用响应文件(response file)来传递参数给你的脚本。(查看 gn help response_file_contents的用法)

    参数太长的话,系统会把这些参数卸载一个不限大小的临时文件中,而在脚本中使用"{ {response_file_contents}}"来替代那个临时文件。因此,你可以用"{ {response_file_contents}}"来传参。

    推荐你把要传给脚本的输入放在"sources"变量中,而需要运行你这个脚本的其它python文件放在"inputs"变量中。

    因为<deps>和<public_deps>总是在<action>执行之前就完成,所以<action>可以依赖前面步骤所输出的东西作为依赖。

 

    GN可以为所有<action>命令设置ninja的"restat"的标志,将其设置为"restat = 1",那么ninja就会在<action>执行完成后检查输出(文件或别的什么)的时间戳,如果这个时间戳不变,那就意味着不需要重新构建相关的东西,这样也减少了不必要的构建。

    <outputs> 可以指定脚本输出的名字。

例子:

 action("run_this_guy_once") {
    script = "doprocessing.py"
    sources = [ "my_configuration.txt" ]
    outputs = [ "$target_gen_dir/insightful_output.txt" ]

    # Our script imports this Python file so we want to rebuild if it changes.
    inputs = [ "helper_library.py" ]

    # Note that we have to manually pass the sources to our script if the
    # script needs them as inputs.
    args = [ "--out", rebase_path(target_gen_dir, root_build_dir) ] +
           rebase_path(sources, root_build_dir)
  }

action_foreach

遍历<sources>中的文件,每个文件都会执行一次脚本。

如果你有额外的数据需要传给脚本,比如一个共享配置或者一个python脚本,你应该把它放入<inputs>变量。

{ {source_name_part}} 是输入文件的名字,比如 "foo.idl"的名字就是"foo"

两个大括号 "{ { }}" 表示的是占位符,可以了解一下GN中的占位符用法,有哪些占位符可以使用。

例子:

  # Runs the script over each IDL file. The IDL script will generate both a .cc
  # and a .h file for each input.
  action_foreach("my_idl") {
    script = "idl_processor.py"
    sources = [ "foo.idl", "bar.idl" ]

    # Our script reads this file each time, so we need to list it as a
    # dependency so we can rebuild if it changes.
    inputs = [ "my_configuration.txt" ]

    # Transformation from source file name to output file names.
    outputs = [ "$target_gen_dir/{
   {source_name_part}}.h",
                "$target_gen_dir/{
   {source_name_part}}.cc" ]

    # Note that since "args" is opaque to GN, if you specify paths here, you
    # will need to convert it to be relative to the build directory using
    # rebase_path().
    args = [
      "{
   {source}}",
      "-o",
      rebase_path(relative_target_gen_dir, root_build_dir) +
        "/{
   {source_name_part}}.h" ]
  }

copy:

声明一个拷贝文件的目标。

所有的输出文件都必须在构建输出目录的里面。通常会用到 |$target_out_dir| 或者 |$target_gen_dir|,这两个分别是生成目标的最终目录,以及产生中间文件的目录。

<sources>和<outputs>必须被指定,<sources>你可以指定多少都行,但<outputs>只能有一项。

如果有多个文件输入,那么就要用源扩展。(可以查看sources_expansion用法)

可以看看占位符"{ {source_name_part}}"的用法。

例子:

  # Write a rule that copies a checked-in DLL to the output directory.
  copy("mydll") {
    sources = [ "mydll.dll" ]
    outputs = [ "$target_out_dir/mydll.dll" ]
  }

  # Write a rule to copy several files to the target generated files directory.
  copy("myfiles") {
    sources = [ "data1.dat", "data2.dat", "data3.dat" ]

    # Use source expansion to generate output files with the corresponding file
    # names in the gen dir. This will just copy each file.
    outputs = [ "$target_gen_dir/{
   {source_file_part}}" ]
  } 

executable:

生成可执行文件目标。目标的生成要取决于这个目标中的源文件是用什么编程语言,一个目标不可以有多种编译语言,比如一个target可以包含C和C++源文件,但不可以有C和Rust源文件。

可用变量:

  Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
         asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
         libs, precompiled_header, precompiled_source, rustflags,
         rustenv, swiftflags
  Deps: data_deps, deps, public_deps
  Dependent configs: all_dependent_configs, public_configs
  General: check_includes, configs, data, friend, inputs, metadata,
           output_name, output_extension, public, sources, testonly,
           visibility
  Rust variables: aliased_deps, crate_root, crate_name

generated_file

声明一个generated_file类型的目标。在解析式将数据写到磁盘。

这个目标类型反映了write_file()函数的一些功能,也具有从它的依赖中手机metadata的能力。

<outputs>变量表示输出到的文件名,它必须是一个包含单个元素的列表。

<output_conversion>变量表示写数据值的格式。

<contents>和<data_keys>必须被指定其中的一个,使用<data>就会把值的内容写到文件,而使用<data_keys>就会触发metadata的收集。

例子:

  Given the following targets defined in //base/BUILD.gn, where A depends on B
  and B depends on C and D:

    group("a") {
      metadata = {
        doom_melon = [ "enable" ]
        my_files = [ "foo.cpp" ]

        # Note: this is functionally equivalent to not defining `my_barrier`
        # at all in this target's metadata.
        my_barrier = [ "" ]
      }

      deps = [ ":b" ]
    }

    group("b") {
      metadata = {
        my_files = [ "bar.cpp" ]
        my_barrier = [ ":c" ]
      }

      deps = [ ":c", ":d" ]
    }

    group("c") {
      metadata = {
        doom_melon = [ "disable" ]
        my_files = [ "baz.cpp" ]
      }
    }

    group("d") {
      metadata = {
        my_files = [ "missing.cpp" ]
      }
    }

  If the following generated_file target is defined:

    generated_file("my_files_metadata") {
      outputs = [ "$root_build_dir/my_files.json" ]
      data_keys = [ "my_files" ]

      deps = [ "//base:a" ]
    }

  The following will be written to "$root_build_dir/my_files.json" (less the
  comments):
    [
      "baz.cpp",  // from //base:c via //base:b
      "missing.cpp"  // from //base:d via //base:b
      "bar.cpp",  // from //base:b via //base:a
      "foo.cpp",  // from //base:a
    ]

  Alternatively, as an example of using walk_keys, if the following
  generated_file target is defined:

  generated_file("my_files_metadata") {
    outputs = [ "$root_build_dir/my_files.json" ]
    data_keys = [ "my_files" ]
    walk_keys = [ "my_barrier" ]

    deps = [ "//base:a" ]
  }

  The following will be written to "$root_build_dir/my_files.json" (again less
  the comments):
    [
      "baz.cpp",  // from //base:c via //base:b
      "bar.cpp",  // from //base:b via //base:a
      "foo.cpp",  // from //base:a
    ]

  If `rebase` is used in the following generated_file target:

  generated_file("my_files_metadata") {
    outputs = [ "$root_build_dir/my_files.json" ]
    data_keys = [ "my_files" ]
    walk_keys = [ "my_barrier" ]
    rebase = root_build_dir

    deps = [ "//base:a" ]
  }

  The following will be written to "$root_build_dir/my_files.json" (again less
  the comments) (assuming root_build_dir = "//out"):
    [
      "../base/baz.cpp",  // from //base:c via //base:b
      "../base/bar.cpp",  // from //base:b via //base:a
      "../base/foo.cpp",  // from //base:a
    ]

变量:

  contents
  data_keys
  rebase
  walk_keys
  output_conversion
  Deps: data_deps, deps, public_deps
  Dependent configs: all_dependent_configs, public_configs

group

声明指定的目标组。

此目标类型允许您创建元目标,它只将一组依赖项收集到一个命名的目标中。组还可以指定适用于其依赖项的配置。

变量:

  Deps: data_deps, deps, public_deps
  Dependent configs: all_dependent_configs, public_configs

例子:

  group("all") {
    deps = [
      "//project:runner",
      "//project:unit_tests",
    ]
  }

你可以把一组依赖,或者一组配置放在一个group里面。

shared_library

声明一个共享库目标。Linux平台会生成一个.so文件,也就是动态库。

变量:

  Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
         asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
         libs, precompiled_header, precompiled_source, rustflags,
         rustenv, swiftflags
  Deps: data_deps, deps, public_deps
  Dependent configs: all_dependent_configs, public_configs
  General: check_includes, configs, data, friend, inputs, metadata,
           output_name, output_extension, public, sources, testonly,
           visibility
  Rust variables: aliased_deps, crate_root, crate_name, crate_type

source_set

声明一个源集类型目标。目前只支持C语言的源集。(也就是类C风格,比如C,C++)

变量:

  Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
         asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
         libs, precompiled_header, precompiled_source, rustflags,
         rustenv, swiftflags
  Deps: data_deps, deps, public_deps
  Dependent configs: all_dependent_configs, public_configs
  General: check_includes, configs, data, friend, inputs, metadata,
           output_name, output_extension, public, sources, testonly,
           visibility

static_library

生成一个静态库。

变量:

  complete_static_lib
  Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
         asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
         libs, precompiled_header, precompiled_source, rustflags,
         rustenv, swiftflags
  Deps: data_deps, deps, public_deps
  Dependent configs: all_dependent_configs, public_configs
  General: check_includes, configs, data, friend, inputs, metadata,
           output_name, output_extension, public, sources, testonly,
           visibility
  Rust variables: aliased_deps, crate_root, crate_name

target

用所给的类型生成一个target。

target(target_type_string, target_name_string) { ... }

例如 

  target("shared_library", "doom_melon") 就等同于 shared_library("doom_melon")

  target("static_library", "doom_melon") 就等同于 static_library("doom_melon")

例子:

  if (foo_build_as_shared) {
    my_type = "shared_library"
  } else {
    my_type = "source_set"
  }

  target(my_type, "foo") {
    ...
  }

assert

断言一个表达式为真。与C语言assert一样。

assert(<condition> [, <error string>])

如果表达式为假,构建就会失败,当个为假的时候就会输出第二个参数的内容。

例子:

  assert(is_win)
  assert(defined(sources), "Sources must be defined");

config

声明一个config对象。

这个配置可以应用于目标上。

这个config里面可以包含flags(cflags/cflags_c/cflags_cc/...), 头文件路径,变量或宏定义(defines)等等。

这个配置可以像target一样通过它自己的标签来被引用。

一个目标按这样的顺序生成:

1. 使用本目标中直接被定义的值;

2. 使用<configs>指定的配置;

3. 根据<public_configs>的指定,遍历依赖查找配置;

4. 根据<all_dependent_configs>的指定,遍历依赖查找配置。

 

在配置定义中有效的变量:

  Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
         asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
         libs, precompiled_header, precompiled_source, rustflags,
         rustenv, swiftflags
  Nested configs: configs

用于应用配置的目标上的变量:

  all_dependent_configs, configs, public_configs

例子:

  config("myconfig") {
    include_dirs = [ "include/common" ]
    defines = [ "ENABLE_DOOM_MELON" ]
  }

  executable("mything") {
    configs = [ ":myconfig" ]
  }

declare_args

声明构建参数。

如果命令行或者工具链参数都没有指定值,那么就会用declare_args设置的默认值,这个默认值无法覆盖命令行的值。

1. declare_args()执行,那么在这个闭包({} 代码块之间)中定义的值都是可以读的,而在这个之前定义的值都不可以。

2. 执行完这个块作用域,在里面设置的变量就会被保存,这些变量称之为"默认值"。一经保存,这些值就可以通过args.gn文件来重写。

3. "gn args"可以重写默认值,在文件中的代码可以使用那些变量。

 

  • 在declare_args() { ... }这个块作用域中不用执行复杂的工作,因为这是设置默认值的,复杂的工作可能会被忽视。尤其是,不要用exec_script()去设置默认值,如果你想用脚本设置默认值,你应该在declare_args()这个块作用域之后再设置,而且应该是设置一些没被定义的值,比如 [],"",或者-1。
  • 因为你不能在同一个块作用域中读定义的变量,如果你想用一个被定义的默认值去定义另一个变量,那么你可以写两个declare_args() { ... } 块:

       

        declare_args() {
          enable_foo = true
        }
        declare_args() {
          # Bar defaults to same user-overridden state as foo.
          enable_bar = enable_foo
        }

例子:

  declare_args() {
    enable_teleporter = true
    enable_doom_melon = false
  }

  如果你想重写enable_doom_melon:
    gn --args="enable_doom_melon=true enable_teleporter=true"
注意: enable_teleporter=true也要写上, 不需要改变就写原来的值。(好像--args是修改args.gn文件,会覆盖文件中的内容,~_~ 谁会把重要东西写在args.gn呢?反正我不用这个文件。)

defined

返回ture如果所给的参数被定义了。

例子:

  template("mytemplate") {
    # To help users call this template properly...
    assert(defined(invoker.sources), "Sources must be defined")

    # If we want to accept an optional "values" argument, we don't
    # want to dereference something that may not be defined.
    if (defined(invoker.values)) {
      values = invoker.values
    } else {
      values = "some default value"
    }
  }

exec_script

同步执行一个脚本,返回输出。

 exec_script(filename,
              arguments = [],
              input_conversion = "",
              file_dependencies = [])

如果脚本不存在,返回非零错误码。

filename:

    要执行的脚本名称,如果filename不是绝对路径,则会被当成相对于当前目录的路径。可以用rebase_path()改变路径,这个函数经常用到,只要你用文件了,可能就要用用它转换路径。

arguments:

    作为参数传递给脚本。可以为空,表示没有参数。

input_conversion:

    控制文件如何读取或者解析。可以查看io_conversion的帮助。(gn help io_conversion)

file_dependencies(可选的):

    脚本读取或者依赖的一个文件列表,这些依赖会被添加到构建结果中,如果这些依赖有改变,构建就会重新生成,脚本也会再运行。

例子:

  all_lines = exec_script(
      "myscript.py", [some_input], "list lines",
      [ rebase_path("data_file.txt", root_build_dir) ])

  # This example just calls the script with no arguments and discards the
  # result.
  exec_script("//foo/bar/myscript.py")

filter_exclude

filter_exclude(values, exclude_patterns)

values:

    必须是一个字符串列表。

exclude_patterns:

    用于匹配的文件模式列表。(也就是过滤规则)

[values]这列表中的值,如果在[exclude_patterns]中可以匹配到,那么就要被过滤掉。

也就是按照 [exclude_patterns] 的规则来筛选 [values] 里面的值。

可以总结为: 匹配到就过滤。

例子:

  values = [ "foo.cc", "foo.h", "foo.proto" ]
  result = filter_exclude(values, [ "*.proto" ])
  # result will be [ "foo.cc", "foo.h" ]

filter_include

filter_include(values, include_patterns)

与<filter_exclude>作用相反。

[values]这列表中的值,如果在[include_patterns]中可以匹配到,那么就要被保留。

可以总结为: 匹配到就保留。

例子:

  values = [ "foo.cc", "foo.h", "foo.proto" ]
  result = filter_include(values, [ "*.proto" ])
  # result will be [ "foo.proto" ]

foreach

    foreach(<loop_var>, <list>) {
      <loop contents>
    }

遍历列表。

例子:

  mylist = [ "a", "b", "c" ]
  foreach(i, mylist) {
    print(i)
  }

  Prints:
  a
  b
  c

forward_variables_from

从不同的作用域拷贝变量。

 forward_variables_from(from_scope, variable_list_or_star,
                         variable_to_not_forward_list = [])

from_scope:</

### 回答1: Chromium 109在Windows系统上的构建非常简单,你可以通过以下步骤完成:1. 下载Chromium源代码;2. 从Chromium源代码中构建Windows系统版本;3. 使用Visual Studio编译Chromium;4. 在Windows系统上运行Chromium。 ### 回答2: Chromium是一款开源的网络浏览器项目,它的源代码可以通过开源社区获取并进行构建。下面是Chromium 109在Windows系统上的构建步骤: 1. 准备开发环境:首先,需要安装Windows操作系统,并确保系统中已经安装了Git以及Python等必要的开发工具。 2. 下载源代码:进入Chromium的官方源代码仓库(https://chromium.googlesource.com/chromium/src),通过Git将源代码下载到本地计算机。 3. 安装依赖项:在源代码的根目录下运行一些脚本文件,脚本文件会检测环境并安装必要的依赖项,如编译器、库文件等。 4. 配置构建:Chromium有许多构建选项,可以通过在源代码根目录下运行GN命令配置构建GN文件是一个用于配置构建的文本文件,可以在其中指定编译器、构建类型、构建目标等选项。 5. 开始构建:运行Ninja命令开始构建Chromium。Ninja是一个构建系统,它会根据GN配置文件生成一系列的构建指令,并进行编译链接。 6. 等待构建完成:构建过程可能需要一些时间,取决于计算机性能以及网络速度。 7. 完成构建构建成功后,在构建目录中就能找到生成的Chromium可执行文件。 以上是Chromium 109在Windows系统上的简要构建步骤,具体的步骤可能会因为开发环境和个人需求的不同而有所变化,但总体上是类似的。 ### 回答3: Chromium 109是指在Windows操作系统构建Chromium(Google Chrome的开源版本)的步骤。 构建Chromium的第一步是设置开发环境。首先,您需要下载并安装Visual Studio,这是Windows系统上的主要开发工具。然后,您需要安装depot_tools,这是Chromium开发所需的一组工具。您还需要安装Python,并将其添加到系统的环境变量中。 接下来的步骤是获取Chromium的源代码。您可以使用depot_tools中的命令行工具"fetch"来执行此操作。执行"fetch chromium"命令将下载最新的Chromium源代码。 下载完成后,您需要为构建过程选择适当的构建配置。Chromium支持多个配置选项,如Debug、Release、ThinLTO等。您可以使用gclient命令将配置设置为您希望构建的配置。 在选择了构建配置后,您可以使用gn工具生成构建脚本。gn生成的构建脚本将包含构建Chromium所需的所有编译选项和依赖库。 接下来,您需要运行ninja命令来执行实际的构建。ninja命令将按照gn生成的构建脚本所定义的规则进行构建。这个过程可能需要一些时间,具体取决于您的计算机的性能和网络速度。 构建完成后,您可以在构建输出文件夹中找到生成的可执行文件和其他相关文件。您可以运行生成的可执行文件来启动Chromium浏览器。 总的来说,构建Chromium 109在Windows系统上需要准备开发环境、获取源代码、选择构建配置、生成构建脚本和执行构建等步骤。这些步骤需要一些开发工具和命令行操作,并可能需要一些时间和计算资源。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值