Linux C/C++ 学习日记(68):grpc(一):配置grpc环境,及CMakeLists.txt模板
·
注:该文用于个人学习记录和知识交流,如有不足,欢迎指点。
一、环境搭建
1. 下载源码
git clone https://github.com/grpc/grpc
2. 查看版本并选择合适的版本,这里选择v1.45.2相对较新的版本
git tag
git checkout v1.45.2
查看此时grpc目录内容的大小du -h --max-depth=1, 可以看到427M左右
ubuntu@VM-16-11-ubuntu:~/rpc/grpc$ du -h --max-depth=1
348M ./.git
32K ./summerofcode
1.5M ./doc
6.5M ./tools
4.0K ./spm-core-include
24M ./test
80K ./cmake
3.0M ./third_party
4.0K ./spm-cpp-include
1.5M ./templates
8.0K ./.bazelci
1.9M ./include
5.0M ./examples
34M ./src
268K ./etc
64K ./.github
284K ./bazel
427M .
3. 下载第三方依赖库
git submodule update --init
下载完后会发现整个grpc目录内容明显变大
再次查看 目录大小,占用了1.3G。
ubuntu@VM-16-11-ubuntu:~/rpc/grpc$ du -h --max-depth=1
899M ./.git
32K ./summerofcode
1.5M ./doc
6.5M ./tools
4.0K ./spm-core-include
24M ./test
80K ./cmake
291M ./third_party
4.0K ./spm-cpp-include
1.5M ./templates
8.0K ./.bazelci
1.9M ./include
5.0M ./examples
34M ./src
268K ./etc
64K ./.github
284K ./bazel
1.3G
4. 编译和安装
mkdir -p cmake/build
cd cmake/build
cmake ../..
make
sudo make install
二、protobuf安装
不用手动安装protobuf,不然版本可能和grcp不匹配,必须在 grpc 执行 git submodule update --init 命令之后生成的 third_party/protobuf 里面编译安装对应的 protobuf。
cd third_party/protobuf/
./autogen.sh
./configure --prefix=/usr/local
make
sudo make install
sudo ldconfig # 使得新安装的动态库能被加载
protoc --version
显示3.19.4
三、测试环境
编译helloworld
cd grpc/examples/cpp/helloworld/
mkdir build
cd build/
cmake ..
make登录后复制
启动服务和客户端
# 启动服务端,监听在50051端口
./greeter_server
Server listening on 0.0.0.0:50051
# 启动客户端,服务端返回Hello world
./greeter_client
Greeter received: Hello world
四、CMakeLists.txt模板
需修改的两处
- 此例针对IM.Login.proto,可将IM.Login修正为实际协议名,且支持多协议生成。
- for_each可以同时生成多个依赖proto的可执行文件(示例中为im_login_client.cc、
im_login_server.cc、im_login_async_server.cc)
# 1. 最低CMake版本
cmake_minimum_required(VERSION 3.10)
# 2. 项目名
project(grpc_demo CXX)
# 3. C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# set(CMAKE_BUILD_TYPE Debug) #生成可调试的文件
# 4. 查找核心依赖(注意使用 CONFIG 模式)
find_package(Protobuf REQUIRED)
find_package(gRPC CONFIG REQUIRED) # 这里加上 CONFIG
# 5. 定义工具和库目标
# Protobuf
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
set(_REFLECTION gRPC::grpc++_reflection)
if(CMAKE_CROSSCOMPILING)
find_program(_PROTOBUF_PROTOC protoc)
else()
set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
endif()
# gRPC
set(_GRPC_GRPCPP gRPC::grpc++)
if(CMAKE_CROSSCOMPILING)
find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
else()
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
endif()
# 6. 配置proto文件
set(PROTO_FILES
${CMAKE_CURRENT_SOURCE_DIR}/IM.Login.proto
#${CMAKE_CURRENT_SOURCE_DIR}/public.proto #支持多协议生成,比如在IM.Login.proto中import public.proto了
)
set(GENERATED_SRCS "") # 用于收集所有生成的 .pb.cc 和 .grpc.pb.cc
# 7. 生成proto和grpc代码
foreach(PROTO_FILE ${PROTO_FILES})
# 步骤1:获取带后缀的完整文件名(如 IM.Login.proto)
get_filename_component(PROTO_FILENAME ${PROTO_FILE} NAME)
# 步骤2:手动替换掉.proto后缀,得到基础名(IM.Login.proto → IM.Login)
string(REPLACE ".proto" "" PROTO_BASE_NAME ${PROTO_FILENAME})
# 步骤3:定义生成的文件路径(确保是 IM.Login.pb.cc)
set(PB_CC "${CMAKE_CURRENT_BINARY_DIR}/${PROTO_BASE_NAME}.pb.cc")
set(PB_H "${CMAKE_CURRENT_BINARY_DIR}/${PROTO_BASE_NAME}.pb.h")
set(GRPC_CC "${CMAKE_CURRENT_BINARY_DIR}/${PROTO_BASE_NAME}.grpc.pb.cc")
set(GRPC_H "${CMAKE_CURRENT_BINARY_DIR}/${PROTO_BASE_NAME}.grpc.pb.h")
# 加入总列表
list(APPEND GENERATED_SRCS ${PB_CC} ${GRPC_CC})
# 生成命令
add_custom_command(
OUTPUT ${PB_CC} ${PB_H} ${GRPC_CC} ${GRPC_H} #如果有这些文件了,就不会再生成
COMMAND ${_PROTOBUF_PROTOC}
ARGS --cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
--grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
-I "${CMAKE_CURRENT_SOURCE_DIR}" #-I 表示proto所在的目录
${PROTO_FILE}
DEPENDS ${PROTO_FILE} #如果当前文件修改了重新生成当前文件。 注意:不同协议间有import需要改为 DEPENDS ${PROTO_FILES},这样, 改了任何一个 proto(包括 public.proto)都重新生成
COMMENT "Generating code for ${PROTO_BASE_NAME}.proto"
)
endforeach()
# 8. 批量编译多个目标
foreach(_target
im_login_client
im_login_server
im_login_async_server)
add_executable(${_target}
"${_target}.cc"
${GENERATED_SRCS} # 链接所有生成的文件
)
target_include_directories(${_target}
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(${_target}
PRIVATE
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF}
pthread
)
endforeach()
# 可选:设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
补充:
| 变量 | 含义 |
|---|---|
CMAKE_CURRENT_SOURCE_DIR |
当前处理的 CMakeLists.txt 所在的源码目录(即源代码所在路径)。 |
CMAKE_CURRENT_BINARY_DIR |
当前处理的 CMakeLists.txt 对应的构建目录(即编译生成文件的路径)。 |
通俗示例假设项目结构如下,且你在 build/ 目录下执行 cmake ..(源码外构建):
project/ # 根目录
CMakeLists.txt # 根 CMakeLists.txt
src/
CMakeLists.txt # 子目录 CMakeLists.txt
main.cpp
build/ # 构建目录(你在这里运行 cmake)
此时变量值为:
- 处理根
CMakeLists.txt时:CMAKE_CURRENT_SOURCE_DIR=/path/to/projectCMAKE_CURRENT_BINARY_DIR=/path/to/project/build
- 处理
src/CMakeLists.txt时:CMAKE_CURRENT_SOURCE_DIR=/path/to/project/srcCMAKE_CURRENT_BINARY_DIR=/path/to/project/build/src
常见用途
CMAKE_CURRENT_SOURCE_DIR:用于引用源码文件,如${CMAKE_CURRENT_SOURCE_DIR}/main.cpp。CMAKE_CURRENT_BINARY_DIR:用于引用生成的文件(如配置头文件、编译输出),如${CMAKE_CURRENT_BINARY_DIR}/config.h。
更多推荐




所有评论(0)