[GN] 谷歌元构建系统GN,toolchain配置

注:主要信息来自于GN的帮助文件

典型格式: 

tool(<tool type>) {
    <tool variables...>
  }


tool type可选的范围:

编译器:
"cc": C编译器
"cxx": C++ 编译器
"objc": Objective C 编译器
"objcxx": Objective C++ 编译器
"rc": Resource compiler (Windows .rc files)
"asm": 汇编器

链接器:
"alink": 静态库链接器,一般进行打包操作,即ar
"solink": 动态库链接器
"link": 完整链接器,主要用于链接出可执行文件

其他工具:
"stamp": 创建时间戳文件
"copy": 复制操作
"action": 默认执行

平台专用工具:
"copy_bundle_data": [iOS, macOS] 复制捆绑文件的工具
"compile_xcassets": [iOS, macOS] 编制资产目录的工具


每个工具可以使用的属性变量

command  [string with substitutions]
适用于:所有工具,"action"则为必选项
指定一个可以执行的语句

default_output_dir  [string with substitutions]
适用于:链接器
相对于输出文件的默认目录(root_build_dir)的路径。 它可以包含其他替换模式。 这将是{{output_dir}}扩展的默认值(下面讨论)但会被目标中的“ output_dir”变量覆盖(如果有的话)。
GN除了传递此字符串外,不对其进行任何处理,可能具有特定于目标的覆盖。

default_output_extension [string ]
适用于:链接器工具
扩展可链接工具的主要输出。它包括前导点。这将是{{output_extension}}扩展的默认值(如下所述),但如果指定了目标,则将被目标中的“ output extension”变量覆盖。空字符串表示无扩展名。
GN除了对该扩展进行传递外,实际上并没有做任何其他事情,可能会传递特定于目标的覆盖。 人们通常会在“输出”中使用{{output_extension}}值来读取该值。
示例:default_output_extension =“ .exe”

depfile [string with substitutions]
适用于:编译器工具(可选)
如果该工具可以写入“ .d”文件,则可以指定结果文件的名称。 这些文件用于列出在构建时发现的头文件依赖项(或其他隐式输入依赖项)。 另请参见“ depsformat”。
示例:depfile =“ {{output}}。d”

depsformat [string]
适用于:编译器工具(当指定了depfile时)
deps输出的格式。 可选值为“ gcc”或“ msvc”。 有关更多信息,请参见Ninja文档中的“ deps”。
示例:depsformat =“ gcc”

description  [string with substitutions, optional]
适用于:所有工具
运行命令时要打印什么。
示例:description =“Compiling {{source}}”

lib_switch  [string, optional, link tools only]
lib_dir_switch  [string, optional, link tools only]

适用于:链接器工具(“alink”除外)
这些字符串将分别放在库和库搜索目录的前面,因为链接器在指定它们的方式上有所不同。
如果指定:
lib_switch =“ -l”
lib_dir_switch =“ -L”
那么[“ freetype”,“ expat”]的“ {{libs}}”扩展为“ -lfreetype -lexpat”。

outputs  [list of strings with substitutions]
适用于:链接器和编译器工具(必需)
该工具生成的输出文件的名称数组。这些是相对于构建输出目录的。必须始终至少有一个输出文件。可以有多个输出(例如,链接器可能会产生一个库和一个导入库)。
该数组仅向GN声明该工具将生成什么文件。您有责任指定实际产生这些文件的工具命令。
如果为共享库链接指定了多个输出,则应考虑设置link_output,depend_output和runtime_outputs。
生成.obj文件的编译器工具示例:
outputs = [
"{{source_out_dir}}/{{source_name_part}}.obj"
]
生成.dll和.lib的链接器工具的示例。使用{{target_output_name}},{{output_extension}}和{{output_dir}}可使目标覆盖这些值。
outputs = [
"{{output_dir}}/{{target_output_name}}"
    "{{output_extension}}",
"{{output_dir}}/{{target_output_name}}.lib",
]

pool [label, optional]
适用于:所有工具(可选)
工具使用的池的标签。 池用于限制在构建过程中可以同时执行的任务数。

link_output  [string with substitutions]
depend_output  [string with substitutions]

适用于:仅“ solink”(可选)
这两个文件指定应使用solink工具的哪个输出进行链接和依赖项跟踪。 这些应与“outputs”中的条目匹配。 如果未指定,则“outputs”数组中的第一项将全部使用。 有关更多信息,请参见下面的“共享库的单独链接和依赖性”。
在Windows上,这些工具会生成.dll共享库和.lib导入库,您将希望前两个成为导入库,第三个成为.dll文件。 在Linux上,如果不执行单独的链接/依赖关系优化,则所有这些都应该是.so输出。

output_prefix  [string]
适用于:链接器工具(可选)
用于输出名称的前缀。 默认为空。 如果该前缀尚不存在,则将在该前缀之前加上目标的名称(如果是手动为其指定,则为output_name)。 结果将显示在{{output_name}}替换模式中。 单个目标可以通过设置以下内容来选择退出输出前缀:
output_prefix_override = true
这通常用于在库上添加“ lib”:
output_prefix = "lib"

precompiled_header_type  [string]
适用于:“ cc”,“ cxx”,“ objc”,“ objcxx”
预编译头文件的类型。 如果未定义或为空字符串,则预编译的头文件将不会用于此工具。 否则,请使用“ gcc”或“ msvc”。
对于要用于给定目标的预编译头,目标(或应用于它的配置)还必须指定“ precompiled_header”,并且
“ msvc”样式的标头,一个“ precompiled_source”值。 如果类型是“ gcc”,然后“ precompiled_header”和“ precompiled_source”都必须解析为同一文件,尽管每种格式都需要不同。

restat  [boolean]
适用于:所有工具(可选,默认为false)
请求Ninja在此工具运行后检查文件时间戳,以确定是否有任何更改。 如果您的工具能够在输出文件未更改的情况下跳过写入输出,请设置此选项。
通常,Ninja会假定运行工具时输出是新的,并且下游依赖项必须重建。 当将此设置为trye时,Ninja可以跳过对实际不影响输出的输入更改重建下游依赖项。

rspfile  [string with substitutions]
适用于:除“action”外的所有工具(可选)
响应文件的名称。 如果为空,将不使用响应文件

rspfile_content  [string with substitutions]
适用于:除“action”以外的所有工具(使用“ rspfile”时需要)
要写入响应文件的内容。 这可能包括要发送给该工具的全部或部分命令,使您可以绕过OS命令行长度限制。 此示例将输入和库添加到响应文件,但直接在命令行上传递链接器标志:
tool("link") {
command = "link -o {{output}} {{ldflags}} @{{output}}.rsp"
rspfile = "{{output}}.rsp"
rspfile_content = "{{inputs}} {{solibs}} {{libs}}"
}

runtime_outputs  [string list with substitutions]
适用于:链接器工具
如果指定,则此列表是应添加到运行时deps的输出的子集(请参见“ gn help runtime_deps”)。 默认情况下(如果runtime_outputs为空或未指定),它将是link_output。


扩展工具变量

所有路径都相对于根构建目录,该目录是运行所有工具的当前目录。 这些扩展适用于所有工具:

 {{label}}
当前目标的标签。 通常在链接工具的“description”字段中使用。 对于默认工具链中的目标,该工具链将从标签中省略,对于其他工具链中的目标,该工具链也将包括在内。

{{label_name}}
目标标签的简称。 这是冒号后面的部分。 对于“ // foo / bar:baz”,它会变成“ baz”。 与{{target_output_name}}不同,它不受工具中的“ output_prefix”或目标上设置的“ output_name”的影响。

{{output}}
当前构建步骤的相对路径和输出名称。 如果有多个输出,则将扩展为所有输出的列表。 示例:“ out / base / my_file.o”

{{target_gen_dir}}
{{target_out_dir}}

当前目标分别生成文件的目录和输出目录。 没有结尾的斜杠。 另请参阅{{output_dir}}了解链接器工具。 示例:“ out / base / test”

{{target_output_name}}
当前目标的简称,不包含路径信息;如果目标中指定了“ output_name”变量的值,则简称该值。 如果有的话,这将包括“ output_prefix”。 另请参见{{label_name}}。
示例:目标名为“ foo”的目标为“ libfoo”,链接器工具“ lib”的输出前缀。

编译器工具具有单个输入和单个输出的概念,以及一组特定于编译器的标志。 提供以下扩展:
{{asmflags}}
{{cflags}}
{{cflags_c}}
{{cflags_cc}}
{{cflags_objc}}
{{cflags_objcc}}
{{defines}}
{{include_dirs}}

字符串对应于为目标指定的已处理标志/定义/包含目录。
示例:“-enable-foo --enable-bar”
Defines将以“ -D”作为前缀,include目录将以“ -I”作为前缀(这些与Posix工具以及Microsoft的工具一起使用)。

{{source}}
当前输入文件的相对路径和名称。
 示例:“ ../../ base / my_file.cc”

{{source_file_part}}
源文件的文件部分,包括扩展名(无目录信息)。
示例:“ foo.cc”

{{source_name_part}}
源文件的文件名部分,没有目录或扩展名。
示例:“ foo”

{{source_gen_dir}}
{{source_out_dir}}

当前输入文件的生成文件和输出目录中的目录分别。 如果源文件与声明目标所在的目录位于同一目录中,则它们将与上面的“目标”版本相同。 示例:“ gen / base / test”

链接器工具具有多个输入和(可能)多个输出。 静态库工具(“alink”)不被视为链接器工具。 提供以下扩展:
{{inputs}}
{{inputs_newline}}

扩展到链接步骤的输入。 这将是目标文件和静态库的列表。
示例:“ obj / foo.o obj / bar.o obj / somelibrary.a”
“ _newline”版本将用换行符而不是空格分隔输入文件。 这在响应文件中很有用:某些链接器可以带有“ -filelist”标志,该标志需要换行符分隔的文件,而某些Microsoft工具具有固定大小的缓冲区,用于解析响应文件的每一行。

{{ldflags}}
扩展到为目标指定的已处理的ldflags和库搜索路径集。
示例:“-m64 -fPIC -pthread -L / usr / local / mylib”

{{libs}}
展开到要链接到的系统库的列表。 每一个都将以“ lib_switch”作为前缀。
作为支持Mac的特殊情况,名称以“ .framework”结尾的库将添加到{{libs}}中,其前面带有“ -framework”,而lib前缀将被忽略。
示例:“-lfoo -lbar”

{{output_dir}}
如果目标未覆盖输出目录,则目标中的“ output_dir”变量的值或工具中的“ default_output_dir”值的值。 这将相对于root_build_dir,并且不会以斜杠结尾。 将会 ”。” 用于输出到root_build_dir。
这与GN根据目标的路径定义的{{target_out_dir}}略有不同,并且不可替代。 {{output_dir}}用于最终输出,{{target_out_dir}}通常用于目标文件和其他输出。
通常{{output_dir}}可以用{{target_out_dir}}或{{root_out_dir}}来定义

{{output_extension}}
如果目标未指定输出扩展名,则目标中的“ output_extension”变量的值,或工具中的“ default_output_extension”值的值。
示例:“.so”

{{solibs}}
{{inputs}}中未指定的共享库依赖项中的额外库。 这是共享库中link_output文件的列表(如果solink工具指定了与“ depend_output”分开的“ link_output”变量)。
通常,您的工具应将它们与libs一样对待。
示例:“ libfoo.so libbar.so”

静态库(“alink”)工具允许{{arflags}}以及常见的工具替换。
复制工具允许通用的编译器/链接器替换,以及{{source}}作为复制源。 印章工具仅允许替换常用工具。
copy_bundle_data和compile_xcassets工具仅允许通用工具替换。 这两个工具都是创建iOS / macOS捆绑包所必需的,仅需要在这些平台上进行定义。
将使用一个源调用copy_bundle_data工具,并且需要将其复制(可选地优化数据表示)至其输出。 可以使用目录作为输入来调用它,并且需要递归复制它。
将使用需要编译为单个输出的一个或多个源(每个资产目录)来调用compile_xcassets工具。 可以使用以下替代方法:
{{inputs}}
扩展到.xcassets列表,以用作编译资产目录的输入。

{{bundle_product_type}}
扩展到将包含已编译资产目录的捆绑软件的product_type。 通常对应于相应create_bundle目标的product_type属性。

{{bundle_partial_info_plist}}
扩展到资产目录编译器生成的部分Info.plist的路径。 通常基于create_bundle目标的target_name。

共享库的单独链接和依赖性
共享库的特殊之处在于,并非对它们所做的所有更改都需要重新链接从属目标。 如果共享库已更改,但导入或导出没有不同,则无需重新链接从属代码,这可以加快构建速度。
如果您的链接步骤可以输出共享库中的导出列表,并且仅在新的导出库不同的情况下才写入文件,所以该文件的时间戳可用于触发重新链接,而实际的共享库将用于链接 。
您需要指定
restat = true
在链接器工具中执行此操作,因此Ninja将在链接后检测依赖项文件的时间戳是否已更改(否则,它将始终假定运行命令会更新输出):
tool("solink") {
    command = "..."
    outputs = [
    "{{output_dir}}/{{target_output_name}}{{output_extension}}",
    "{{output_dir}}/{{target_output_name}}"
        "{{output_extension}}.TOC",
    ]
    link_output =
    "{{output_dir}}/{{target_output_name}}{{output_extension}}"
    depend_output =
    "{{output_dir}}/{{target_output_name}}"
        "{{output_extension}}.TOC"
    restat = true
}
例如:
 

toolchain("my_toolchain") {
# Put these at the top to apply to all tools below.
lib_switch = "-l"
lib_dir_switch = "-L"

tool("cc") {
    command = "gcc {{source}} -o {{output}}"
    outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ]
    description = "GCC {{source}}"
}
tool("cxx") {
    command = "g++ {{source}} -o {{output}}"
    outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ]
    description = "G++ {{source}}"
}
};

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值