供应商模式

供应商模式是 Bzlmod 的一项功能,可让您创建 外部依赖项的本地副本。这对于离线构建或您想要 控制外部依赖项的来源非常有用。

启用供应商模式

您可以通过指定 --vendor_dir 标志来启用供应商模式。

例如,将其添加到 .bazelrc 文件中:

# Enable vendor mode with vendor directory under <workspace>/vendor_src
common --vendor_dir=vendor_src

供应商目录可以是相对于工作区根目录的相对路径,也可以是 绝对路径。

供应商特定的外部代码库

您可以使用带有 --repo 标志的 vendor 命令来指定要供应商哪个代码库,它接受 规范代码库名称显示的代码库名称

例如,运行:

bazel vendor --vendor_dir=vendor_src --repo=@rules_cc

bazel vendor --vendor_dir=vendor_src --repo=@@rules_cc~

都将使 rules_cc 在 <workspace root>/vendor_src/rules_cc~ 下供应商。

为给定目标供应商外部依赖项

如需供应商构建给定目标模式所需的所有外部依赖项, 您可以运行 bazel vendor <target patterns>

例如

bazel vendor --vendor_dir=vendor_src //src/main:hello-world //src/test/...

将供应商构建 //src/main:hello-world 目标 和 //src/test/... 下的所有目标所需的全部代码库,并使用当前配置。

在后台,它会执行 bazel build --nobuild 命令来分析 目标模式,因此构建标志可以应用于此命令并 影响结果。

离线构建目标

供应商外部依赖项后,您可以通过以下方式离线构建目标

bazel build --vendor_dir=vendor_src //src/main:hello-world //src/test/...

构建应在没有网络访问权限和 代码库缓存的干净构建环境中运行。

因此,您应该能够签入供应商的源代码,并在另一台机器上离线构建相同的 目标。

供应商所有外部依赖项

如需供应商传递外部依赖项图中的所有代码库,您可以 运行:

bazel vendor --vendor_dir=vendor_src

请注意,供应商所有依赖项有一些缺点

  • 提取所有代码库(包括传递引入的代码库)可能非常耗时。
  • 供应商目录可能会变得非常大。
  • 如果某些代码库与当前平台或环境不兼容,则可能无法提取。

因此,请考虑先为特定目标供应商。

使用 VENDOR.bazel 配置供应商模式

您可以使用位于供应商目录下的 VENDOR.bazel 文件来控制如何处理给定的代码库。

有两个可用的指令,两者都接受 规范代码库名称列表作为实参:

  • ignore():完全忽略供应商模式中的代码库。
  • pin():将代码库固定到其当前的供应商来源,就像此代码库有一个 --override_repository 标志一样。运行供应商命令时,Bazel 不会更新此代码库的供应商来源 ,除非它被取消固定。 用户可以手动修改和维护此代码库的供应商来源。

例如

ignore("@@rules_cc~")
pin("@@bazel_skylib~")

使用此配置

  • 这两个代码库都将从后续供应商命令中排除。
  • 代码库 bazel_skylib 将被替换为位于 供应商目录下的来源。
  • 用户可以安全地修改 bazel_skylib 的供应商来源。
  • 如需重新供应商 bazel_skylib,用户必须先停用 pin 语句 。

了解供应商模式的工作原理

Bazel 会提取 $(bazel info output_base)/external 下项目的外部依赖项。供应商外部依赖项意味着将 相关文件和目录移至给定的供应商目录,并使用 供应商的来源进行后续构建。

供应商的内容包括:

  • 代码库目录
  • 代码库标记文件

在构建期间,如果供应商的标记文件是最新的,或者代码库 固定在 VENDOR.bazel 文件中,那么 Bazel 会通过在 $(bazel info output_base)/external 下创建指向供应商来源的符号链接来使用供应商的来源,而不是实际 运行代码库规则。否则,系统会输出警告,并且 Bazel 将 回退到提取最新版本的代码库。

供应商注册表文件

Bazel 必须执行 Bazel 模块解析才能提取外部 依赖项,这可能需要通过互联网访问注册表文件。为了实现离线构建,Bazel 会供应商从网络提取的所有注册表文件,这些文件位于 <vendor_dir>/_registries 目录下。

外部代码库可能包含指向其他文件或 目录的符号链接。为了确保符号链接正常运行,Bazel 使用以下 策略在供应商的来源中重写符号链接:

  • 创建指向 $(bazel info output_base)/external 的符号链接 <vendor_dir>/bazel-external。它会自动被每个 Bazel 命令 刷新。
  • 对于供应商的来源,将最初指向$(bazel info output_base)/external下路径的所有符号链接重写为<vendor_dir>/bazel-external下的相对路径。

例如,如果原始符号链接是

<vendor_dir>/repo_foo~/link  =>  $(bazel info output_base)/external/repo_bar~/file

它将被重写为

<vendor_dir>/repo_foo~/link  =>  ../../bazel-external/repo_bar~/file

其中

<vendor_dir>/bazel-external  =>  $(bazel info output_base)/external  # This might be new if output base is changed

由于 <vendor_dir>/bazel-external 由 Bazel 自动生成,因此 建议将其添加到 .gitignore 或等效项中,以避免签入。

借助此策略,即使供应商的来源被移至其他位置或 bazel 输出基准 发生更改,供应商来源中的符号链接也应能正常运行。