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_client
greeter_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 Found
WARNING: 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 Found
ERROR: /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 failed
INFO: Elapsed time: 9.127s
INFO: 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文件暴露了一切
为什么官网不把这个步骤写到文档啊啊啊?程序员成长不用靠这样的磨难的啊!
头发已经很少了,放过我们好吗?