Reputation: 3652
Is there any way to do the equivalent of add_custom_command (run an external script when a certain file changes), but for something that should be run during CMake script execution itself? (That is, for dependency graph generation.)
We have our source code files split up into multiple sub-libraries, and there are configuration files which list which source file goes with which library. (The format of these configuration files are fixed by another tool we use.) Currently, we run a custom external script which parses those configuration files and writes new files, which are then loaded by the CMake build process to give the list of filenames to be passed to add_library(). This means that each time a source file is added/removed, we need to remember to re-run the prebuild command, before re-running CMake, and then re-launching the build command.
I know that CMake can recognize that it needs to re-run itself, so I'm hoping that we can get CMake to 1) recognize that the configuration files are changed 2) rerun the configfile parser 3) load the new file list 4) use the new file list to regenerate the dependency tree 5) finally launch the actual build/compilation process with the new files included. ... and all this from the standard build command, without having to manually run the external configfile parser or manually re-run the CMake command, and without needless execution when the configfile hasn't changed.
In searching, I did find this question, where using configure_file() is suggested, but that doesn't address how to invoke the external configfile parser script.
Upvotes: 1
Views: 2310
Reputation: 42842
Turning my comment into an answer
configure_file()
is the right choice to retrigger the configuration process. And execute_process()
is used to run commands during the configuration step.
Here is an abstract CMake snippet of the steps in your description:
function(my_add_library_from_cfg _target _cfg_file)
# Retrigger configuration process each time config file changes
get_filename_component(_cfg_name "${_cfg_file}" NAME)
configure_file("${_cfg_file}" "${_cfg_name}.tmp")
# Generating sources and file list
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo "#define FOO"
OUTPUT_FILE foo.c
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo "foo.c"
OUTPUT_FILE files.lst
)
# Reading file list and add library
file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/files.lst" _sources_lst)
add_library(${_target} ${_sources_lst} "${_cfg_file}")
endfunction(my_add_library_from_cfg)
configure_file()
will retrigger CMake each time the given .cfg
file changes
.cfg
file as a command line parameter in execute_process()
you should use the generated .tmp
version in the current binary directoryexecute_process()
can do a lot of things
stdout
and write the output to filesWORKING_DIRECTORY
here is the current binary directoryfile()
reads in the list of source files
GENERATED
source file property
Upvotes: 3