Fuchsia 构建系统:变体

使用 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" ]

选择器语法

通常,您会将一组字符串用于变体选择器。每个元素都定义了一个变体名称 以及适用的对象(可选)系统会按照您指定的顺序测试选择器, 都适用

  • 单独使用变体名称(例如 asanhost_ubsan。这些全局选择器应列在最后。

  • 将已命名变体应用于特定目标,格式为 variant_name/target_output_name 例如 asan-ubsan/ledgerhost_asan/zxdb_tests。这些代码应在所有代码 来覆盖更通用的规则。

变体与二进制文件(如 executableloadable_moduletest、 或 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 安装未包含在软件包中,而是包含在启动文件系统中。 这些程序没有自己的共享库加载器, 执行它们的组件提供的任何共享库。这通常 是可行的,因为 shls 等程序只有非常少的、非常常见的 依赖项不过,并不能保证该组件包 拥有足够或兼容的共享库以便命令行程序 需求。支持 ASan 的软件包通常不包含适用于这些程序的适当启动器 因此大多数支持 ASan 的组件都无法运行 /boot。如果已启用 ASan 的组件尝试执行此操作,则会收到上述错误消息。

幸运的是,修复操作涉及执行所有软件包应该执行的操作 即明确声明其依赖项。如果您的包裹 依赖于某个二进制文件,它应将其声明为依赖项,然后使用 声明的依赖项,而不是 /boot 目录中的依赖项。如果 我们的构建系统中定义的 zircon_extras_manifest 规则, //build/config/fuchsia/zircon_images.gni可让你依赖 在 /boot 目录中找到的二进制文件。这些文件会安装在 /pkg/bin/,您应该从那里执行这些任务。