How to add_custom_command() for the CMake build process itself?

戏子无情 提交于 2019-12-02 09:14:08

问题


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.


回答1:


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
    • if you actually use the .cfg file as a command line parameter in execute_process() you should use the generated .tmp version in the current binary directory
  • execute_process() can do a lot of things
    • I used it to echo to stdout and write the output to files
    • the default WORKING_DIRECTORY here is the current binary directory
  • file() reads in the list of source files
    • full paths each, newline separated
  • I have written the generated files by purpose to the binary output directory
    • it makes a clean build easier, just delete the whole binary output directory
    • and CMake has build-in support for this; it will search for source files without absolute path first in the current source and then in current binary directory
  • And I didn't use the GENERATED source file property
    • because that would only be needed if the sources were generated by a previous build step
    • and CMake itself won't recognize anymore when actually a file from source file list would be missing


来源:https://stackoverflow.com/questions/32670701/how-to-add-custom-command-for-the-cmake-build-process-itself

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!