使用 Fuchsia GN 制造机械可以构建单独的组件 不同“变体”中的字符。变体通常只是意味着使用额外的编译器 但如果您多编写一些 GN 代码,他们就能做得更多。 到目前为止定义的变体可实现 排错程序和 LTO。
指定变体
使用 GN build 参数将变体规范传入 build
select_variant
。请注意,这些代码的顺序
变体选择器很重要,如下面的语法部分所述。
使用 fx set
,通过 --variant=
标志传递字符串变体选择器:
fx set core.x64 --variant=asan/cat --variant=asan/ledger --variant=host_asan
此示例指示 build 编译“cat”。和“分类账”Fuchsia 二进制文件以及所有托管工具 (有关这些字符串的确切语法,请参阅下文)。
如果您已有 build 目录,则可以通过修改 GN 参数来添加或修改变体
(根据需要使用 build 的 GN 输出目录替换 out/default
):
fx gn args out/default
该命令将打开一个编辑器。向该文件附加一个用于分配变体选择器的行
以字符串列表的形式添加到 select_variant
构建参数中:
select_variant = [ "asan/cat", "asan/ledger", "host_asan" ]
选择器语法
通常,您会将一组字符串用于变体选择器。每个元素都定义了一个变体名称 以及适用的对象(可选)系统会按照您指定的顺序测试选择器, 都适用
单独使用变体名称(例如
asan
或host_ubsan
。这些全局选择器应列在最后。将已命名变体应用于特定目标,格式为
variant_name/target_output_name
例如asan-ubsan/ledger
或host_asan/zxdb_tests
。这些代码应在所有代码 来覆盖更通用的规则。
变体与二进制文件(如 executable
、loadable_module
、test
、
或 fuchsia_driver
),而不能是 Fuchsia 软件包、Fuchsia 组件、共享库、静态库或
源代码集。一旦变体与目标匹配,它所依赖的所有库都将使用
该变体。由于 Fuchsia 软件包和组件与变体选择无关,
在变体规范中指定软件包或组件名称则不会产生任何效果。每个可执行文件
或软件包中的模块可以指定自己的变体。
默认情况下,目标输出名称是您提供给 GN 目标定义的名称(用英文引号括起来)。
此目标定义了 my_program
目标,您可以使用选择器对其应用 asan
asan/my_program
:
executable("my_program") { ... }
有些目标会使用 GN output_name
变量替换输出名称(这通常是为了
提供全局唯一的二进制文件名称以避免冲突)。在此示例中,变体选择器
与替换的输出名称匹配,因此您仍将使用 asan/my_program
对其应用 asan:
executable("bin") {
output_name = "my_program"
}
在某些情况下,模板可能会以不明显的方式替换输出名称。如果您发现 变体不匹配,一种简单的方法是在 build 目录中查找 并使用该名称
高级选择器
您还可以提供一个 GN“作用域”用作变体选择器,
控制匹配目标的构建方式。必须在“gn args”中设置改为
相较之下命令行。请参阅
select_variant
build 参数文档:
。
查看可用变体的列表并详细了解如何定义
请参阅
known_variants
build 参数。
常见的变体名称
debug
:未优化的编译。release
:优化的编译。asan
:编译时使用的 Address Sanitizer 检查内存滥用情况,如释放后使用和出界数组访问。ubsan
:用于编译时检查的未定义的行为排错程序 例如整数溢出和指针错位等未定义行为的异常。asan-ubsan
:asan + ubsan 的组合。lto
:链接时优化 整个计划优化。thinlto
:精简链接时优化 对整个程序进行更轻量级优化,以加快编译速度。coverage
:用于生成 C++ 的代码覆盖率信息。coverage-rust
:涵盖 Rust。无法与coverage
同时使用,截止日期为: Rust 和 C++ 编译器之间存在与 LLVM 库版本偏差的问题。kasan
:仅将 asan 应用于内核。gcc
:使用 GCC 而不是 Clang 进行编译。启动配置支持此功能 并且只会影响某些目标(包括内核)。
在asan-fuzzer
模糊测试工具。这些变体
,应按照模糊测试说明来设置 build。
此外,还有一些简写选择器可将变体应用到宿主二进制文件(工具
在 Linux 或 Mac 主机上运行的计算机):
* host_asan
* host_asan-ubsan
* host_coverage
* host_coverage-rust
* host_profile
某些预构建版本可能只适用于部分变体。有关 ffmpeg 的具体内容,请参阅 //src/media/lib/ffmpeg/BUILD.gn.
问题排查备注
检查变体是否已应用于二进制文件
每个变体都有一个唯一的输出目录和工具链名称,命名为
<architecture>-<variant name>
。然后,系统会将这些二进制文件复制到根 build 目录,
和构建。例如,针对 x64 设备的 asan-ubsan 变体将使用
//build/toolchain/fuchsia:x64-asan-ubsan
工具链,并将二进制文件放入
out/default/x64-asan-ubsan
(将 build 目录替换为“default”)。
运行 GN(通常是 build 的第一步)后,您会看到一个 binaries.json
文件
其中包含每个二进制文件的信息。您可以通过 dist
文件名和 label
(即
工具链名称在括号中)。如果您的二进制文件
可能在目标和主机上都被编译,另请注意记录中的 os
字段。这是一个
使用“asan-ubsan”针对 x64 编译的 Fuchsia 二进制文件示例变体:
{
"cpu": "x64",
"debug": "x64-asan-ubsan/exe.unstripped/blobfs",
"dist": "x64-asan-ubsan/blobfs",
"elf_build_id": "x64-asan-ubsan/blobfs.build-id.stamp",
"label": "//src/storage/blobfs/bin:blobfs(//build/toolchain/fuchsia:x64-asan-ubsan)",
"os": "fuchsia",
"type": "executable"
},
复制 ASan 故障
我们的基础架构在启用 ASan 的配置中运行测试。要复制
构建启用了 ASan 的基础架构,使用 fx repro <build_id>
并运行
发出的所有命令
请注意,这将构建由基础架构运行的所有测试 并将其安装在系统映像中您可能不希望出现这种情况,原因有两个:
- 构建所有测试通常很慢,而且没有必要进行构建。开发者可以 发现将软件包标签限制在所需测试中更为有效。
- 在系统映像中提前安装所有测试意味着 软件部署工作流不会执行。
从启用 ASan 的二进制文件中启动可执行文件
如果您尝试使用 ASan 变体,则可能会遇到类似于 如下所示:
launcher: error: Launch: elf_load: handle_interp failed
dlsvc: could not open 'asan/ld.so.1'
Fuchsia 的结构是围绕软件包和组件构建的。每个组件均包含 以及它需要运行的所有共享库这有助于 Fuchsia 规避库 影响其他操作系统的版本控制问题。这也意味着,如果 如果您要在组件内运行二进制文件,则必须提供 相应二进制文件的相应共享库加载器
一组命令行程序位于/boot/
Fuchsia 安装未包含在软件包中,而是包含在启动文件系统中。
这些程序没有自己的共享库加载器,
执行它们的组件提供的任何共享库。这通常
是可行的,因为 sh
和 ls
等程序只有非常少的、非常常见的
依赖项不过,并不能保证该组件包
拥有足够或兼容的共享库以便命令行程序
需求。支持 ASan 的软件包通常不包含适用于这些程序的适当启动器
因此大多数支持 ASan 的组件都无法运行
/boot
。如果已启用 ASan 的组件尝试执行此操作,则会收到上述错误消息。
幸运的是,修复操作涉及执行所有软件包应该执行的操作
即明确声明其依赖项。如果您的包裹
依赖于某个二进制文件,它应将其声明为依赖项,然后使用
声明的依赖项,而不是 /boot
目录中的依赖项。如果
我们的构建系统中定义的 zircon_extras_manifest
规则,
//build/config/fuchsia/zircon_images.gni
可让你依赖
在 /boot
目录中找到的二进制文件。这些文件会安装在
/pkg/bin/
,您应该从那里执行这些任务。