资讯详情

VS2015 编译 gRPC C++ 实战:版本对齐与依赖管理

📅 2026/10/19 2:20:00 | 华诺云谱 👁 阅读
VS2015 编译 gRPC C++ 实战:版本对齐与依赖管理
简介这份资源面向在 Windows 平台使用 C 进行微服务与分布式系统开发的工程师提供基于 Visual Studio 2015 编译的 gRPC 预编译库与示例工程帮助开发者跳过繁琐的源码编译环节快速搭建可运行的 gRPC 开发环境。压缩包共 884 个文件约 71.97MB以 430 个 h 头文件、306 个 cc 源文件、64 个 proto 接口定义文件为主并包含 18 个 lib 静态库、8 个 dll 动态库及 26 个 exe 可执行文件同时提供 sln 解决方案与 vcxproj 工程文件覆盖 Debug 与 Release 两种配置。包内自带 helloworld 测试项目定义 Greeter 服务与 SayHello 方法可直接编译运行便于理解服务定义、Stub 生成、HTTP/2 通信与流式调用等核心机制。目前已有 1758 人学习下载适合希望掌握 gRPC 在 Windows 下 C 工程化落地的开发者参考实践。1. 在 Windows 上把 gRPC C 塞进 VS2015一次版本对齐的硬仗如果你手头有一个必须用 Visual Studio 2015 维护的老项目又想在里面接入 gRPC C 做服务间通信那你大概率已经体会过那种“每一步都像在拆盲盒”的感觉。VS2015 的 MSVC 编译器版本是 1900C11 支持只能算“基本够用”而 gRPC 从某个版本之后就开始要求 C14 甚至更高再加上它依赖的 protobuf、abseil、c-ares、zlib、openssl 这一长串第三方库版本稍微错开一点编译期就是满屏的模板报错。更麻烦的是网上大多数 gRPC 编译教程默认你用的是 VS2019 或 VS2022直接照搬过来CMake 配置阶段就会因为工具集不匹配而翻车。这篇笔记记录的就是我如何在 Windows VS2015 这套“老而弥坚”的组合上把 gRPC C 从零编译出来、配进项目、跑通第一个 Hello World 的完整过程包括版本怎么选、依赖怎么装、CMake 参数怎么给以及编译失败时该往哪个方向排查。2. 环境准备VS2015 下 gRPC 的版本选择与依赖清单2.1 为什么 gRPC 版本不能随便挑gRPC C 的版本和 MSVC 工具集之间存在一条隐形的兼容线。VS2015 对应_MSC_VER 1900它对 C14 的支持是残缺的而 gRPC 从 v1.30 左右开始大量使用 C14 特性比如泛型 lambda、std::make_unique的完整支持到 v1.40 之后更是直接要求 C17。所以如果你在 VS2015 上拉最新版 gRPC基本是自找麻烦。我一般会把 gRPC 版本锁定在v1.28.x 到 v1.33.x这个区间。这个区间的 gRPC 对 C11 的依赖还比较重MSVC 1900 能扛住同时它依赖的 protobuf 版本是 3.11 到 3.13 左右abseil 还没有被强制引入abseil 是从 gRPC v1.35 开始成为硬依赖的那玩意儿在 VS2015 上编译简直是噩梦。具体选哪个小版本取决于你项目里其他库的 protobuf 版本——如果项目里已经有 protobuf 3.11.4那就选 gRPC v1.28.1如果 protobuf 是 3.13.0那就选 gRPC v1.33.2。版本对齐比选“最新”重要得多。2.2 依赖库清单与获取方式在 Windows 上编译 gRPC C你不可能只下载一个 gRPC 源码包就完事。它依赖以下这些库而且每个库的版本也要和 gRPC 版本匹配依赖库作用推荐版本配合 gRPC v1.33.xprotobuf序列化与代码生成3.13.0c-ares异步 DNS 解析1.16.1zlib压缩1.2.11opensslTLS/SSL1.1.1gbenchmark性能测试可选1.5.2googletest单元测试可选1.10.0这些库不需要你手动一个个下载。gRPC 源码包里有一个third_party目录里面以 git submodule 的形式引用了这些依赖。但问题是如果你直接git clone不带--recursive这些子模块是空的带了--recursive拉下来的又是各子模块的最新版版本可能对不上。所以我一般会这样做先克隆 gRPC 主仓库并切换到指定 tag然后手动进入third_party下的每个子目录把它们也切换到 gRPC 该版本所要求的 commit。gRPC 每个 release 的third_party目录下都有一个*.version文件或者.gitmodules里记录了对应的 commit hash照着切就行。2.3 工具链检查CMake、Git、NASM 一个都不能少在开始编译之前先确认你机器上这几样东西都装好了CMake版本至少 3.15我一般用 3.18.6 的 Windows 安装包。注意安装时勾选“Add CMake to the system PATH”。Git用于拉取源码和子模块版本 2.28 以上即可。NASMopenssl 编译时需要下载后把nasm.exe所在目录加入 PATH。Perlopenssl 的构建脚本依赖 Perl推荐用 Strawberry Perl。装完之后在命令行里逐个验证cmake --version git --version nasm -v perl --version如果nasm或perl提示找不到命令说明 PATH 没配好后面编译 openssl 一定会失败。这一步看起来简单但我见过太多人卡在这里编译报错半天才发现是 NASM 没装。3. 编译 gRPC从 CMake 配置到生成 VS2015 解决方案3.1 拉取源码与子模块对齐先找一个空间足够的目录比如D:\dev\grpc-build然后执行git clone --branch v1.33.2 https://github.com/grpc/grpc.git cd grpc git submodule update --init --recursive这里--branch v1.33.2指定了我们要的 gRPC 版本--recursive会把third_party下的子模块一并拉下来。拉完之后进入third_party/protobuf、third_party/cares/cares、third_party/zlib等目录分别 checkout 到 gRPC v1.33.2 所要求的 commit。具体 commit hash 可以看 gRPC 仓库根目录下的.gitmodules文件或者直接看third_party下每个子目录里的README。提示如果你网络环境拉取子模块经常断可以先用git submodule update --init拉主模块再逐个进入子目录手动git clone对应版本最后把目录名改成 gRPC 期望的名字。3.2 CMake 配置参数详解gRPC 的 CMake 配置是整个编译过程中最关键的一步。参数给错了要么编译不过要么编出来的库缺功能。我一般会在 gRPC 源码根目录下新建一个build目录然后在这个目录里执行 CMake 命令mkdir build cd build cmake .. -G Visual Studio 14 2015 Win64 ^ -DCMAKE_BUILD_TYPERelease ^ -DgRPC_BUILD_TESTSOFF ^ -DgRPC_BUILD_CSHARP_EXTOFF ^ -DgRPC_BUILD_GRPC_CSHARP_PLUGINOFF ^ -DgRPC_BUILD_GRPC_NODE_PLUGINOFF ^ -DgRPC_BUILD_GRPC_PHP_PLUGINOFF ^ -DgRPC_BUILD_GRPC_PYTHON_PLUGINOFF ^ -DgRPC_BUILD_GRPC_RUBY_PLUGINOFF ^ -DgRPC_INSTALLON ^ -DCMAKE_INSTALL_PREFIXD:/dev/grpc-install ^ -DgRPC_SSL_PROVIDERpackage ^ -DOPENSSL_ROOT_DIRD:/dev/openssl-install ^ -DgRPC_ZLIB_PROVIDERpackage ^ -DZLIB_ROOTD:/dev/zlib-install ^ -DgRPC_CARES_PROVIDERpackage ^ -DCARES_ROOT_DIRD:/dev/cares-install ^ -DgRPC_PROTOBUF_PROVIDERpackage ^ -DProtobuf_ROOTD:/dev/protobuf-install逐条解释一下这些参数-G Visual Studio 14 2015 Win64指定生成 VS2015 的 64 位解决方案。如果你要 32 位把Win64去掉。-DCMAKE_BUILD_TYPERelease生成 Release 版本。Debug 版本在 VS2015 下编译 gRPC 会非常慢而且体积巨大除非你要调试 gRPC 内部逻辑否则一律用 Release。-DgRPC_BUILD_TESTSOFF关掉测试代码。gRPC 自带的测试用例非常多编译它们会额外花一两个小时而且容易因为 googletest 版本问题报错。-DgRPC_BUILD_GRPC_*_PLUGINOFF关掉其他语言的插件。你只用 C这些插件编出来也没用。-DgRPC_INSTALLON和-DCMAKE_INSTALL_PREFIX指定安装目录后面cmake --install会把头文件、库文件、protoc 插件都放到这个目录下方便项目引用。-DgRPC_SSL_PROVIDERpackage等告诉 gRPC 不要用third_party里的源码编译依赖而是用你已经编译好的库。这样做的前提是你已经提前把 openssl、zlib、c-ares、protobuf 都编译并安装到了指定目录。如果你不想提前编译这些可以把package改成module让 gRPC 自己编译它们但那样编译时间会翻倍而且 openssl 在 VS2015 下用 module 模式编译经常出问题。3.3 提前编译依赖库的实操如果你选择了package模式就需要先把 openssl、zlib、c-ares、protobuf 这四个库编译好。以 protobuf 为例cd D:\dev\protobuf-3.13.0 mkdir build cd build cmake .. -G Visual Studio 14 2015 Win64 ^ -DCMAKE_BUILD_TYPERelease ^ -Dprotobuf_BUILD_TESTSOFF ^ -Dprotobuf_MSVC_STATIC_RUNTIMEOFF ^ -DCMAKE_INSTALL_PREFIXD:/dev/protobuf-install cmake --build . --config Release --target install-Dprotobuf_MSVC_STATIC_RUNTIMEOFF这个参数很关键。它让 protobuf 使用动态运行时库/MD而不是静态运行时/MT。gRPC 默认用的是/MD如果你这里用了/MT链接时会出现运行时库冲突报一堆LNK2038错误。openssl 和 c-ares 的编译也类似注意 openssl 要用VC-WIN64A目标并且指定--prefix和--openssldir。3.4 生成解决方案并编译CMake 配置成功后会在build目录下生成grpc.sln。用 VS2015 打开这个解决方案选择Release x64配置然后编译ALL_BUILD目标。编译过程大概需要 30 到 60 分钟取决于机器性能。编译完成后再编译INSTALL目标把产物安装到D:/dev/grpc-install。如果你不想用 VS 界面也可以在命令行里直接cmake --build . --config Release --target INSTALL编译过程中如果遇到某个项目报错先看错误信息里是哪个源文件、哪个依赖库的问题。常见的错误包括找不到openssl/ssl.hOPENSSL_ROOT_DIR 没设对、cares.h找不到CARES_ROOT_DIR 没设对、protobuf 版本不匹配导致的google::protobuf命名空间报错。4. 避坑与排查VS2015 编译 gRPC 最常见的五类翻车4.1 现象CMake 配置阶段报 “Could NOT find OpenSSL”原因OPENSSL_ROOT_DIR指向的目录里没有include和lib子目录或者 openssl 编译时没有生成libssl.lib和libcrypto.lib。解决确认 openssl 安装目录结构是D:/dev/openssl-install/include/openssl/ssl.h和D:/dev/openssl-install/lib/libssl.lib。如果 lib 目录下只有.dll没有.lib说明编译时没有生成静态导入库需要重新编译 openssl 并确保no-shared没有开启。4.2 现象编译 protobuf 时出现大量std::string相关模板错误原因VS2015 的 STL 对某些 C11 特性支持不完整而 protobuf 3.13 的部分代码用了较新的写法。解决把 protobuf 版本降到 3.11.4 或 3.12.4。如果项目必须用 3.13可以尝试在 CMake 里加上-DCMAKE_CXX_FLAGS/D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING但这只是掩盖警告根本问题还是编译器版本。4.3 现象链接时出现LNK2038: mismatch detected for RuntimeLibrary原因gRPC 和它依赖的库使用了不同的运行时库选项。gRPC 默认用/MD而某个依赖库编译时用了/MT。解决统一所有库的运行时库选项。在编译 protobuf、openssl、c-ares、zlib 时都加上-DCMAKE_CXX_FLAGS_RELEASE/MD或对应的 CMake 选项。protobuf 用-Dprotobuf_MSVC_STATIC_RUNTIMEOFFopenssl 用no-static配置。4.4 现象编译到一半报 “fatal error C1060: compiler is out of heap space”原因VS2015 的 32 位编译器在处理 gRPC 的大型模板文件时内存不足。解决确保你用的是 64 位工具集Visual Studio 14 2015 Win64并且在 VS 的“项目属性 - C/C - 命令行”里加上/Zm200或/Zm500增加编译器内存分配上限。如果还是不行把grpc.sln里的项目分批编译不要一次性ALL_BUILD。4.5 现象生成的grpc_cpp_plugin.exe运行时提示缺少libprotoc.dll原因protobuf 编译时生成了动态库但grpc_cpp_plugin依赖的libprotoc.dll没有放到同一目录或 PATH 里。解决把D:/dev/protobuf-install/bin加入系统 PATH或者把libprotoc.dll复制到grpc_cpp_plugin.exe所在目录。更彻底的做法是编译 protobuf 时用静态库-Dprotobuf_BUILD_SHARED_LIBSOFF这样就不存在 DLL 依赖问题。5. 项目集成与验证让第一个 gRPC 服务在 VS2015 里跑起来5.1 在 VS2015 项目中配置 gRPC 头文件与库路径编译安装完成后D:/dev/grpc-install目录下会有include、lib、bin三个子目录。在你的 VS2015 项目里右键项目 - 属性做以下配置C/C - 常规 - 附加包含目录添加D:/dev/grpc-install/include和D:/dev/protobuf-install/include。链接器 - 常规 - 附加库目录添加D:/dev/grpc-install/lib和D:/dev/protobuf-install/lib。链接器 - 输入 - 附加依赖项添加grpc.lib、grpc.lib、libprotobuf.lib、libprotoc.lib、zlib.lib、libssl.lib、libcrypto.lib、cares.lib、ws2_32.lib。注意ws2_32.lib是 Windows Socket 库gRPC 的网络层依赖它不加会报WSAStartup相关的链接错误。5.2 编写 proto 文件并生成 C 代码新建一个hello.proto文件syntax proto3; package hello; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name 1; } message HelloReply { string message 1; }然后用 gRPC 安装目录下的protoc.exe和grpc_cpp_plugin.exe生成代码D:/dev/grpc-install/bin/protoc.exe ^ --proto_path. ^ --cpp_out. ^ --grpc_out. ^ --pluginprotoc-gen-grpcD:/dev/grpc-install/bin/grpc_cpp_plugin.exe ^ hello.proto执行成功后会生成hello.pb.cc、hello.pb.h、hello.grpc.pb.cc、hello.grpc.pb.h四个文件。把这四个文件加入 VS 项目然后写一个简单的服务端和客户端代码编译链接。5.3 验证服务端与客户端通信服务端核心代码#include grpcpp/grpcpp.h #include hello.grpc.pb.h class GreeterServiceImpl final : public hello::Greeter::Service { grpc::Status SayHello(grpc::ServerContext* context, const hello::HelloRequest* request, hello::HelloReply* reply) override { std::string prefix(Hello ); reply-set_message(prefix request-name()); return grpc::Status::OK; } }; int main() { std::string server_address(0.0.0.0:50051); GreeterServiceImpl service; grpc::ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(service); std::unique_ptrgrpc::Server server(builder.BuildAndStart()); std::cout Server listening on server_address std::endl; server-Wait(); return 0; }客户端核心代码#include grpcpp/grpcpp.h #include hello.grpc.pb.h int main() { auto channel grpc::CreateChannel(localhost:50051, grpc::InsecureChannelCredentials()); std::unique_ptrhello::Greeter::Stub stub hello::Greeter::NewStub(channel); hello::HelloRequest request; request.set_name(VS2015); hello::HelloReply reply; grpc::ClientContext context; grpc::Status status stub-SayHello(context, request, reply); if (status.ok()) { std::cout Server replied: reply.message() std::endl; } else { std::cout RPC failed: status.error_message() std::endl; } return 0; }先运行服务端再运行客户端。如果客户端输出Server replied: Hello VS2015说明整条链路已经打通。如果客户端报14: Connect Failed检查服务端是否真的在监听 50051 端口以及防火墙有没有拦截。5.4 一个容易忽略的验证细节编译链接成功后不要只跑一次就完事。我一般会做三件事来确认环境真的稳了第一把服务端和客户端分别编译成 Debug 和 Release 两个版本确认两种配置下都能跑通第二把客户端里的localhost换成127.0.0.1再跑一次排除 DNS 解析的干扰第三故意把服务端关掉看客户端是否能正确返回Connect Failed而不是直接崩溃。这三步走完基本可以确定 gRPC 在你的 VS2015 环境里已经落地了。从那以后我每次在 VS2015 上配 gRPC都会先把版本对照表和依赖清单写在纸上编译前逐项打勾再也不敢凭感觉拉最新版了。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑