I have a python script that parses all of the C++ source files in the project's directory, looks for some stuff in the files, and then generates a file. This python script works fine, but I want it to automatically run before building my C++ project.
So basically, I want this python script to run before every build, so if any .h or .cpp files have been changed. I'd also like it to run if the python script itself has been changed. I have the python script in question, genenums.py
, in the same directory as my C++ source files such as main.cpp
, etc.
I've tried experimenting with add_custom_command
based on documentation, but I can't get cmake to ever run this python script in any instance. I'm not sure how to make this work right, as I'm new to cmake.
Here's my current cmake file:
cmake_minimum_required(VERSION 3.9)
project(enum_test)
set(CMAKE_CXX_STANDARD 17)
include_directories(include)
find_package( PythonInterp 2.7 REQUIRED )
find_package( PythonLibs 2.7 REQUIRED )
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} genenums.py
DEPENDS genenums.py $(CMAKE_CURRENT_BINARY_DIR)
OUTPUT enums.h
WORKING_DIRECTORY $(CMAKE_CURRENT_BINARY_DIR)
COMMENT "Generating enums"
)
add_executable(enum_test main.cpp test.h test.cpp)
Ok, I have a foolproof, non-ugly way to have cmake run any kind of commands right before a build to build a dependency, waiting until the commands are done before doing the build.
add_custom_target(
run ALL
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/genenums.py ${CMAKE_CURRENT_SOURCE_DIR}
BYPRODUCTS enums.h
COMMENT "Generating enums"
)
add_dependencies(enum_test run)
The two key parts are the add_custom_target
and add_dependencies
, both are required to make this work. Place both after the add_executable
in CMakeLists.txt
. enum_test
refers to the target created by add_executable
(the first name in its list), so you'd set that to your project's name.
You can name the custom target to whatever you like (I used run
here) by changing the run
in both add_custom_target
and add_dependencies
to something else.
There's one additional catch with add_custom_target
... WORKING_DIRECTORY
in that did nothing for my python script. Even when I tried to set the WORKING_DIRECTORY
to ${CMAKE_CURRENT_SOURCE_DIR}
, the script executed in the default ${CMAKE_CURRENT_BINARY_DIR}
anyway.
So for this one catch, whatever commands you're using need to be able to take a command line argument of ${CMAKE_CURRENT_SOURCE_DIR}
and use that to operate in the source directory properly (assuming that's your goal). That's why I have ${CMAKE_CURRENT_SOURCE_DIR}
at the end of this line:
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/genenums.py ${CMAKE_CURRENT_SOURCE_DIR}
Here's the full CMakeLists.txt
with the working setup, should be fairly easy to adapt to any particular project's CMakeLists.txt
.
cmake_minimum_required(VERSION 3.9)
project(enum_test)
set(CMAKE_CXX_STANDARD 17)
include_directories(include)
find_package( PythonInterp 2.7 REQUIRED )
add_executable(enum_test enums.h main.cpp test.h test.cpp)
add_custom_target(
run ALL
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/genenums.py ${CMAKE_CURRENT_SOURCE_DIR}
BYPRODUCTS enums.h
COMMENT "Generating enums"
)
add_dependencies(enum_test run)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With