Suppose you have a repository with a folder (named dataset) with several .csv files and a python script (named csvcut.py) that takes all the .csv in dataset and generates corresponding .h files.
Those .h files are included in some .cpp files to build an executable (add_executable(testlib...
) used for testing.
Suppose you use add_custom_target(test_pattern...
to make a target (named test_pattern) that runs csvcut.py, and add_dependencies(testlib test_pattern)
to run the script before building testlib.
This works, but it would be better if:
#include <tests/dataset/generated.h>
.Do you have any suggestions for making these improvements / optimizations?
Thanks, Alberto
This requires multiple steps, but can all be handled with standard CMake. First, we'll use add_custom_command
to actually generate the files. I'm also adding a custom target, but only since I couldn't figure out how to make an INTERFACE
library work without it.
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/include/foo.h"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/gen.py"
DEPENDS
gen.py
foo.h.in
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include"
)
add_custom_target(gen_files
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/foo.h"
)
For my case, gen.py
just spits out a basic header file, but it shouldn't matter. List whatever files you need as output, and your csv file should be under DEPENDS
(for me, foo.h.in
tries to simulate this).
Since you only mentioned generating header files, I created an INTERFACE
library that depends on the gen_files
target. I also added the appropriate include directory.
add_library(foo INTERFACE)
target_include_directories(foo
INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/include"
)
add_dependencies(foo
gen_files
)
If building a STATIC
/SHARED
library, I was able to add the generated files directly as sources and dependencies worked, but the INTERFACE
library required the extra target (even when I tried listing the files under add_dependencies
). Since you already have a custom target, I assume this won't be a huge issue.
Lastly, I have an executable that links against foo
.
add_executable(main
main.c
)
target_link_libraries(main
PRIVATE
foo
)
Demo:
$ make clean
$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake include Makefile
$ make
[ 33%] Generating include/foo.h
[ 33%] Built target gen_files
[ 66%] Building C object CMakeFiles/main.dir/main.c.o
[100%] Linking C executable main
[100%] Built target main
$ make clean
$ make main
[ 33%] Generating include/foo.h
[ 33%] Built target gen_files
[ 66%] Building C object CMakeFiles/main.dir/main.c.o
[100%] Linking C executable main
[100%] Built target main
$ make
[ 33%] Built target gen_files
[100%] Built target main
$ touch ../foo.h.in
$ make
[ 33%] Generating include/foo.h
[ 33%] Built target gen_files
[100%] Built target main
$ touch ../gen.py
$ make
[ 33%] Generating include/foo.h
[ 33%] Built target gen_files
[100%] Built target main
$ ls include/
foo.h
If either the input (foo.h.in
) or generation script (gen.py
) change, the targets are rebuilt.