
简介面向 Windows VS2015 的一套 gRpc 1.28 C 预编译库基于 HTTP/2 协议非常适合在 Windows 桌面环境快速搭建 gRpc 服务端与客户端的中高级 C 开发者。它省去手动编译 gRpc 及 protobuf 依赖的环节直接提供可链接的静态库、头文件与 CMake 配置核心依赖 protobuf 3.11 也已一并打包。整个压缩包共 472 个文件其中头文件.h与静态库.lib占绝大多数还包含 14 个 CMake 脚本、12 个 proto 示例文件及少量可执行工具整体约 24.47MB目录拆分清晰include、lib、bin、share、cmake 各司其职bin 与 share 目录还可辅助部署和调试便于把库文件和构建脚本快速集成到 VS2015 工程。目前已有超过 995 人学习下载。这份资源的价值在于开箱即用的编译产物与示例 proto 定义可以帮助开发者理解 protobuf 服务接口的生成流程在项目初始化、接口联调或团队内部依赖统一时显著减少重复编译与工程配置成本。 在Windows上用VS2015编译gRPC的C库这活儿看着不复杂真操作起来全是暗坑。尤其当项目锁定在“gRPC 1.28 Windows VS2015 C编译库”这个组合时很多老教程不是版本对不上就是遇到莫名其妙的链接错误。这篇文章把我实际编译、集成、调通这套环境的过程完整记录下来包含CMake参数、子模块拉取、openssl选型、运行时库一致性、常见报错排查等内容希望能帮到正在给旧项目接入gRPC的C开发者。1. 为什么是gRPC 1.28 VS2015这个组合1.1 版本匹配背后的现实逻辑VS2015对应的MSVC工具集是v140编译器对C14的支持完整度一般对C17更是别指望太多。gRPC新版1.40以上大量使用abseil和更新的C特性在VS2015上编译基本是地狱模式光模板实例化报错就能耗掉半天。而gRPC 1.28这个版本在第三方依赖上相对克制protobuf对应3.11.x依赖的abseil部分也温和CMake构建体系成熟稳定是VS2015环境下一个性价比很高的版本。另一个现实因素是很多存量项目就是VS2015工程因为历史原因不可能整体升级工具集。此时把gRPC作为外部依赖编译成库比拉着全项目升级要稳妥得多。如果你可以自由选择环境那我推荐直接用VS2017以上但如果你被困在VS2015那锁定gRPC 1.28.1是比较明智的做法。1.2 依赖组件清单与编译顺序编译gRPC本身不是单一工程它依赖protobuf、zlib、c-ares、re2、abseil-cpp以及SSL库。理解整体编译顺序后期排错会轻松很多依赖作用备注protobuf序列化与代码生成必须最先可用protoc.exe 是核心工具zlib压缩一般跟随CMake自动编译c-aresDNS解析Windows下建议使用跟随CMakere2正则引擎部分grpc内部功能需要abseil-cpp基础工具库1.28开始大量依赖头文件和静态库都要对上openssl / boringsslTLS加密建议用openssl别用boringsslgrpc本体通信框架最后编译生成grpc.lib等库我见过有人想跳过某些依赖直接编译gRPC结果在链接阶段拼了一晚上absl符号。这玩意儿没有捷径老老实实让CMake统一管理构建更靠谱。2. 源码拉取与编译前的环境准备2.1 拉代码与submodule的完整操作gRPC的源码通过git管理大量子模块拉不全会导致后面CMake配置阶段就报错。建议这么操作git clone --recurse-submodules -b v1.28.1 https://github.com/grpc/grpc.git grpc-1.28.1如果网络不稳定先克隆主仓库再单独拉子模块git clone -b v1.28.1 https://github.com/grpc/grpc.git grpc-1.28.1 cd grpc-1.28.1 git submodule update --init --recursive子模块数量多且体积大一次拉取失败没关系重复执行git submodule update --init --recursive即可git会断点续传。重点确认third_party/protobuf、third_party/abseil-cpp、third_party/zlib、third_party/cares、third_party/re2这些目录里文件完整尤其third_party/protobuf不能是空目录否则后面一定会扑街。2.2 为什么SSL提供者选openssl而不是boringsslgRPC的CMake默认SSL提供者是module方式它指的就是boringssl。boringssl是Google维护的编译它需要Go环境而且在VS2015下编译老版本boringssl还容易出现编译器不兼容的报错这是第一个大头坑。我建议直接指定-DgRPC_SSL_PROVIDERpackage然后准备一份Windows版OpenSSL。去官网下载预编译的Win64 OpenSSL 1.1.1安装或解压到固定目录比如D:/libs/OpenSSL-Win64。这样把openssl作为外部包提供编译gRPC时只需要链接它的lib省掉一整条boringssl编译链路基本从此不再为TLS发愁。记住别自己从源码编openssl除非你特别需要定制openssl功能。预编译包配合MT/MTd运行时一样能正常工作没必要给自己加戏。3. CMake配置与核心编译流程3.1 生成VS2015工程文件的命令写法在gRPC源码目录外建一个build目录我习惯把构建产物和源码分开方便后续清理。推荐用如下CMake命令mkdir build cd build cmake .. -G Visual Studio 14 2015 -A x64 ^ -DCMAKE_INSTALL_PREFIXD:/libs/grpc-install ^ -DgRPC_BUILD_TESTSOFF ^ -DgRPC_BUILD_CSHARP_EXTOFF ^ -DgRPC_INSTALLON ^ -DgRPC_SSL_PROVIDERpackage ^ -DOPENSSL_ROOT_DIRD:/libs/OpenSSL-Win64 ^ -DCMAKE_MSVC_RUNTIME_LIBRARYMultiThreadedDLL注意几个参数-G Visual Studio 14 2015表示VS2015加-A x64生成64位工程。早期CMake可能有Win64后缀的老写法新版本统一用-A。如果不加-A x64默认生成Win32工程和你项目位数不一致会导致后续灾难性的链接错误。-DgRPC_BUILD_TESTSOFF关掉测试否则ALL_BUILD里面全是测试目标编译时间翻倍。-DgRPC_BUILD_CSHARP_EXTOFF关掉C#扩展这玩意儿在Windows上经常拖慢构建。-DCMAKE_MSVC_RUNTIME_LIBRARYMultiThreadedDLL表示统一用/MD运行时库。如果你业务项目用的是/MT这里要改成MultiThreaded。这是最容易踩坑的地方后面专门讲。3.2 只编译核心目标而不是一股脑ALL_BUILD很多人直接cmake --build . --config Release结果编译整个ALL_BUILD耗时极长。实际你只需要几个关键目标cmake --build . --config Release --target grpc cmake --build . --config Release --target grpc_unsecure cmake --build . --config Release --target grpc_cpp_plugin cmake --build . --config Release --target grpc_plugin_support cmake --build . --config Release --target protoc其中grpc是带SSL的完整库grpc_unsecure是不带SSL的明文版。protoc和grpc_cpp_plugin是后面要用来生成C代码的工具必须编译出来。编完之后执行安装cmake --build . --config Release --target install安装后D:/libs/grpc-install下会有include、lib、bin三个目录。头文件都在include里库在lib里protoc.exe和grpc_cpp_plugin.exe在bin里。3.3 实际编译耗时与产物形态在我测试机i5-850016G内存机械硬盘上全量核心目标编译大约40分钟如果是SSD会快不少。编译过程中CMake会自动把protobuf、re2、c-ares、abseil等第三方库一起编掉中间要是某个第三方库编译失败通常是因为前面条件没准备齐优先检查openssl路径和子模块完整性。安装目录里的库文件Release版本一般是grpc.lib、grpc.lib、gpr.lib、libprotobuf.lib这一类。Debug版本会根据CMake配置在文件名后加d后缀所以建议业务项目统一使用Release配置减少链接期的混乱。4. 把gRPC集成到你的业务项目中4.1 VS2015项目属性配置要点新建或者打开你的C项目给工程配置以下属性附加包含目录D:/libs/grpc-install/include附加库目录D:/libs/grpc-install/lib预处理器定义追加NOMINMAX、_WIN32_WINNT0x0601避免Windows头文件和标准库的min/max宏冲突也保证gRPC能识别目标系统版本。附加依赖项至少包含grpc.lib、grpc.lib、gpr.lib、libprotobuf.lib实际使用时要看编译产物以你安装目录lib下实际文件为准。最关键的一点业务项目的“运行库”设置必须和gRPC库一致。如果你编译gRPC用的是/MD业务项目就不能用/MT否则链接阶段会出现LNK2038: mismatch detected for RuntimeLibrary这种错误很常见也很折磨人。我个人的习惯是统一用Release /MDDebug就用/MDd在CMake里通过CMAKE_MSVC_RUNTIME_LIBRARY控制两边不要混。4.2 从proto文件到可用桩代码假设你有一个最简单的helloworld.protosyntax proto3; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply); } message HelloRequest { string name 1; } message HelloReply { string message 1; }用安装目录下bin里的工具生成C代码D:/libs/grpc-install/bin/protoc.exe -I. --cpp_out./gen helloworld.proto D:/libs/grpc-install/bin/protoc.exe -I. --grpc_out./gen --pluginprotoc-gen-grpcD:/libs/grpc-install/bin/grpc_cpp_plugin.exe helloworld.proto生成的文件包括helloworld.pb.h、helloworld.pb.cc、helloworld.grpc.pb.h、helloworld.grpc.pb.cc。把这四个文件加入你的VS2015工程#include helloworld.grpc.pb.h就能写服务端和客户端代码了。如果在生成代码时报找不到插件多半是插件路径写错注意Windows下路径用绝对路径或者正斜杠。4.3 最小服务端与客户端示例服务端写法大概这样#include helloworld.grpc.pb.h #include grpcpp/grpcpp.h class GreeterServiceImpl final : public helloworld::Greeter::Service { grpc::Status SayHello(grpc::ServerContext* context, const helloworld::HelloRequest* request, helloworld::HelloReply* reply) override { reply-set_message(Hello request-name()); return grpc::Status::OK; } }; int main() { GreeterServiceImpl service; grpc::ServerBuilder builder; builder.AddListeningPort(0.0.0.0:50051, grpc::InsecureServerCredentials()); builder.RegisterService(service); std::unique_ptrgrpc::Server server(builder.BuildAndStart()); server-Wait(); }客户端写法大概这样#include helloworld.grpc.pb.h #include grpcpp/grpcpp.h int main() { auto channel grpc::CreateChannel(localhost:50051, grpc::InsecureChannelCredentials()); auto stub helloworld::Greeter::NewStub(channel); helloworld::HelloRequest request; request.set_name(grpc); helloworld::HelloReply reply; grpc::ClientContext context; grpc::Status status stub-SayHello(context, request, reply); if (status.ok()) { // reply.message() 就是 Hello grpc } }这个demo能跑通说明库的链接、头文件、运行时环境全部OK。5. 高频坑位对照表与个人心得症状直接原因解决办法CMake配置时报找不到protobuf头文件子模块缺失反复执行git submodule update --init --recursive编译boringssl报错且无Go环境SSL provider选了module改用-DgRPC_SSL_PROVIDERpackage openssl预编译包protoc.exe运行提示缺少DLL缺少VC运行库安装VS2015对应的Visual C RedistributableLNK2038 RuntimeLibrary不匹配业务项目与gRPC库运行库不一致全部统一 /MD 或全部统一 /MTLNK2019 absl符号无法解析链接遗漏absl库或版本不一致检查三方库链接列表确保lib齐全编译gRPC本体时无故崩溃VS2015没有打Update 3安装VS2015 Update 3补丁我这里再补充一些个人经验。一个是编译完的build目录千万别删。后来你八成会遇到“当初没编grpc_cpp_plugin”“想补一个Debug版库”“要调试某个内部符号”这类需求build目录里的CMake缓存和中间文件能让这些操作快速完成删了就得从头再来。另一个是正确看待gRPC的静态库体积。Release版grpc.lib带依赖一起静态链接后生成的exe动辄几十MB这是正常的不必惊慌。如果你嫌大可以考虑用动态库方式编译gRPCCMake里可配置但要额外分发一堆DLL维护成本更高我一般选静态库图个省心。最后说一句这套gRPC 1.28 VS2015的组合虽然能用但终究是“带着镣铐跳舞”。如果你手里的项目没有强制的工具链约束我会建议尽快升级到VS2017或VS2019用新版本gRPC会省掉这里一半以上的折腾。但真到了必须停留在VS2015的那天上面这套流程踩过的坑和总结的配置项基本上能让你少走一整个星期的弯路。本文还有配套的精品资源点击获取