利用Cmake自动编译proto文件生成protobuf cpp代码

项目中pb用的越来越多,更改后手动编译proto越来越麻烦,摸索了下在cmake中自动编译proto文件的办法。

  1. 利用cmake提供的宏PROTOBUF_GENERATE_CPP

示例代码结构如下:

1
2
3
4
5
6
7
8
9
10
11
[@gapp_devnet_1 ~/tests/cmakepb]$ tree
.
|-- CMakeLists.txt
|-- build
`-- src
|-- CMakeLists.txt
|-- main.cpp
`-- proto
|-- CMakeLists.txt
|-- cmd.proto
`-- head.proto

顶层CMakeLists.txt如下:

1
2
3
project (demo)
cmake_minimum_required(VERSION 2.8)
add_subdirectory(src)

src/CMakeLists.txt如下:

1
2
3
add_subdirectory(proto)
add_executable(demo main.cpp)
target_link_libraries(demo proto)

src/proto/CMakeLists.txt如下:

1
2
3
4
5
6
7
8
find_package(Protobuf REQUIRED)
FILE(GLOB protofiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
message(STATUS ${protofiles})
PROTOBUF_GENERATE_CPP(PROTOSRCS PROTOHDRS ${protofiles})
message(STATUS ${PROTOSRCS})
add_library(proto STATIC ${PROTOSRCS} ${PROTOHDRS})
target_link_libraries(proto protobuf)
target_include_directories(proto PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

采用out of source编译,cmake将生成的.pb.h,.pb.cc放在build/src/proto/目录下,故而需要在src/proto/CMakeLists.txt中设置target_include_directories(proto PUBLIC ${CMAKE_CURRENT_BINARY_DIR}),这样生成的头文件才能被外层cmake可见。

  1. 利用命令ADD_CUSTOM_COMMAND

示例代码结构如下:

1
2
3
4
5
6
7
8
9
10
[@gapp_devnet_1 ~/tests/cmakepb1]$ tree
.
|-- CMakeLists.txt
|-- build
`-- src
|-- CMakeLists.txt
|-- main.cpp
`-- proto
|-- cmd.proto
`-- head.proto

3 directories, 5 files
顶层CMakeLists.txt如下:

1
2
3
project (demo)
cmake_minimum_required(VERSION 2.8)
add_subdirectory(src)

src/CMakeLists.txt如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FILE(GLOB proto_files ${CMAKE_CURRENT_SOURCE_DIR}/proto/*.proto)
FOREACH(proto_file ${proto_files})
STRING(REGEX REPLACE "[^/]proto" "" proto_file_name ${proto_file})
LIST(APPEND PROTO_SRCS "${proto_file_name}.pb.cc")
ADD_CUSTOM_COMMAND(
OUTPUT "${proto_file_name}.pb.h" "${proto_file_name}.pb.cc"
COMMAND protoc --proto_path=${CMAKE_CURRENT_SOURCE_DIR}/proto
--cpp_out=${CMAKE_CURRENT_SOURCE_DIR}/proto/ ${proto_file}
DEPENDS ${proto_file}
)
ENDFOREACH(proto_file)
message(STATUS ${PROTO_SRCS})
include_directories(./proto)
add_executable(demo main.cpp ${PROTO_SRCS})
target_link_libraries(demo protobuf)