简介:这份资源面向在Windows平台使用C++进行微服务与分布式系统开发的工程师,提供基于Visual Studio 2015构建的gRPC预编译开发环境,解决从源码编译gRPC耗时长、依赖配置繁琐的问题。压缩包共884个文件,约71.97MB,以430个h头文件、306个cc源文件、64个proto接口定义文件为主,并包含18个lib静态库、8个dll动态库及26个exe可执行文件,同时提供Debug与Release两套编译产物,兼顾调试与生产需求。包内自带helloworld测试项目,定义Greeter服务与SayHello方法,可直接运行验证服务调用流程,便于快速理解protobuf服务定义、Stub代码生成、HTTP/2多路复用与流式通信等核心机制。目前已有1758人学习下载,适合希望跳过环境搭建、直接上手gRPC C++开发的Windows开发者参考使用。
1. 在 VS2015 上把 gRPC 跑起来:一份能直接复现的 Windows 编译笔记
如果你手头有一个必须用 VS2015 维护的老项目,又恰好要接 gRPC,那你大概率已经体会过那种“官方文档默认你用 CMake + 新版 VS,而现实是你连 C++11 都开不全”的撕裂感。这份资源就是冲着这个场景来的:它把 gRPC C++ 在 Windows + Visual Studio 2015 下的编译、依赖拉取、工程生成和最小可运行示例串成了一条能走通的链路。适合两类人——一类是被老工具链锁死、必须原地把 gRPC 编出来的维护者;另一类是想搞清楚 gRPC 在 Windows 上到底依赖了哪些东西、为什么一编译就报一堆链接错误的学习者。下面按“先讲清楚它是什么、再动手编、最后说坑”的顺序展开,每一步都尽量落到能抄的命令和参数上。
2. gRPC C++ 在 Windows 上的依赖链:为什么 VS2015 是个分水岭
2.1 gRPC 的 C++ 实现到底依赖了什么
很多人第一次编 gRPC 失败,不是因为不会用 CMake,而是没意识到 gRPC C++ 不是一个“纯头文件库”,它底下压着一整条依赖链。核心几块:protobuf 负责消息序列化和.proto代码生成;zlib 负责压缩;boringssl(或 openssl)负责 TLS 和加密;abseil(新版本)负责基础工具库;还有 re2、c-ares 这些做正则和异步 DNS 的。VS2015 这个时间点比较尴尬——它对应的是 MSVC 19.0,对 C++11 的支持是“基本可用但缺斤少两”,对 C++14/17 几乎为零。而 gRPC 不同版本对编译器的最低要求是往上走的,越新的 tag 越依赖高版本 MSVC 和 C++17。所以选版本不是随便挑最新的,而是要先确认“这个 tag 的 CMakeLists 里写的 CMAKE_CXX_STANDARD 是多少”。
常见做法是:先看 gRPC 仓库根目录的CMakeLists.txt,搜CMAKE_CXX_STANDARD,如果写的是 17,那 VS2015 基本没戏;如果某个较早的 tag 还停留在 11 或 14,那才有操作空间。这一步不做,后面全是白费功夫。
2.2 为什么推荐用 vcpkg 而不是手动一个个编依赖
手动编依赖是血泪经验的来源。protobuf 要编、zlib 要编、boringssl 在 Windows 上还要装 Perl 和 NASM 才能生成汇编,少一个环节就是一堆 unresolved external symbol。vcpkg 的价值在于它把这些依赖的编译脚本和补丁都封装好了,你只需要指定 triplet 和版本,它帮你把静态库吐出来。
在 VS2015 场景下,triplet 要用x64-windows或x86-windows,并且要确认 vcpkg 本身的版本不要太新——太新的 vcpkg 默认拉取的依赖版本可能已经要求 C++17。我一般会 checkout 一个相对早期的 vcpkg commit,再配合--triplet x64-windows安装。命令大致如下:
# 拉取 vcpkg(建议固定到一个较早的 commit,避免依赖版本过新) git clone https://github.com/microsoft/vcpkg.git cd vcpkg git checkout <一个较早的commit> # 引导 vcpkg,生成 vcpkg.exe .\bootstrap-vcpkg.bat # 安装 gRPC,指定 64 位 Windows 静态库 triplet .\vcpkg install grpc:x64-windows逻辑说明:bootstrap-vcpkg.bat会在当前目录生成 vcpkg 可执行文件;install grpc:x64-windows会连带把 protobuf、zlib、abseil 等依赖一起编好。参数上,x64-windows表示动态库,x64-windows-static表示静态库,如果你要发布单个 exe,选 static 更省事,但要注意运行库选项(/MT vs /MD)必须和你的工程一致,否则又是一轮链接错误。
2.3 VS2015 下用 CMake 生成解决方案的正确姿势
依赖装好之后,用 CMake 生成 VS2015 的.sln。关键参数是-G指定生成器,VS2015 对应的是Visual Studio 14 2015 Win64。同时要把 vcpkg 的工具链文件传进去,否则 CMake 找不到刚装好的依赖。
# 在 gRPC 源码目录下建一个 build 目录 mkdir build && cd build # 生成 VS2015 解决方案,指定 vcpkg 工具链 cmake .. ^ -G "Visual Studio 14 2015 Win64" ^ -DCMAKE_TOOLCHAIN_FILE=<vcpkg路径>/scripts/buildsystems/vcpkg.cmake ^ -DCMAKE_BUILD_TYPE=Release ^ -DgRPC_BUILD_TESTS=OFF逻辑说明:-G决定生成哪种 IDE 的工程文件,写错生成器名 CMake 会直接报找不到;CMAKE_TOOLCHAIN_FILE是让 CMake 通过 vcpkg 定位依赖的关键,不传这个,find_package(gRPC)就会失败;gRPC_BUILD_TESTS=OFF能省掉大量测试目标的编译时间,第一次跑通流程时建议关掉。生成成功后,build 目录下会出现grpc.sln,用 VS2015 打开,先编ALL_BUILD,再编INSTALL(如果配置了安装规则)。
3. 从 proto 到可执行文件:一个最小 gRPC 服务的完整落地
3.1 写一个能跑通的 .proto 并生成 C++ 代码
先定义一个最简单的服务,一个请求一个响应,别一上来就搞流式,流式在 VS2015 下的编译问题更多。假设文件叫hello.proto:
syntax = "proto3"; package hello; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; }生成 C++ 代码需要protoc.exe和grpc_cpp_plugin.exe,这两个在 vcpkg 安装目录的installed/x64-windows/tools/grpc/下能找到。命令:
# 生成消息类代码 protoc.exe -I. --cpp_out=. hello.proto # 生成 gRPC 服务桩代码 protoc.exe -I. --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin.exe hello.proto逻辑说明:--cpp_out生成hello.pb.cc和hello.pb.h,负责消息的序列化;--grpc_out配合--plugin生成hello.grpc.pb.cc和hello.grpc.pb.h,负责服务端和客户端的方法桩。两个插件缺一不可,只跑第一个的话,服务类根本不存在。参数-I.是 proto 的搜索路径,如果 proto 里 import 了其他文件,这里要写对。
3.2 服务端和客户端的最小实现
服务端继承生成的Greeter::Service,重写SayHello:
#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_ptr<grpc::Server> server(builder.BuildAndStart()); server->Wait(); return 0; }客户端创建 channel 和 stub,发一个请求:
#include <grpcpp/grpcpp.h> #include "hello.grpc.pb.h" int main() { auto channel = grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()); std::unique_ptr<hello::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 << reply.message() << std::endl; } return 0; }逻辑说明:服务端用ServerBuilder注册服务并监听端口,InsecureServerCredentials表示不启用 TLS,本地调试够用;客户端用CreateChannel建连接,NewStub拿到桩对象,调用方式和本地函数一样。参数上,端口号两边必须一致,0.0.0.0表示监听所有网卡,本地测试也可以写127.0.0.1。
3.3 在 VS2015 工程里配置头文件和库路径
生成的代码要编进你自己的工程,需要在 VS2015 的项目属性里配三处:C/C++ → 常规 → 附加包含目录,加上 vcpkg 的installed/x64-windows/include;链接器 → 常规 → 附加库目录,加上installed/x64-windows/lib;链接器 → 输入 → 附加依赖项,加上grpc.lib、grpc++.lib、protobuf.lib、zlib.lib等。如果用的是静态 triplet,还要加上libcrypto.lib、libssl.lib、absl_*.lib这一串。
提示:VS2015 默认的 C++ 标准是 C++14 之前的,如果编译时报
constexpr或auto相关错误,去 C/C++ → 语言 → C++ 语言标准,确认没有强制指定更高标准,同时检查是否误开了/std:c++17。
4. 避坑与排查:VS2015 编 gRPC 最常见的五类翻车
4.1 链接时报一堆 unresolved external symbol
现象:编译通过,链接阶段报LNK2019,符号名里带grpc或protobuf。原因通常是库路径没配对,或者 Debug/Release 混用——vcpkg 装的是 Release 库,工程却切到 Debug 配置。解决:确认项目配置和 vcpkg triplet 一致,Debug 就装x64-windows的 debug 版本(vcpkg 默认同时装 debug 和 release),并在附加依赖项里区分grpcd.lib和grpc.lib。
4.2 protoc 生成代码时报 “protoc-gen-grpc not found”
现象:跑--grpc_out时提示找不到插件。原因:--plugin后面的路径写错,或者grpc_cpp_plugin.exe根本不在那个目录。解决:用绝对路径指定插件,先确认grpc_cpp_plugin.exe存在;Windows 下路径不要带空格,必要时用引号包起来。
4.3 编译 boringssl 时卡在 Perl 或 NASM
现象:vcpkg 安装过程中报 “Perl not found” 或 “NASM not found”。原因:boringssl 在 Windows 上生成汇编需要这两个工具。解决:装一个 Perl(比如 Strawberry Perl)和 NASM,并把它们的可执行文件目录加进系统 PATH,然后重新跑 vcpkg install。这一步没有捷径,缺了就是编不过。
4.4 运行时报 “The procedure entry point ... could not be located”
现象:exe 能编出来,一运行就弹窗说找不到某个 DLL 入口。原因:动态链接时,运行时加载的 DLL 版本和编译时用的头文件/库版本不一致,常见于系统里已经有一份旧版 protobuf 或 grpc 的 DLL。解决:把 vcpkg 生成的 DLL 拷到 exe 同目录,或者改用静态 triplet 重新编,彻底避开 DLL 搜索路径的玄学。
4.5 VS2015 编大工程时内存爆掉
现象:编译grpc.sln到一半,VS 卡死或报 “out of memory”。原因:gRPC 的某些源文件很大,VS2015 的 32 位编译器进程有内存上限。解决:分批编译,先编依赖库再编主库;或者用 64 位的 MSBuild 命令行编译,msbuild grpc.sln /p:Configuration=Release /m,/m开多核但注意别把内存吃满。
5. 进阶:把 gRPC 集成进现有 VS2015 工程的三个实用技巧
第一个技巧是用 CMake 的find_package而不是手动配路径。在你自己工程的CMakeLists.txt里写find_package(gRPC CONFIG REQUIRED),然后target_link_libraries(your_target PRIVATE gRPC::grpc++),这样头文件、库、依赖会一次性带进来,比在 VS 属性页里一个个填靠谱得多。前提是生成工程时传了 vcpkg 的工具链文件。
第二个技巧是版本锁定。VS2015 能编的 gRPC 版本是有上限的,我一般会在 vcpkg 的ports/grpc/portfile.cmake里把REF固定到一个确认能过的 tag,而不是让它拉 master。这样团队里每个人编出来的东西一致,不会出现“我这儿能编你那儿不能”的情况。
第三个技巧是验证方法。编完之后别急着写业务,先跑官方自带的helloworld示例,服务端和客户端各起一个,看到 “Greeter received: Hello world” 才算链路通了。然后再把你自己的 proto 加进去,一步步替换。下面这张表是我常用的排查顺序:
| 阶段 | 检查项 | 通过标准 |
|---|---|---|
| 依赖安装 | vcpkg install 无报错 | installed 目录下有 grpc、protobuf 的 lib 和 include |
| 代码生成 | protoc 两个插件都跑通 | 生成 .pb.cc/.pb.h 和 .grpc.pb.cc/.grpc.pb.h |
| 工程编译 | 链接无 LNK2019 | exe 或 lib 成功产出 |
| 运行验证 | 服务端客户端能通信 | 客户端打印出预期响应 |
从那以后我每次在新机器上配 VS2015 + gRPC,都强制先跑一遍 helloworld,确认工具链没问题再动业务代码,省得把环境问题和代码问题搅在一起查。希望帮到你。
本文还有配套的精品资源,点击获取