Google都搜索不到的gRPC c++从零开始写一个服务端和客户端指南
本文主要讲述了使用bazel编译gRPC C++客户端和服务端的过程,先记录下步骤,最后是吐槽,不喜勿看,技术人员可以直接看01步骤,非技术人员可以直接看02吐槽
01
—
步骤
本文的代码需要使用bazel编译,建议先熟悉下bazel的命令
https://docs.bazel.build/versions/master/bazel-overview.html
如果不想安装bazel和编译环境,可以使用官方提供的容器镜像去编译,本人就是使用这种方式
https://docs.bazel.build/versions/master/bazel-container.html
1. bazel项目的目录如下
grpc-demo-cpp├── demo│ ├── BUILD│ ├── greeter_client.cc│ └── greeter_server.cc├── proto│ ├── BUILD│ └── helloworld.proto└── WORKSPACE
3. 编写WORKSPACE文件
参考:https://github.com/grpc/grpc/tree/master/src/cpp#bazel
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")http_archive(name = "com_github_grpc_grpc",urls = ["https://github.com/grpc/grpc/archive/64c6cfc791241fe4c4ecab41cb36d01cdddb3df4.tar.gz",],strip_prefix = "grpc-64c6cfc791241fe4c4ecab41cb36d01cdddb3df4",)load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")grpc_deps()load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")grpc_extra_deps()
3. 编写proto文件
我偷懒,就直接用gRPC github的example
https://github.com/grpc/grpc/blob/master/examples/protos/helloworld.proto
4. 编写proto文件夹的BUILD文件
参考:https://github.com/grpc/grpc/blob/master/examples/protos/BUILD
package(default_visibility = ["//visibility:public"])load("@rules_proto//proto:defs.bzl", "proto_library")load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library")load("@com_github_grpc_grpc//bazel:grpc_build_system.bzl", "grpc_proto_library")grpc_proto_library(name = "helloworld_proto",srcs = ["helloworld.proto"],)
5. bazel编译proto
参考:https://docs.bazel.build/versions/master/bazel-container.html
docker run \--network host \-e USER="$(id -u)" \-u="$(id -u)" \-v /root/src/grpc-demo-cpp:/src/workspace \-v /tmp/build_output:/tmp/build_output \-w /src/workspace \-e BAZEL_LINKLIBS=-l%:libstdc++.a \l.gcr.io/google/bazel:latest \--output_user_root=/tmp/build_output \build //proto:all
6. 根据生成的头文件可以编写客户端和服务端代码
我偷懒,就直接用gRPC github的example
https://github.com/grpc/grpc/blob/master/examples/cpp/helloworld/greeter_client.cc
https://github.com/grpc/grpc/blob/master/examples/cpp/helloworld/greeter_server.cc
7. 编写demo文件夹的BUILD文件
参考:https://github.com/grpc/grpc/blob/master/examples/cpp/helloworld/BUILD
cc_binary(name = "greeter_client",srcs = ["greeter_client.cc"],deps = ["@com_github_grpc_grpc//:grpc++","//proto:helloworld_proto",],)cc_binary(name = "greeter_server",srcs = ["greeter_server.cc"],defines = ["BAZEL_BUILD"],deps = ["@com_github_grpc_grpc//:grpc++","@com_github_grpc_grpc//:grpc++_reflection","//proto:helloworld_proto",],)
8. bazel编译客户端和服务端
参考:https://docs.bazel.build/versions/master/bazel-container.html
docker run \--network host \-e USER="$(id -u)" \-u="$(id -u)" \-v /root/src/grpc-demo-cpp:/src/workspace \-v /tmp/build_output:/tmp/build_output \-w /src/workspace \-e BAZEL_LINKLIBS=-l%:libstdc++.a \l.gcr.io/google/bazel:latest \--output_user_root=/tmp/build_output \build //demo:all
9. 试运行
在文件夹grpc-demo-cpp/bazel-bin/demo下会生成可执行文件
greeter_clientgreeter_server
执行即可,这两个文件的参数可以看源码
10. 完毕
02
—
吐槽
笔者只是想做一个c++的gRPC客户端,官网告诉我,很简单
实际上没那么简单
先看了官网文档,https://grpc.io/docs/languages/cpp/quickstart/
c++程序员真不是那么好当的,安装了一堆环境和软件,如gcc,cmake,经历了各种版本困惑后,开始编译
它抛了个错误给我
CMake Error at cmake/abseil-cpp.cmake:38 (find_package):Could not find a package configuration file provided by "absl" with any ofthe following names:abslConfig.cmakeabsl-config.cmakeAdd the installation prefix of "absl" to CMAKE_PREFIX_PATH or set"absl_DIR" to a directory containing one of the above files. If "absl"provides a separate development package or SDK, be sure it has beeninstalled.Call Stack (most recent call first):CMakeLists.txt:247 (include)
搜了下github,发现是个bug,还没修复
Errors compiling with external protobuf and abseil
https://github.com/grpc/grpc/issues/23667
为什么官网推荐的步骤,编译不出来啊啊啊啊啊?这是官网该有的态度吗?
2020 1月份的issue,为什么不修复啊?因为疫情躺在病床上吗?
还好,gRPC github还说能用bazel
但是,用bazel怎么把proto文件编成c++文件?它文档没写。
搜了半天google,发现有个bazel rule插件
https://github.com/stackb/rules_proto
好像很牛,可以编译个gRPC客户端出来,这个好,省事
搞起,开心的开始编译
它抛了个错误给我
WARNING: Download from https://mirror.bazel.build/github.com/google/protobuf/archive/v3.7.1.tar.gz failed: class com.google.devtools.build.lib.bazel.repository.downloader.UnrecoverableHttpException GET returned 404 Not FoundWARNING: Download from https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/archive/be3b1fc838386bdbea39d9750ea4411294870575.tar.gz failed: class com.google.devtools.build.lib.bazel.repository.downloader.UnrecoverableHttpException GET returned 404 Not FoundERROR: /path/to/bazel/cache/external/build_stack_rules_proto/node/BUILD.bazel:13:1: no such package '@com_github_grpc_grpc//src/compiler': BUILD file not found in directory 'src/compiler' of external repository @com_github_grpc_grpc. Add a BUILD file to a directory to mark it as a package. and referenced by '@build_stack_rules_proto//node:grpc_js'ERROR: Analysis of target '//:greeter_node_grpc' failed; build aborted: Analysis failedINFO: Elapsed time: 9.127sINFO: 0 processes.FAILED: Build did NOT complete successfully (7 packages loaded, 7 targets configured)
搜了下github,发现是个bug,还没修复
https://github.com/stackb/rules_proto/issues/139
为什么官网推荐的步骤,编译不出来啊啊啊啊啊?这是官网该有的态度吗?
2020 2月份的issue,为什么不修复啊?因为疫情躺在病床上吗?
不死心,再搜下github,发现bazel官方有个rule插件
https://github.com/bazelbuild/rules_proto
赶紧试了一把,发现这个插件能把proto文件编成c++文件,但是没有办法生成gRPC服务代码,好吧,放弃它,开始想哭了
冷静思考了一下,gRPC官方是怎么用bazel编译proto文件的呢?
翻了下gRPC github的example,总算是找对地方了,protos文件夹里的BUILD文件暴露了一切
为什么官网不把这个步骤写到文档啊啊啊?程序员成长不用靠这样的磨难的啊!
头发已经很少了,放过我们好吗?
