vlambda博客
学习文章列表

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 of the following names:
abslConfig.cmake absl-config.cmake
Add 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 been installed.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文件暴露了一切


为什么官网不把这个步骤写到文档啊啊啊?程序员成长不用靠这样的磨难的啊!

头发已经很少了,放过我们好吗?