protobuf是google开发的一个序列化和反序列化的库,通过.proto文件定义文件格式,序列化后的数据是binary的,可以在多语言上使用.一般情况下,若客户端和服务端都是自己做的,用protobuf作为通讯协议,无疑是一个不错的选择.
个人一般喜欢用CMake来管理c++工程.那么,cmake下使用protobuf对个人而言是个很重要的事情.
我准备了一个简单的工程,如此处所示.
cmake有官方的modules,文件是FindProtobuf.cmake,里面有宏PROTOBUF_GENERATE_CPP.用法据介绍如下:
C++
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS foo.proto)
ADD_EXECUTABLE(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
TARGET_LINK_LIBRARIES(bar ${PROTOBUF_LIBRARIES})很厉害是吧..
现在我有一组文件如下:
Bash
├── CMakeLists.txt
├── README.md
├── meta
│ └── proto
│ ├── CMakeLists.txt
│ └── common
│ ├── bar
│ │ ├── CMakeLists.txt
│ │ └── bar.proto
│ └── foo
│ ├── CMakeLists.txt
│ └── foo.proto
└── src
├── CMakeLists.txt
├── c_proto.cc
└── c_proto.hh其中foo.proto文件如下:
C
message foo_msg
{
optional string name = 1;
}bar.proto文件如下:
C
import "common/foo/foo.proto";
message bar_msg
{
optional foo_msg foo = 1;
optional string name = 2;
}如上是对foo_msg和bar_msg的定义,bar引用了foo.开始我是使用的PROTOBUF_GENERATE_CPP那个宏,然后在有import的时候,妥妥的跪了,google家的也表示不解.
然后直接骚扰下cmake的mail list.然后第二天,一个好心的中国人告诉我,他们都是自定义protoc的命令的.
经过一些挣扎修改,最后决定还是手工拼命令.
C
FIND_PACKAGE(Protobuf REQUIRED)find宏可以获得PROTOBUF_LIBRARIES,所有用到proto的需要依赖这组lib.
然后在proto的逻辑root目录下设置好参数,把它加入proto flags list中
C
SET(PROTO_META_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR})
LIST(APPEND PROTO_FLAGS -I${CMAKE_CURRENT_SOURCE_DIR})然后代码如下:
C
FILE(GLOB BAR_PROTOS "*.proto")
FOREACH(FIL ${BAR_PROTOS})
GET_FILENAME_COMPONENT(ABS_FIL ${FIL} ABSOLUTE)
GET_FILENAME_COMPONENT(FIL_WE ${FIL} NAME_WE)
LIST(APPEND BAR_SRCS "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
LIST(APPEND BAR_HDRS "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
EXECUTE_PROCESS(
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} ${PROTO_FLAGS} --cpp_out=${PROTO_META_BASE_DIR} ${FIL}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
ENDFOREACH()
ADD_LIBRARY(bar ${BAR_SRCS})
TARGET_LINK_LIBRARIES(bar foo)
Comments · 10