gRPC C++ 源码构建完全指南:bazel 与 CMake 双路线、依赖管理与交叉编译实操
【免费下载链接】grpcC++ based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)项目地址: https://gitcode.com/GitHub_Trending/gr/grpc
本篇技术指南基于 gRPC 仓库根目录的 BUILDING.md 展开,面向 gRPC C++ 贡献者与高级用户,系统讲解从源码构建 gRPC 的完整流程:各平台前置依赖安装、仓库克隆、bazel 与 CMake 两套构建系统的实操命令、gRPC_<dep>_PROVIDER依赖提供模式、安装与交叉编译、以及protoc编译器注意事项。读完本文,你可以独立完成 Linux/macOS/Windows 上的 gRPC 源码构建、可执行文件与库的安装部署,以及面向 ARM 等目标架构的交叉编译。
一、文档定位:谁需要"从源码构建"gRPC
BUILDING.md 开宗明义:该文档只覆盖 gRPC 本身的构建,目标读者是gRPC C++ 的贡献者和/或高级用户(power users)。普通使用者不必走源码构建路线,而应参考 src/cpp/README.md 中"开始使用 gRPC C++"一节的依赖库接入方式——把 gRPC 作为 C++ 应用的依赖有多种途径,且系统级安装(全局安装)往往不是最优选择。
这一区分对实操很重要:如果你只是要写一个 gRPC 客户端/服务端程序,优先评估包管理器或 CMakeFetchContent/子模块方式引入;只有当你需要构建 gRPC 自身、跑它的测试套件、产出分发包(make install)或做交叉编译时,本文的流程才是必要的。
二、各平台前置依赖(Pre-requisites)
Linux
基础构建工具链:
$ [sudo] apt-get install build-essential autoconf libtool pkg-config若计划使用 CMake 构建,额外安装:
$ [sudo] apt-get install cmake如果你是贡献者,且计划构建并运行测试,还需安装(clang 与 LLVM C++ 库仅 sanitizer 构建需要):
$ [sudo] apt-get install clang libc++-devmacOS
先在终端安装 Xcode 或 Command Line Tools for Xcode:
$ [sudo] xcode-select --install再通过 Homebrew 安装构建所需包:
$ brew install autoconf automake libtool shtoolCMake 按其官方下载渠道自行安装即可。
macOS 实用技巧:构建时建议显式设置LIBTOOL与LIBTOOLIZE环境变量,确保make使用 brew 安装的版本而非系统旧版本:
$ LIBTOOL=glibtool LIBTOOLIZE=glibtoolize makeWindows(面向 CMake + MSVC 构建)
按 BUILDING.md 的要求准备以下组件:
- 安装Visual Studio 2022 或更高版本(实际使用的是其中的 Visual C++ 编译器);
- 安装 Git;
- 安装 CMake;
- 安装nasm并加入
PATH(choco install nasm)——boringssl 编译所需,属必装项; - (可选)安装 Ninja(
choco install ninja),用于加速构建。
三、克隆仓库(含子模块)
构建前必须克隆 gRPC 仓库并下载其依赖子模块。gRPC 的部分第三方依赖源码放在 git submodule 中,third_party/下可见abseil-cpp、protobuf、boringssl-with-bazel、googletest等目录,依赖源码由git submodule命令或--recursive标志拉取。以最新稳定 release tag 为例:
Unix / Windows 命令相同:
$ git clone -b RELEASE_TAG_HERE https://gitcode.com/GitHub_Trending/gr/grpc $ cd grpc $ git submodule update --init注意:
RELEASE_TAG_HERE需替换为实际要构建的 release tag 名称。
关于 bazel 的例外:bazel 构建体系采用完全不同的依赖模型(依赖在构建时声明并拉取),只有当使用 bazel 以外的构建系统(如 cmake)时才需要关心子模块下载。这一点从仓库中同时存在 WORKSPACE 与 MODULE.bazel 两个 bazel 依赖声明文件可以得到印证:当前仓库版本号为 1.84.0-dev(见 MODULE.bazel 中version = "1.84.0-dev"),并固定使用 bazel 8.7.0(见 .bazelversion)。
四、构建路线一:bazel(官方推荐)
4.1 为什么推荐 bazel
BUILDING.md 的结论明确:C++ 世界不存在能覆盖所有平台与用例的"标准"构建系统,gRPC 因此支持多种构建系统,而bazel 是 gRPC C++ 的主构建系统(primary build system)。文档原话:熟悉 bazel 的话"我们完全可以推荐它"——使用 bazel 能获得最好的开发者体验,同时构建更快、更干净,并支持 Linux、macOS 与 Windows 三平台。
4.2 版本要求与 bzlmod 注意事项
- 构建 gRPC 需要bazel 1.0.0 或更高版本。当前仓库通过 .bazelversion 固定为8.7.0;
- bzlmod 兼容性问题:如果你使用 Bazel 7 或更新版本构建 gRPC,需要关闭 bzlmod,因为(按文档表述)gRPC 尚未完全兼容 bzlmod。做法是给 Bazel 命令加
--enable_bzlmod=false。
4.3 构建与测试
在仓库根目录执行:
# 构建 gRPC C++ $ bazel build :all# 运行全部 C/C++ 测试 $ bazel test --config=dbg //test/...4.4 维护者进阶:远程执行(Remote Execution)
BUILDING.md 指出:gRPC 维护者若可访问官方测试集群,应使用 gRPC 的 Remote Execution 环境来获得构建/测试速度的显著提升及其他实用特性。该环境的完整用法在 tools/remote_build/README.md 中,核心命令形如:
# 在 Linux 上远程执行 opt 构建测试 bazel --bazelrc=tools/remote_build/linux.bazelrc test --config=opt //test/... # sanitizer 运行(asan / msan / tsan / ubsan) bazel --bazelrc=tools/remote_build/linux.bazelrc test --config=asan //test/... # Windows 远程执行(必须从 Windows 机器运行) bazel --bazelrc=tools/remote_build/windows.bazelrc test --config=windows_opt //test/...需要留意的是:该远程集群仅限 gRPC 团队成员使用(需要集群访问权限);非团队成员只能依赖本地构建与官方 CI(Kokoro)跑的测试。另外该文档特别强调:执行 bazel 命令的操作系统必须与目标构建/执行平台一致,否则可能出现"配置像 Mac、实际跑在 Linux"这类无意义的结果。
五、构建路线二:CMake
前提:已用--recursive克隆仓库或完成子模块更新。以下各小节均需在 grpc 仓库目录下操作。
5.1 Linux/Unix:Make 生成器
$ mkdir -p cmake/build $ cd cmake/build $ cmake -DCMAKE_CXX_STANDARD=17 ../.. $ make如需构建共享库(.so),给cmake追加-DBUILD_SHARED_LIBS=ON。
当前仓库的 CMakeLists.txt 要求CMake 最低版本 3.22(cmake_minimum_required(VERSION 3.22)),并在 APPLE 平台未显式指定CMAKE_CXX_STANDARD时自动回退为 C++17(见 CMakeLists.txt)。
5.2 Windows:Visual Studio 2022 生成器
使用 "Visual Studio" 生成器时,CMake 会生成一个解决方案(grpc.sln),其中为 CMakeLists.txt 中定义的每个 target 各生成一个 VS 工程(另加若干 CMake 自动添加的便捷工程)。用 Visual Studio 打开后即可浏览并构建代码:
@rem 在 grpc 目录、完成递归克隆或子模块更新后执行 md .build cd .build cmake -G "Visual Studio 17 2022" -DCMAKE_CXX_STANDARD=17 .. cmake --build . --config Release5.3 Windows:Ninja(构建更快)
注意:即便使用 Ninja,仍需安装 Visual C++(Visual Studio 的一部分)来编译 C/C++ 源码:
@rem 在 grpc 目录、完成递归克隆或子模块更新后执行 cd cmake md build cd build call "%VS170COMNTOOLS%..\..\VC\Auxiliary\Build\vcvarsall.bat" x64 cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 ..\.. cmake --build .VS 与 Ninja 两种方式下,若要将 gRPC C++ 作为 DLL 使用,可用-DBUILD_SHARED_LIBS=ON开启,但见下文 5.6 节的警告。
5.4 统一的 C++ 标准(C++17)
BUILDING.md 专门用一节强调这一点:为避免构建 gRPC 及其依赖时出现构建错误(尤其是 gRPC C++ 1.70 起),所有 CMake 构建必须使用同一 C++ 标准(至少 C++17)。原因是 gRPC C++ 1.70 起要求至少 C++17,而依赖库 Abseil 会按 C++ 版本提供不同 API——例如absl::string_view在 C++17 前后的实现不同。C++ 版本不一致会导致类型不兼容等连锁问题。
这一点在源码中得到印证:当前 CMakeLists.txt 对核心库 target 均显式声明了 C++17 编译特征,如target_compile_features(gpr PUBLIC cxx_std_17)、target_compile_features(grpc PUBLIC cxx_std_17)等(分别见 CMakeLists.txt、CMakeLists.txt)。因此你的工程(以及通过 CMake 引入 gRPC 的下游工程)都应统一指定-DCMAKE_CXX_STANDARD=17。
5.5 依赖管理:gRPC_<dep>_PROVIDER双模式
gRPC 的 CMake 构建系统对第三方依赖提供两种处理方式:
module:连同 gRPC 一起构建依赖,源码取自 gRPC 的 git 子模块(third_party/下);package:使用系统上已安装的依赖(来自系统包管理器,或你之前用 CMake +CMAKE_INSTALL_PREFIX预装的包)。
该行为由gRPC_<depname>_PROVIDER系列 CMake 变量控制。以 c-ares 为例:gRPC_CARES_PROVIDER=module时 CMake 会先构建 c-ares 再构建 gRPC;gRPC_CARES_PROVIDER=package时 CMake 则在系统中查找已安装的 c-ares 并使用它。
从 CMakeLists.txt 可以看到当前仓库中全部受管依赖及其默认值均为module:
| 变量 | 依赖 | 默认值 |
|---|---|---|
gRPC_ZLIB_PROVIDER | zlib | module |
gRPC_CARES_PROVIDER | c-ares | module |
gRPC_RE2_PROVIDER | re2 | module |
gRPC_SSL_PROVIDER | ssl(boringssl/openssl) | module |
gRPC_PROTOBUF_PROVIDER | protobuf | module |
gRPC_BENCHMARK_PROVIDER | benchmark | module(仅gRPC_BUILD_TESTS=ON时有效,否则为 none) |
gRPC_ABSL_PROVIDER | abseil | module |
此外还有几个常用选项(见 CMakeLists.txt):
gRPC_BUILD_TESTS(默认 OFF):是否构建测试;gRPC_BUILD_CODEGEN(默认 ON):是否构建代码生成工具;gRPC_DOWNLOAD_ARCHIVES(默认 ON):当第三方目录为空时自动下载源码压缩包——这解释了为何当前仓库中部分third_party/子目录是空的:CMake 构建时会按需补齐。
package模式的配套查找脚本位于 cmake/modules/(如 cmake/modules/Findc-ares.cmake、cmake/modules/Findre2.cmake)。
5.6 Windows DLL 构建须知
gRPC C++ 的 Windows DLL 构建仅"尽力支持"(best effort)。BUILDING.md 明确不推荐把 gRPC C++ 当作 DLL 使用,原因是 C++ DLL 在 Windows 上的固有限制,例如:
- C++ 没有稳定 ABI;
- 不能在一个 DLL 中分配内存、在另一个 DLL 中释放等。
尽管不推荐,构建本身并不被禁止(CMake 加-DBUILD_SHARED_LIBS=ON即可),但使用方需自担风险:文档特别提醒存在重要缺陷、某些功能可能完全不可用或以"有趣的方式"损坏,且官方没有为 DLL 构建做大规模测试(为避免维护成本与测试时长增加),因此可能出现回归/构建损坏。
5.7 构建后安装(Install)
用 CMake 安装 gRPC 只需两步:设置-DgRPC_INSTALL=ON,然后构建installtarget。安装位置由 CMake 标准变量CMAKE_INSTALL_PREFIX控制。当前仓库中gRPC_INSTALL在顶层构建时默认为 ON,作为子模块构建时默认 OFF(见 CMakeLists.txt)。
按 CMake 版本区分两种做法:
CMake 3.13+:依赖可保持 "module" 模式,与 gRPC 一起单步构建并安装。仓库提供的可执行参考脚本是 test/distrib/cpp/run_distrib_test_cmake_module_install.sh,其核心步骤即:
mkdir -p "cmake/build" cd "cmake/build" cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_STANDARD=17 \ -DgRPC_INSTALL=ON \ -DgRPC_BUILD_TESTS=OFF \ -DgRPC_SSL_PROVIDER=package \ ../.. make -j4 install脚本随后会构建examples/cpp/helloworld来验证安装产物可用。
gRPC < 1.27 或 CMake < 3.13:依赖必须选 "package" 模式,即系统上需先有这些库的外部副本。参考脚本 test/distrib/cpp/run_distrib_test_cmake.sh 演示了"先用 CMake 安装依赖、再安装 gRPC 本体"的完整流程;BUILDING.md 中给出的等价命令为:
# 注意:gRPC 的全部依赖必须已安装 $ cmake ../.. -DgRPC_INSTALL=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_STANDARD=17 \ -DgRPC_ABSL_PROVIDER=package \ -DgRPC_CARES_PROVIDER=package \ -DgRPC_PROTOBUF_PROVIDER=package \ -DgRPC_RE2_PROVIDER=package \ -DgRPC_SSL_PROVIDER=package \ -DgRPC_ZLIB_PROVIDER=package $ make $ make install5.8 交叉编译(Cross-compiling)
可用 CMake 为其他架构交叉编译 gRPC,流程要点:
- 先为宿主架构构建
protoc与grpc_cpp_plugin。这两个工具在 gRPC 构建过程中会被调用,因此必须存在可在宿主机原生运行的可执行文件; - 为目标平台安装交叉编译工具链;
- 编写 CMaketoolchain 文件,告诉 CMake 交叉编译器与系统工具的位置;
- 通过
CMAKE_TOOLCHAIN_FILE变量传入:
$ cmake ../.. -DCMAKE_TOOLCHAIN_FILE=path/to/file $ make仓库中的可执行示例是 test/distrib/cpp/run_distrib_test_cmake_aarch64_cross.sh,它以 x86 → aarch64(ARM64 Linux)为例,完整演示了上述流程。该脚本生成的 toolchain 文件内容可作为模板参考:
SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_STAGING_PREFIX /tmp/stage) set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc-10) set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++-10) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)脚本的执行顺序值得注意:第一步先在宿主架构上cmake + make install(把宿主版protoc/grpc_cpp_plugin装进 PATH),第二步带-DCMAKE_TOOLCHAIN_FILE=/tmp/toolchain.cmake构建 ARM 版 gRPC,第三步再为 ARM 构建 helloworld 示例——此时示例构建会找到并复用第一步安装的宿主版代码生成工具。
5.9 关于 SONAME 与 ABI 兼容性
BUILDING.md 对 CMake 构建的共享库 SONAME 给出谨慎承诺:团队会在 ABI 破坏(ABI breach)时尽力提升 SONAME 修订号;SONAME 变化明确指示 ABI 不兼容,但同一 SONAME 版本之间不做任何 ABI 稳定性保证。依赖共享库 ABI 的发行方应据此设计自己的兼容性测试。当前 CMake 构建的库版本信息定义在 CMakeLists.txt(如gRPC_CORE_SOVERSION、gRPC_CPP_SOVERSION)。
六、已弃用路线:UNIX 上的make构建
BUILDING.md 明确标注该路线为deprecated(已弃用):make曾是 gRPC 的默认构建系统,但官方已不再推荐,应改用bazel或cmake;根目录 Makefile 仅面向内部使用,不面向公众。
如仍需使用:
$ make常见故障排查:若在 Linux 上遇到类似aclocal-1.15: command not found的错误(通常发生在安装前置依赖之前就跑过make),可执行:
$ git clean -f -d -x && git submodule foreach --recursive git clean -f -d -x $ [sudo] apt-get install build-essential autoconf libtool pkg-config $ make即先彻底清理工作区与子模块,再补装前置依赖后重新构建。
七、关于protoc的说明
gRPC 默认使用 Protocol Buffers,生成桩(stub)服务端与客户端代码需要protoc编译器。若按上文描述从源码编译 gRPC(递归克隆了仓库),构建系统会自动检测系统中是否已有protoc;若没有,则会尝试从third_party中的 protobuf 源码自动编译一份。因此在"module" 模式下你无需预装protoc,而交叉编译场景下则需要预先准备宿主架构的原生protoc(见 5.8 节)。
八、构建方式速查表
| 场景 | 推荐方式 | 关键命令/参数 |
|---|---|---|
| 贡献者开发、跑全量测试 | bazel | bazel build :all、bazel test --config=dbg //test/... |
| Linux/Unix 常规构建 | CMake + Make | cmake -DCMAKE_CXX_STANDARD=17 ../..+make |
| Windows 浏览式开发 | CMake + VS2022 生成器 | cmake -G "Visual Studio 17 2022" |
| Windows 快速构建 | CMake + Ninja | cmake -GNinja -DCMAKE_BUILD_TYPE=Release |
| 系统级安装 | CMake | -DgRPC_INSTALL=ON+make install |
| 使用系统已有依赖 | CMake | -DgRPC_<DEP>_PROVIDER=package(全部依赖) |
| 共享库 | CMake | -DBUILD_SHARED_LIBS=ON(Windows DLL 需谨慎) |
| 交叉编译 | CMake | 先建宿主版 protoc,再-DCMAKE_TOOLCHAIN_FILE=... |
适用前提小结:本文所有命令以当前仓库(1.84.0-dev 开发线)为准,要求 CMake ≥ 3.22、bazel ≥ 1.0.0(仓库固定 8.7.0)、C++17 工具链;package模式下的依赖版本需与 gRPC 期望的 ABI/特性相匹配,若遇到依赖不匹配,回退到默认的module模式(连同源码一起构建)是最稳妥的选择。
【免费下载链接】grpcC++ based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)项目地址: https://gitcode.com/GitHub_Trending/gr/grpc
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考