常见样式和最佳实践

概览

以下样式和最佳实践适用于 Fuchsia 中的所有 Bazel 文件。

此页面是 Bazel 样式指南和最佳实践的一部分,其中 包含针对特定场景的其他指南。

源代码文件和依赖项列表的局部变量

虽然官方指南 不鼓励使用依赖项 变量,但 Fuchsia 允许使用 依赖项变量来管理大型共享源代码文件或依赖项列表。请考虑列表是否基本相似,或者是否仅共享一些常见项,以此进行练习。

不减法:切勿从列表变量中移除项。

请勿使用 glob()

请勿使用 glob() [SHAC 错误]。请改为明确列出文件。

fx build 从 Ninja 操作运行 Bazel,而 Ninja 仅跟踪 glob() 上次运行时匹配的文件。如果您添加了 glob() 现在会匹配的文件,Ninja 不会注意到。增量 build 和 fx test 运行会继续使用旧文件列表。明确列出文件时,添加文件意味着修改 BUILD.bazel 文件,而 Ninja 会跟踪该文件。

此规则特定于 Fuchsia。官方 Bazel 样式指南允许非递归 glob,并且在 Bazel 不再在 Ninja 中运行时,可能会再次允许使用非递归 glob。

build/bazel/shac/glob_allowlist.json 运行检查的每个代码库的根目录中列出了对 glob() 的现有使用情况(例如, //build/bazel/shac/glob_allowlist.json 和 //vendor/google/build/bazel/shac/glob_allowlist.json)。 未经 build 团队批准,请勿添加新条目。系统不会检查 third_party/ 目录下的上游代码。

切勿使用递归 glob

无论是否涉及 Ninja,都不应在任何 Bazel 代码中使用递归 glob (**)。官方 Bazel 样式指南 禁止对源文件使用递归 glob。 它们会跳过包含自己的 BUILD.bazel 文件的子目录,因此很难确定它们匹配哪些文件。此外,它们在每个目录中的缓存和并行化效果不如 BUILD.bazel 文件。

唯一的例外是第三方库和其他代码库(例如 //vendor/... 代码库)的特定情况,在这些情况下,列出每个路径并不实际。在 third_party/ 目录之外,这些路径仍需要许可名单条目。

公开范围

以下是一般准则,适用于 BUILD.bazel 和 .bzl 文件。如需了解更具体的详细信息,请参阅每个文件的页面。

尽可能在 BUILD.bazel 和 .bzl 文件中指定公开范围

唯一支持该属性但不需要指定该属性的场景是软件包(目录)私有的宏。

请勿使用公开范围

请勿在 bazel_sdk/ 目录之外使用公开范围 ("//visibility:public" 或 visibility("public")) 。只有当代码被外部 代码库使用时,此访问级别 才适用,这不 适用于 fuchsia.git 中的非 SDK 代码。

公开范围应尽可能缩小,同时仍允许测试和反向依赖项访问

公开范围应仅限于需要该范围和/或应允许使用该范围的目标。请保持保守但实用。例如,如果目标在 //src 的五个直接子目录中使用,请考虑使用 //src:__subpackages__,以避免在添加新用途时需要修改公开范围。但是,如果目标仅应由驱动程序使用,请将其限制为实现驱动程序的软件包。

使用软件包组进行常见的非琐碎公开范围定义

如果多个目标的 visibility 应限制为同一组 标签,请考虑使用 package_group表示该组。package_group 在与目标一起使用时也 支持负公开范围,但与 加载公开范围一起使用时不支持。

请勿混用 SDK 和平台符号及目标

平台目标(即 AIB 或 IDK 中的所有内容)不得使用 Fuchsia Bazel SDK 中定义的符号、其提供的目标或使用其构建的目标。

反之亦然,使用 Fuchsia Bazel SDK 构建的目标不应依赖于平台目标或从平台 .bzl 文件加载符号。

请勿使用 Fuchsia Bazel SDK 路径

平台代码绝不应访问包含 bazel_sdk 的文件路径或 Fuchsia Bazel SDK 代码库路径,例如:

  • @fuchsia_sdk//

  • @internal_sdk//

  • @rules_fuchsia//fuchsia

唯一允许使用的此类路径以 @fuchsia_rules_common/ 开头,但只有 build 团队应直接使用这些路径。

平台代码还应避免使用 bazel_sdk/ 路径,但与 Fuchsia Bazel SDK 共享实现的特定 build 规则除外。

目标和 .bzl 文件的标签

引用目标

引用目标(例如,在 deps 中)时,只要不使用 禁止的标签模式,就允许使用以以下任一项开头的标签:

从 .bzl 文件加载

Fuchsia 平台的大多数通用宏和规则都可以在 //build/bazel/rules/ 中找到。

只要不使用禁止的标签模式,就可以安全地从标签以以下内容开头的 .bzl 文件中 load():

还允许使用以下内容,但只有 build 团队的开发者可能会使用它们:

  • @fuchsia_build_config//:defs.bzl

  • @fuchsia_build_info//:args.bzl

  • @fuchsia_rules_common//

禁止的标签模式

请勿使用 [SHAC 错误]:

  • 工作区根软件包标签(以 //: 开头的标签)

    • 在非常特殊且非常罕见的情况下,需要使用此标签 (请参阅问题 560343570),但通常只有 build 团队才应使用此标签。
  • 在软件包 名称(即英文冒号 (:) 后的标签部分)中包含斜杠 (/) 的标签。

    • 集成第三方库时存在罕见的例外情况。

fuchsia_... 文件和符号位于 Fuchsia Bazel SDK 中

避免定义名称以 fuchsia_ 开头的文件、宏和规则。 以 fuchsia_ 开头的现有名称实例可能属于 Fuchsia Bazel SDK(请参阅 请勿使用 Fuchsia Bazel SDK 路径),避免使用此类名称有助于保持这种分离。

如需了解在需要区分 Fuchsia 平台与常规 Bazel 标识符时使用的一种模式,请参阅封装内置规则和常用规则、宏和 函数。

使用 Fuchsia 专用封装容器

如果存在 Fuchsia 专用封装容器,请使用这些封装容器,而不是外部代码库、宏等。这有助于确保 Fuchsia build 配置得到一致应用。

具体而言,以下语言有封装容器:

  • C/C++:使用 //build/bazel/rules/cc/... 中的 fx_cc_...(),而不是 @rules_cc// 中的 cc_...。

  • Rust:使用 //build/bazel/rules/rust/... 中的 rustc_...(),而不是 @rules_rust// 中的 rust_...。

Fuchsia 没有以下语言的封装容器。请从以下路径加载,以保持一致性:

  • Go:@io_bazel_rules_go//go...

  • Python:@rules_python//python...

字符串

对字符串使用双引号,但为了避免转义而使用单引号的情况除外

默认情况下,对字符串使用双引号。 但是,如果 输出双引号更合适,并且这样做需要 转义双引号 (\"),请使用单引号 以避免转义。