gRPC Bazel 构建支持详解:WORKSPACE 依赖接入、版本策略与源码实现剖析
2026/9/8 22:20:17 网站建设 项目流程

gRPC Bazel 构建支持详解:WORKSPACE 依赖接入、版本策略与源码实现剖析

【免费下载链接】grpcC++ based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)项目地址: https://gitcode.com/GitHub_Trending/gr/grpc

gRPC 仓库的主构建系统是 Bazel,C++、Python 与 Objective-C 三类构建规则均以 Bazel 定义为源头,CMake 等其他构建系统的规则也是从 Bazel 定义生成的。本文基于 bazel_support.md 的官方说明,结合 bazel/grpc_deps.bzl、bazel/grpc_extra_deps.bzl 与 MODULE.bazel 等仓库源码,讲解如何在自己的 Bazel 工程(WORKSPACE 或 bzlmod)中引入 gRPC 依赖、当前支持的 Bazel 版本策略(8.7.0),以及grpc_deps/grpc_extra_deps两个仓库规则宏在底层究竟加载了哪些外部仓库。

Bazel 是 gRPC 的主构建系统

doc/bazel_support.md 明确给出 gRPC 对构建系统的定位:

  • grpc/grpc仓库的主要构建系统是 Bazel,官方为 C++、Python 和 Objective-C 提供了 Bazel 规则;
  • C++ 虽然同时支持 CMake 等构建系统,但这些规则实际上是从 Bazel 定义生成的
  • 使用 Bazel 构建的项目引入grpc/grpc,目的不仅是把 gRPC 作为库依赖,还可以用 gRPC 提供的规则直接生成 protobuf 代码、stub 与 servicer 代码

这一“Bazel 为源、其余构建系统生成”的架构在仓库中有直接证据:仓库根目录的 build_autogenerated.yaml、build_handwritten.yaml 与 tools/buildgen/ 目录共同承担从 Bazel 规则生成各构建系统(CMake、Makefile、Ruby gemspec、CocoaPods 等)所需清单的职责;根 BUILD 文件中定义了核心目标grpc(C 库,见 BUILD)与grpc++(C++ 库,见 BUILD),它们是下游项目最常依赖的两个标签。

因此对下游 Bazel 工程而言,接入 gRPC 的关键只有两步:引入grpc_depsgrpc_extra_deps两个仓库规则,再调用它们。

在 WORKSPACE 中接入 gRPC:grpc_deps 与 grpc_extra_deps

按照 doc/bazel_support.md 的“Basic Usage”一节,下游项目需要在自己的WORKSPACE文件中调用grpc_depsgrpc_extra_deps仓库规则,官方示例如下(文档中以 v1.45.0 版本归档为示例,实际使用时应按需替换为对应的发布 tag、strip_prefixsha256):

workspace(name = "example_workspace") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "com_github_grpc_grpc", strip_prefix = "grpc-1.45.0", sha256 = "ec19657a677d49af59aa806ec299c070c882986c9fcc022b1c22c2a3caf01bcd", urls = ["https://github.com/grpc/grpc/archive/refs/tags/v1.45.0.tar.gz"], ) load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") grpc_deps() load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") grpc_extra_deps()

三个步骤的含义:

  1. http_archive把 gRPC 自身作为外部仓库@com_github_grpc_grpc拉入工作区(仓库内repo_namecom_github_grpc_grpc,见 MODULE.bazel);
  2. 调用grpc_deps():一次性引入编译与测试 gRPC 所需的全部第三方外部仓库
  3. 调用grpc_extra_deps():引入上述外部仓库自身的传递性依赖(如 protobuf、rules_go 等仓库各自声明的依赖)。

深入源码:grpc_deps() 加载了哪些外部仓库

bazel/grpc_deps.bzl 中grpc_deps()的实现是一个幂等的批量http_archive调用序列——每个仓库都先检查"xxx" not in native.existing_rules(),若消费方工作区已声明同名仓库则跳过,从而允许用户自行覆盖版本。所有urls都优先指向 gRPC 维护的镜像storage.googleapis.com/grpc-bazel-mirror/...,并附原始地址作为回退,这是对构建稳定性与可复现性的关键设计(见 bazel/update_mirror.sh 与 bazel/update_mirror_helper.py 的镜像维护逻辑)。

从 bazel/grpc_deps.bzl 的源码结构看,grpc_deps()主要加载以下类别的仓库:

类别仓库(仓库名)说明
平台与规则集platformsrules_ccrules_shellrules_javarules_protobazel_skylibbazel_featuresBazel 生态基础规则集
加密与压缩boringsslzlib(打add_custom_build_file.patch补丁)、openssl默认 TLS 后端为 BoringSSL;zlib 提供压缩支持
序列化com_google_protobuf(打 protobuf.patch)、grpc_protoprotoc 与 gRPC 服务 proto 定义
网络与解析com_github_cares_cares(c-ares,使用 third_party/cares/cares.BUILD 作为 BUILD)、com_googlesource_code_re2异步 DNS 解析与正则
通用库com_google_absl(abseil-cpp)、com_google_googletest核心依赖与测试框架
可观测性io_opencensus_cppopencensus_protoio_opentelemetry_cppOpenCensus / OpenTelemetry 遥测
xDS 生态com_envoyproxy_protoc_gen_validatecom_github_cncf_xdsdev_cel(cel-spec)、envoy_api构建 C++ xDS proto 所需
语言工具链io_bazel_rules_go(打 rules_go.patch)、bazel_gazellebuild_bazel_rules_apple+build_bazel_apple_support(Objective-C)、com_google_fuzztest(fuzz 测试)、com_github_google_benchmark分别对应 Go 依赖、Apple 平台构建、fuzz 与基准测试
其他com_google_googleapisgoogle_cloud_cppbazel_toolchainsbazel_compdbgoogleapis 导入、RBE 工具链、编译数据库

在函数末尾,grpc_deps()还会依次调用grpc_module_deps()(补充google_cloud_cpp仓库)与 bazel/grpc_python_deps.bzl 中的grpc_python_deps(),后者引入 Python 规则集相关依赖,对应文档中“为 Python 提供 Bazel 规则”的能力。

两个容易踩坑的细节值得注意:

  • OpenSSL 仅支持 bzlmod。bazel/grpc_deps.bzl 中有一段注释:“Building grpc with openssl is only supported when using bzlmod”,因此 WORKSPACE 模式下openssl仓库只是被实现为只含空cc_librarysslcrypto)的 dummy 仓库,保证使用 WORKSPACE 的工程能继续构建;
  • 测试专用依赖grpc_test_only_deps()(bazel/grpc_deps.bzl)额外加载com_google_libprotobuf_mutatoryaml-cpp,仅用于运行 gRPC 自身的测试,源码注释标明其“仅供内部使用,不建议消费方调用”。

深入源码:grpc_extra_deps() 初始化仓库自身的传递依赖

bazel/grpc_extra_deps.bzl 中的grpc_extra_deps(ignore_version_differences = False)负责调用各外部仓库自带的“依赖展开”宏,使其声明的二级依赖就位。从源码调用链看,它依次执行:

  • rules_shell_dependencies()/rules_shell_toolchains():Shell 规则工具链;
  • rules_java_dependencies()protobuf_deps()rules_proto_dependencies()bazel_features_deps():Java / Protobuf / proto 规则链;
  • go_rules_dependencies()+go_register_toolchains(version = "1.22.5")+gazelle_dependencies()(bazel/grpc_extra_deps.bzl):注册 Go 工具链,供 xDS proto 的 Go 代码生成使用;
  • go_third_party():拉取 protoc-gen-validate 的 Go 第三方依赖(源码注释说明其用于构建 C++ xDS protos);
  • apple_rules_dependencies(ignore_version_differences = ...)apple_support_dependencies():Objective-C 构建所需的 Apple 规则依赖,参数ignore_version_differences直接透传给前者,用于容忍 Bazel 版本差异告警;
  • switched_rules_by_language(name = "com_google_googleapis_imports", cc = True, grpc = True, python = True)(bazel/grpc_extra_deps.bzl):只为 C++、gRPC 与 Python 三种语言初始化 googleapis 目标,避免无谓地展开其他语言代码生成;
  • google_cloud_cpp_deps()py_repositories()googletest_deps():补齐其余仓库的依赖。

源码注释也直接给出了 WORKSPACE 用法模板(grpc_deps()grpc_test_only_deps()grpc_extra_deps()的调用顺序),与文档示例一致。

bzlmod:MODULE.bazel 下的模块依赖声明

当前仓库同时提供 bzlmod 支持(Bazel 8 起默认开启的模块化依赖管理),MODULE.bazel 是这一路径的权威声明,也是比 WORKSPACE 方式更推荐使用 gRPC 的方式:

module( name = "grpc", version = "1.84.0-dev", compatibility_level = 1, repo_name = "com_github_grpc_grpc", )

MODULE.bazel 声明模块名为grpcrepo_name保持com_github_grpc_grpc(与 WORKSPACE 时代的仓库名兼容)。其后以bazel_dep精确声明了全部常规依赖及版本,例如:

  • abseil-cpp20250512.1、boringssl0.20260616.0、c-ares1.19.1、protobuf35.1、zlib1.3.1.bcr.5、googletest1.17.0(MODULE.bazel);
  • openssl3.3.1.bcr.1(MODULE.bazel)——印证了“OpenSSL 构建仅在 bzlmod 下支持”的源码注释;
  • 开发依赖dev_dependency = True单独归类:google_benchmarkyaml-cppfuzztestgoogle_cloud_cpplibpfm等(MODULE.bazel);
  • Python 侧通过rules_python注册 3.10 至 3.14 多版本工具链(默认 3.11),并用pip.parse(requirements_lock = "//:requirements.bazel.lock")锁定 pip 依赖(MODULE.bazel)。

MODULE.bazel 中还大量使用archive_override/single_version_override覆盖 BCR 默认配置,例如:用f1f503da这个略新于 1.3.1 的 zlib 提交替换 BCR 版本并打补丁(MODULE.bazel);将 re2 声明为 BCR 版本号但实际使用 2022-04-01 快照以保持与 CMake 构建一致(MODULE.bazel);libpfm 因上游原始链接失效而改指 grpc-bazel-mirror 镜像(MODULE.bazel)。从源码结构看,这些覆盖集中体现了“Bazel 侧版本必须与 CMake 等其他构建系统的锁定版本对齐”的维护策略——这正是文档中“Bazel 是源头”主张的具体落地。

当前支持的 Bazel 版本:8.7.0 与版本策略

doc/bazel_support.md 的“Supported Versions”一节给出 gRPC 的 Bazel 版本支持策略:

  • 支持Bazel 最新稳定版,以及上一代大版本在转入维护模式后至少 6 个月内的版本;
  • 该策略与 Google 基础 C++ 支持策略(Foundational C++ Support Policy)保持一致;
  • 个别发布可能有更宽的兼容范围;当前支持版本列表为8.7.0一项。

仓库中有多处与该结论互相印证的证据:

  1. bazel/supported_versions.txt 的内容仅有一行8.7.0,是 CI 与工具链脚本读取的机器可读清单;
  2. 仓库根的 .bazelversion 文件同样写入8.7.0
  3. tools/bazel 是一个 Bazel wrapper 脚本,利用 Bazel “工作区内//tools/bazel脚本可劫持 bazel 调用”的机制,确保任何人在该仓库中执行bazel时都使用受支持的版本:
    • .bazelversion读取版本号(可用环境变量OVERRIDE_BAZEL_VERSION覆盖),再按平台(Linux x86_64 / aarch64、Darwin x86_64 / arm64、Windows MINGW/MSYS)下载对应二进制(见 tools/bazel);
    • 下载时先尝试grpc-bazel-mirror镜像、失败再回退原始源(tools/bazel);
    • 设置DISABLE_BAZEL_WRAPPER可跳过 wrapper 逻辑直接使用系统 Bazel;OVERRIDE_BAZEL_WRAPPER_DOWNLOAD_DIR可改变二进制下载目录(tools/bazel)。

对下游工程的含义是:如果你的 Bazel 不是 8.7.0,至少应先确认其落在上述策略区间内再尝试构建;仓库内 .bazelrc 仅做了一件事——从旧位置导入 tools/bazel.rc(import %workspace%/tools/bazel.rc),实际构建参数都集中在后者中,排查 Bazel 行为差异时可以直接查看该文件。

用 gRPC 的 Bazel 规则生成 protobuf / stub / servicer 代码

文档指出,引入 gRPC 仓库的另一个重要用途是生成 protobuf、stub 与 servicer 代码。仓库中对应规则的实现位于 bazel/cc_grpc_library.bzl(cc_grpc_library规则,把cc_proto与 gRPC 代码生成组合起来)、bazel/generate_cc.bzl(底层代码生成 action)以及 bazel/grpc_build_system.bzl。在消费方 BUILD 文件中,典型用法是先对服务 proto 应用cc_proto,再用cc_grpc_library生成 stub/servicer 目标,最后链接@com_github_grpc_grpc//:grpc++目标——具体写法可参考仓库内 examples/cpp/ 下各示例的 BUILD 文件与 doc/bazel_support.md 的说明。

小结

回到 doc/bazel_support.md 的核心结论:gRPC 的 Bazel 支持分为“仓库级”与“规则级”两层——仓库级通过grpc_deps()/grpc_extra_deps()(WORKSPACE)或 MODULE.bazel 的模块依赖(bzlmod)引入 gRPC 及其完整依赖树,版本策略锁定在 Bazel 8.7.0(见 bazel/supported_versions.txt 与 .bazelversion);规则级则提供cc_grpc_library等规则,使下游项目能够直接生成 protobuf/stub/servicer 代码。由于 CMake 等其他构建系统的规则都源自 Bazel 定义,理解上述 Bazel 层结构也是理解 gRPC 全部构建路径的基础。

【免费下载链接】grpcC++ based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)项目地址: https://gitcode.com/GitHub_Trending/gr/grpc

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询