Reputation: 5102
I do have a project with a Protobuf interface that I need to compile and install for Python using CMake.
My CMakeLists.txt
looks like below:
file(GLOB PROTO_INPUT "*.proto")
add_custom_target(BuildPythonInterface ALL
protoc -I=${CMAKE_CURRENT_SOURCE_DIR} --python_out=${CMAKE_CURRENT_BINARY_DIR} ${PROTO_INPUT}
DEPENDS ${PROTO_INPUT})
file(GLOB PROTOBUF_INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/*_pb2.py")
LIST(APPEND PROTOBUF_INTERFACE "${INIT_PY}" )
install(FILES ${PROTOBUF_INTERFACE} DESTINATION "lib/python2.7/site-packages/${PROJECT_NAME}/proto/")
It does indeed work like a charm, when running it twice, but if I delete my build directory and start configering it from the scratch, then the protobuf-interface files for Python are not being found by file(GLOB PROTOBUF_INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/*_pb2.py")
as they are not yet existent, until the make all
command is run once.
Is there a way to make CMake execute the above code line after having run the build once? Or maybe an other (cleaner?) way of doing this?
Upvotes: 2
Views: 797
Reputation: 171127
The preferred CMake way of doing this would be to list both input and output files explicitly instead of using file(GLOB)
. There are multiple reasons for this; what you're facing is one of them; the fact that with GLOB
, adding a file does not cause an automatic re-run of CMake (and thus the file is not picked up) is another.
Nevertheless, if GLOB
s are the best way to go in your specific scenario (as you mentioned in comments), you can solve this by using install(DIRECTORY)
instead of installing files. Something like this:
file(GLOB PROTO_INPUT "*.proto")
add_custom_target(BuildPythonInterface ALL
protoc -I=${CMAKE_CURRENT_SOURCE_DIR} --python_out=${CMAKE_CURRENT_BINARY_DIR}/ToBeInstalled ${PROTO_INPUT}
DEPENDS ${PROTO_INPUT})
install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ToBeInstalled/
DESTINATION "lib/python2.7/site-packages/${PROJECT_NAME}/proto/"
FILES_MATCHING PATTERN "*_pb2.py"
)
install(FILES ${INIT_PY} DESTINATION "lib/python2.7/site-packages/${PROJECT_NAME}/proto/")
Notice the trailing slash in the DIRECTORY
argument. It's important: if it wasn't present, the name ToBeInstalled
would be appended to the destination directory. With the trailing slash, this appending is suppressed.
Upvotes: 3