如何用 Bazel vendor 模式获取外部依赖本地副本并离线构建?

发布时间:2026/9/14 20:24:53
如何用 Bazel vendor 模式获取外部依赖本地副本并离线构建? 如何用 Bazel vendor 模式获取外部依赖本地副本并离线构建【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazelBazel 项目默认从网络拉取外部依赖构建机一旦断网或需要控制依赖来源构建就会失败。Bazel 的 vendor 模式可以把外部依赖抓取到工作区内的一个目录形成可入库的本地副本之后构建直接使用这份副本实现离线构建。本文基于 Bazel vendor 模式文档 说明完整的操作路径开启 vendor 模式、把依赖 vendor 到本地、离线构建以及如何用VENDOR.bazel管理已 vendor 的仓库。开启 vendor 模式vendor 模式通过--vendor_dir标志启用该参数指定存放外部依赖本地副本的目录。路径可以是相对于工作区根目录的相对路径也可以是绝对路径。最方便的做法是把它写进.bazelrc让所有命令默认生效# Enable vendor mode with vendor directory under workspace/vendor_src common --vendor_dirvendor_src这样 vendor 目录位于workspace/vendor_src。也可以不在.bazelrc中配置而是在每条命令后手动追加--vendor_dirvendor_src。将目标依赖 vendor 到本地副本文档推荐的做法是先只 vendor 构建特定目标所需的依赖而不是把全部依赖都拉下来。只 vendor 构建目标所需的依赖bazel vendor --vendor_dirvendor_src //src/main:hello-world //src/test/...该命令会 vendor 出构建//src/main:hello-world以及//src/test/...下所有目标在当前配置下所需的全部仓库。底层实际上是执行一次bazel build --nobuild来分析这些 target pattern因此附加在命令上的构建类标志会影响分析结果进而影响最终 vendor 了哪些仓库。只 vendor 指定仓库如果只想把某一个外部仓库 vendor 下来用--repo标志指定仓库名它同时接受 canonical repo name 和 apparent repo name 两种写法bazel vendor --vendor_dirvendor_src --reporules_cc或bazel vendor --vendor_dirvendor_src --reporules_cc两种写法都会把rules_ccvendor 到workspace root/vendor_src/rules_cc下。可选分支vendor 全部依赖bazel vendor --vendor_dirvendor_src这条命令会 vendor 传递依赖图中的所有仓库文档明确列出它的几个缺点拉取所有仓库包括传递引入的可能很耗时vendor 目录会变得非常大某些与当前平台或环境不兼容的仓库可能拉取失败。因此文档建议优先按目标 vendor而不是全量 vendor。离线构建并验证结果依赖 vendor 完成后用同样的--vendor_dir构建即可bazel build --vendor_dirvendor_src //src/main:hello-world //src/test/...验证标准来自文档的两条说明构建应在没有网络访问、也没有 repository cache的干净构建环境中正常工作由于 vendor 出的源码可以 check in 到代码仓库你可以在另一台机器上拉取代码后离线构建同样的目标。换句话说判断 vendor 是否覆盖完整的方式就是在无网络、无缓存的环境下执行上面的构建命令若能成功即说明当前目标所需的依赖都已 vendor 到位。文档还给出一个需要重新 vendor 的边界条件如果你修改了待构建的目标、外部依赖、构建配置或者更换了 Bazel 版本需要重新执行 vendor 命令否则离线构建可能失败。用 VENDOR.bazel 管理已 vendor 的仓库vendor 目录下的VENDOR.bazel文件控制各个仓库在 vendor 模式下的处理方式。文件中有两个指令参数都是 canonical repo name 列表ignore()让 vendor 模式完全忽略某个仓库pin()把仓库固定为其当前已 vendor 的源码效果相当于对该仓库加了一个--override_repository标志。运行 vendor 命令时 Bazel 不会更新被 pin 仓库的源码除非取消 pin你可以手工修改并维护这份已 vendor 的源码。示例配置ignore(rules_cc) pin(bazel_skylib)配置后的行为两个仓库都会从后续的 vendor 命令中排除bazel_skylib会被 override 为 vendor 目录下的源码可以安全地手工修改如果要重新 vendorbazel_skylib必须先移除这条 pin 语句。另外设置了local或configure为 true 的 repository rule 始终会被排除在 vendor 之外无法通过 vendor 模式接管。理解 vendor 模式的内部机制影响排障vendor 的本质是Bazel 平时把外部依赖放在$(bazel info output_base)/external下vendor 模式把相关文件和目录移动到 vendor 目录后续构建直接使用这份副本。被 vendor 的内容包括仓库目录本身和仓库的 marker 文件。构建时的选择逻辑如果 vendored marker 文件是最新的或者仓库在VENDOR.bazel中被 pinBazel 会在$(bazel info output_base)/external下创建指向 vendor 源码的符号链接来使用它而不是重新执行 repository rule否则 Bazel 打印一条 warning 并回退到抓取该仓库的最新版本。如果你在没有 pin 的情况下手工修改了 vendor 源码修改会被使用但一旦 marker 过期并再次 vendor这份源码会被覆盖。两个与离线构建直接相关的细节Registry 文件Bazel 模块解析可能需要访问 registry 文件vendor 时会把从网络拉取的 registry 文件一并 vendor 到vendor_dir/_registries目录这是离线构建能走通模块解析的前提。符号链接Bazel 会自动创建vendor_dir/bazel-external指向$(bazel info output_base)/external并把 vendor 源码中原先指向 output base 下 external 目录的符号链接改写为vendor_dir/bazel-external下的相对路径因此 vendor 源码移动到别处或 output base 变化后符号链接仍可用。bazel-external由 Bazel 自动生成文档建议把它加入.gitignore避免 check in。注意两类边界指向$(bazel info output_base)/external之外的绝对路径符号链接不会被改写仍可能破坏跨机器兼容性Windows 上 vendor 符号链接需要启用--windows_enable_symlinks标志才有效。离线环境下使用 bazel 子命令的补充项一些 Bazel 子命令如bazel mod tidy有隐式的工具依赖这些工具无法从用户构建目标到达因此bazel vendor //...默认不会包含它们。如果计划离线或 hermetic 环境例如配合--vendor_dir和--nofetch中运行bazel mod tidy这类命令需要把bazel_tools//tools:tools_for_bazel_subcommands这个 filegroup 加入 vendor 调用bazel vendor //... bazel_tools//tools:tools_for_bazel_subcommands小结一条最短可行路径是在.bazelrc中加common --vendor_dirvendor_src执行bazel vendor --vendor_dirvendor_src 目标 pattern然后用bazel build --vendor_dirvendor_src 同样的目标在无网络、无 repository cache 的环境中验证构建通过。需要固定或排除某些仓库时用 vendor 目录下的VENDOR.bazel配置pin()/ignore()目标、依赖、构建配置或 Bazel 版本变化后要重新 vendor。更多背景可参考 外部依赖总览 和 vendor 模式文档。【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考