简介:面向 Windows 平台 C++ 开发者提供的 gRPC 静态库预编译资源,适合需要在本机快速集成 RPC 框架、又不想耗费大量时间自行编译的工程师,尤其适用于 32 位与 64 位、Debug 与 Release 多套构建配置并存的工程场景。压缩包共 4181 个文件,约 359.89MB,以 2712 个头文件、345 个 lib 静态库、584 个 pc 配置文件及 88 个 cmake 脚本为主,另含 proto 定义、inc 头文件与少量 dll、pem 证书文件,覆盖编译产物、依赖描述与工程集成所需的关键组成。已有 1051 人学习下载,说明该预编译方案在社区中具备一定认可度。资源同时提供 32 位与 64 位的 Debug、Release 四套版本,可省去从源码拉取依赖、配置工具链与反复排错的过程,直接用于项目链接与调试;配合作者记录的编译过程说明,读者还能理解各产物的来源与目录组织,便于后续按需裁剪或替换版本。
1. 从一次链接翻车说起:Windows 上 gRPC C++ 静态库到底装什么
第一次在 Windows 上给一个 C++ 服务接 gRPC,我按 Linux 的习惯直接vcpkg install grpc,编译一路绿灯,结果交付到一台没装运行库的机器上,exe 双击就弹窗缺 DLL。那次翻车让我记住一件事:Windows 上谈 gRPC C++,动态库和静态库是两条完全不同的路,选错了后面全是补丁。这篇笔记记录的是静态库这条路的完整落地过程——从工具链版本、依赖来源,到 CMake 参数、链接顺序,再到装坏之后怎么回滚。适合两类人:一是要在 Windows 上做单文件分发、不想带一堆 DLL 的 C++ 开发者;二是已经装过 gRPC 但被 abseil、protobuf 版本打架折腾过的熟手。下面所有版本和参数都按我实际跑通的一套来写,你照着走能少踩几个坑。
2. 装之前先把环境钉死:工具链与依赖版本对照
Windows 上 gRPC C++ 静态库装不起来,八成不是 gRPC 本身的问题,而是工具链和依赖版本没对齐。gRPC 的 C++ 实现依赖 abseil、protobuf、re2、c-ares、zlib、openssl 这一串库,任何一个版本错位,报错都会指向一个看起来毫不相关的地方。所以第一步不是敲安装命令,而是把版本表列清楚。
2.1 我实际跑通的版本组合
下面这套是我在一台 Windows 10 21H2、VS2022 的机器上验证过的组合,静态库能编、能链、能跑通一个 hello 服务。版本不必完全照抄,但同一行里的搭配建议整体保持一致,尤其是 gRPC 和 protobuf、abseil 三者之间。
| 组件 | 版本 | 说明 |
|---|---|---|
| Visual Studio | 2022 17.8 | 用 MSVC v143 工具集,C++17 起步 |
| CMake | 3.27.x | 3.20 以上即可,低于 3.16 会有策略报错 |
| Git | 2.4x | 拉源码和子模块用 |
| gRPC | 1.60.x | 静态库编译的主版本 |
| protobuf | 3.21.x 或 4.25.x | 必须与 gRPC 的 third_party 对齐 |
| abseil | 随 gRPC 子模块 | 不要单独装另一个版本 |
| OpenSSL | 3.0.x | 需要静态库版本,不是安装包默认的动态库 |
| zlib | 1.3.x | 静态编译 |
这里最容易出问题的是 protobuf。gRPC 源码树里third_party/protobuf是一个子模块,指向它自己验证过的版本。如果你系统里另外装了一个 protoc,PATH 里先命中的可能是那个,于是编译期头文件和运行期库版本对不上,链接时报一堆undefined symbol。我一般会先把系统里的 protoc 从 PATH 里摘掉,只让 CMake 用源码树里的那份。
2.2 依赖从哪来:子模块还是包管理器
两条路:一是用git clone --recurse-submodules把 gRPC 和它的全部第三方依赖一起拉下来,二是用 vcpkg 或 Conan 这类包管理器装。静态库场景我更倾向第一条,原因是子模块的版本是 gRPC 官方验证过的组合,包管理器里的版本更新节奏和 gRPC 不一定同步,静态链接时符号冲突的概率更高。
拉源码的命令如下,注意--recurse-submodules不能省,否则 third_party 目录是空的,CMake 配置阶段就会报找不到 abseil。
git clone --recurse-submodules -b v1.60.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc cd grpc git submodule update --init --recursive-b v1.60.0锁定 tag,避免拉到主干上正在改的代码;--depth 1和--shallow-submodules只拉最新一层提交,能省不少时间和磁盘。如果你后面要切版本,浅克隆会麻烦一点,那就去掉这两个参数。拉完之后进third_party看一眼,abseil-cpp、protobuf、re2、c-ares、zlib 都应该有内容,空目录说明子模块没拉全,先解决这个再往下走。
2.3 OpenSSL 静态库单独准备
gRPC 的 TLS 部分依赖 OpenSSL,而 Windows 上默认装出来的 OpenSSL 往往是动态库。静态链接需要.lib形式的静态库,我一般用源码自己编一份,或者用已经编好的静态版本。编的时候注意两点:一是平台选 x64,二是运行库要和后面 gRPC 的编译选项一致(都用/MT或都用/MD,静态库分发场景通常选/MT)。这一步不做好,后面 CMake 配置能过,链接阶段会报LNK2001找不到SSL_CTX_new之类的符号。
3. 用 CMake 编静态库:参数怎么给、坑在哪
环境钉死之后,真正编译这一步反而没那么玄学,关键是 CMake 的几个开关要给对。gRPC 的 CMake 脚本对静态库的支持是完整的,但它默认会编动态库,也会编测试和示例,这些都要显式关掉,否则编译时间翻几倍,产物里还混进不需要的东西。
3.1 配置阶段的完整命令
我用的是一套 out-of-source 构建,源码目录和构建目录分开,方便装坏了直接删构建目录重来。命令如下:
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 ^ -DCMAKE_BUILD_TYPE=Release ^ -DCMAKE_INSTALL_PREFIX="D:/libs/grpc-static" ^ -DgRPC_BUILD_TESTS=OFF ^ -DgRPC_BUILD_CSHARP_EXT=OFF ^ -DgRPC_BUILD_GRPC_CSHARP_PLUGIN=OFF ^ -DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF ^ -DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF ^ -DgRPC_BUILD_GRPC_PHP_PLUGIN=OFF ^ -DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF ^ -DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF ^ -DgRPC_SSL_PROVIDER=package ^ -DOPENSSL_ROOT_DIR="D:/libs/openssl-static" ^ -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded"逐项说清楚。-G "Visual Studio 17 2022" -A x64指定生成器和平台,Windows 上必须显式给-A x64,否则默认可能是 Win32,编出来的库和你的 x64 工程对不上。CMAKE_INSTALL_PREFIX是安装目录,后面工程里find_package就指这里。一串gRPC_BUILD_*_PLUGIN=OFF是关掉其他语言的代码生成插件,纯 C++ 项目用不到,关掉能省一大截编译时间。gRPC_SSL_PROVIDER=package表示 OpenSSL 用外部提供的,配合OPENSSL_ROOT_DIR指到你编好的静态库目录。最后CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded"对应/MT,这是静态库分发的关键——如果你的主工程用/MD,这里就要改成MultiThreadedDLL,两边必须一致,否则链接期报运行库冲突。
提示:
CMAKE_MSVC_RUNTIME_LIBRARY这个变量要求 CMake 3.15 以上,且策略 CMP0091 为 NEW。老版本 CMake 不认这个变量,会静默忽略,结果运行库还是默认值,后面链接报错很难查。
3.2 编译与安装
配置通过后执行编译和安装:
cmake --build build --config Release --target install -j 8--config Release对多配置生成器(VS)是必须的,单配置生成器(Ninja)则看CMAKE_BUILD_TYPE。--target install一步到位,编完直接装到前面指定的前缀目录。-j 8按机器核数调,gRPC 全量编译在 8 核机器上大概二三十分钟,核少就耐心等,别中途 Ctrl+C,半截产物会让下次增量编译状态混乱。
装完之后去D:/libs/grpc-static下看,应该有bin、include、lib、cmake几个目录。lib里是一堆.lib,包括grpc.lib、grpc++.lib、gpr.lib、address_sorting.lib、upb.lib以及 abseil、protobuf 的静态库。cmake目录里是gRPCConfig.cmake这类配置文件,主工程靠它来find_package。
3.3 主工程怎么接进来
主工程的CMakeLists.txt里这样写:
cmake_minimum_required(VERSION 3.20) project(my_grpc_client CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") find_package(gRPC CONFIG REQUIRED) find_package(Protobuf CONFIG REQUIRED) add_executable(my_grpc_client main.cpp) target_link_libraries(my_grpc_client PRIVATE gRPC::grpc++ gRPC::grpc++_reflection protobuf::libprotobuf )find_package(gRPC CONFIG REQUIRED)会去CMAKE_PREFIX_PATH里找前面装的gRPCConfig.cmake,所以配置主工程时要带上-DCMAKE_PREFIX_PATH="D:/libs/grpc-static"。链接目标用gRPC::grpc++这种带命名空间的写法,CMake 会自动把传递依赖(abseil、c-ares 等)一起带上,比手动列一长串.lib靠谱得多。grpc++_reflection是反射服务,调试 grpcurl 之类的工具时会用到,不需要可以去掉。
4. 避坑与排查:静态库链接阶段最常见的五类翻车
静态库这条路,编译阶段通常顺,问题集中在链接和运行阶段。下面五条是我自己踩过、也帮别人排查过的,按「现象 → 原因 → 解决」记下来。
4.1 LNK2005 重复符号
现象:链接时报大量LNK2005: xxx already defined,符号集中在 abseil 或 protobuf 里。原因:工程里同时链了两份 abseil——一份来自 gRPC 的静态库,一份来自你另外装的包管理器版本。解决:统一依赖来源,把系统里或 vcpkg 里的 abseil、protobuf 从链接列表里去掉,只保留 gRPC 安装目录下的那份;检查CMAKE_PREFIX_PATH是否混进了别的安装前缀。
4.2 LNK2019 找不到 OpenSSL 符号
现象:LNK2019: unresolved external symbol SSL_CTX_new。原因:OPENSSL_ROOT_DIR指向的是动态库版本,或者静态库的.lib没被正确带进来。解决:确认该目录下lib里是静态.lib,且gRPC_SSL_PROVIDER=package生效;必要时在target_link_libraries里显式补上libssl、libcrypto的静态库路径。
4.3 运行库不匹配
现象:LNK2038: mismatch detected for 'RuntimeLibrary'。原因:gRPC 静态库用/MT编的,主工程用/MD,或者反过来。解决:两边统一。静态分发选/MT,主工程CMAKE_MSVC_RUNTIME_LIBRARY设成MultiThreaded;如果主工程必须/MD,就重新编一份/MD的 gRPC。
4.4 protoc 版本错位
现象:生成的.pb.cc编译报错,提示 protobuf 头文件版本和库版本不一致。原因:PATH 里先命中的是系统装的 protoc,和源码树里的 protobuf 版本不同。解决:把系统 protoc 从 PATH 摘掉,用 gRPC 安装目录bin下的 protoc;生成代码时显式指定--plugin=protoc-gen-grpc=指向同一目录的插件。
4.5 装坏了怎么回滚
现象:改了几次 CMake 参数后构建目录状态混乱,报错越来越离谱。原因:增量编译残留了旧配置的中间产物。解决:直接删掉build目录和安装前缀目录,从配置命令重新来一遍。我一般会在构建目录外留一份配置命令的脚本,回滚就是删目录加重跑脚本,比在 CMakeCache 里逐项改快得多。
5. 装完怎么验证:一个最小服务跑通才算数
库编出来、工程链上了,不等于装好了。静态库最容易在运行期暴露问题——比如某个依赖没被真正静态链进去,或者运行库混用导致启动即崩。我的验证习惯是写一个最小的 hello 服务,服务端和客户端都静态链接,然后在一台没装任何开发环境的机器上跑一遍。
先写 proto:
syntax = "proto3"; package demo; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; }用安装目录下的 protoc 生成代码:
D:/libs/grpc-static/bin/protoc.exe ^ --grpc_out=. --cpp_out=. ^ --plugin=protoc-gen-grpc=D:/libs/grpc-static/bin/grpc_cpp_plugin.exe ^ demo.proto生成demo.pb.cc、demo.pb.h、demo.grpc.pb.cc、demo.grpc.pb.h四个文件。服务端实现SayHello返回一句拼接字符串,客户端连localhost:50051调一次,打印返回值。两个可执行文件都用前面那套CMakeLists.txt链接,编译出来之后做三件事:
第一,用dumpbin /dependents my_grpc_client.exe看依赖列表,除了系统 DLL(kernel32、ws2_32 这类),不应该出现grpc.dll、protobuf.dll、libcrypto-3-x64.dll。出现了就说明静态链接没生效,回去查运行库和链接目标。
第二,把 exe 单独拷到一台没装 VS、没装 OpenSSL 的干净机器上,双击运行客户端,能连上服务端并打印结果,才算真静态。
第三,故意把服务端关掉再跑客户端,确认报的是连接失败而不是缺 DLL 崩溃,这能区分「链接问题」和「逻辑问题」。
注意:
dumpbin在 VS 开发者命令提示符里才有,普通 cmd 里要先调vcvars64.bat。这一步别偷懒,我见过太多次「本机跑得好好的,换机器就崩」,最后都是依赖没查。
从那以后我每次编完 gRPC 静态库,都强制走一遍dumpbin加干净机器运行这两步,不看到依赖列表干净就不算完。希望这套流程能帮到你,少在链接报错里绕圈。
本文还有配套的精品资源,点击获取