Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake: conditionally generate protobuf `*pb.{h|cpp}` files when *.proto files change

I am part of a project that is using protobufs to communicate between a Python based client and a c++ based server. We are also using CMake.

With CMake, I am looking for a way to conditionally call the protoc program only when *.proto files change. My current directory structure (this seems to be part of the problem) has a directory for the *.proto files, and separate directories for the generated *.pb.{h|cc} and *_pb2.py files:

  build/
  Messages/proto/  <--- .proto files are here
  Messages/cpp/    <--- would like the auto generated c++ files here
  Messages/py/     <--- would like the auto generated Python files here
  Server/Main.cpp
  Client/Main.py
  CMakeLists.txt

The (root) CMakeLists.txt file (below) runs the protoc program when the build/cmake .. command is executed:

project(AAA)

MESSAGE("Protobuf autogeneration STARTED")

file(GLOB proto_packages "${AAA_SOURCE_DIR}/Messages/proto/*.proto")
execute_process(COMMAND protoc -I=${AAA_SOURCE_DIR}/Messages/proto --cpp_out=${AAA_SOURCE_DIR}/Messages/cpp/ --python_out=${AAA_SOURCE_DIR}/Messages/py/ ${proto_packages})

MESSAGE("Protobuf autogeneration COMPLETED")

cmake_minimum_required(VERSION 2.8)
find_package(Boost)
find_package(Protobuf REQUIRED)

include_directories(${Boost_INCLUDE_DIRS})
include_directories(${PROTOBUF_INCLUDE_DIR})

add_subdirectory(Messages/proto)
add_subdirectory(Messages/cpp)
add_subdirectory(Server)

The Messages/proto/CMakeLists.txt file (which I'm not sure has any effect):

file(GLOB proto_packages "${AAA_SOURCE_DIR}/Messages/proto/*.proto")
execute_process(COMMAND protoc -I=${AAA_SOURCE_DIR}/Messages/proto --cpp_out=../cpp --python_out=../py ${proto_packages}
            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

Ideally, the protoc program should run as part of the build/make command, and only (re)generate the *.pb.{h|cc} and *_pb2.py files when a *.proto file changes.

Some files in the Server/ directory have #include <Messages/cpp/Xxxx.pb.h> directives.

For bonus points, I would prefer to have the *.pb.{h|cc} and *_pb2.py files be generated into their respective directories (Messages/cpp/ and Messages/py/ respectively). However, if someone is able to help with the dependency part of the problem, I am happy to have the *.pb.{h|cc} and *_pb2.py files co-exist with the *.proto files.

Thanks in advance for any suggestions !

like image 344
Scottymac Avatar asked Sep 18 '13 00:09

Scottymac


1 Answers

This is untested, but you need to add a custom command a custom target.

You'd need to create some variables for the output line, but without knowing how to turn *.proto into the *.pb.{h|cc} and *_pb2.py files I can't help there. See the proto_packages_cpp and proto_packages_python variables for where those should go.

file(GLOB proto_packages "${AAA_SOURCE_DIR}/Messages/proto/*.proto")
add_custom_command(
    COMMAND protoc -I=${AAA_SOURCE_DIR}/Messages/proto --cpp_out=../cpp --python_out=../py ${proto_packages}
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    DEPENDS ${proto_packages}
    OUTPUT ${proto_packages_cpp} ${proto_packages_python}
)
add_custom_target(protobuf_autogeneration_target ALL
    DEPENDS ${proto_packages}
)
like image 134
grim Avatar answered Oct 02 '22 22:10

grim