如何为CMake构建过程本身添加_custom_command()?

时间:2015-09-19 16:43:04

标签: cmake add-custom-command

是否有任何方法可以执行相当于add_custom_command(在某个文件更改时运行外部脚本),但是对于应该在CMake脚本执行期间运行的内容? (也就是说,生成依赖图。)

我们将源代码文件拆分为多个子库,并且有配置文件列出哪个源文件与哪个库一起使用。 (这些配置文件的格式由我们使用的另一个工具修复。)目前,我们运行一个自定义外部脚本,解析这些配置文件并写入新文件,然后由CMake构建过程加载,以提供文件名列表传递给add_library()。这意味着每次添加/删除源文件时,我们都需要记住在重新运行CMake之前重新运行prebuild命令,然后重新启动构建命令。

我知道CMake可以认识到它需要重新运行,所以我希望我们可以让CMake 1)认识到配置文件已经改变2)重新运行配置文件解析器3)加载新文件列表4)使用新文件列表重新生成依赖关系树5)最后使用包含的新文件启动实际的构建/编译过程。 ...以及标准构建命令中的所有这些,无需手动运行外部配置文件解析器或手动重新运行CMake命令,并且在配置文件未发生更改时无需执行。

在搜索中,我确实找到了this question,其中建议使用configure_file(),但这并没有解决如何调用外部配置文件解析器脚本的问题。

1 个答案:

答案 0 :(得分:2)

将我的评论转化为答案

configure_file()是重新触发配置过程的正确选择。 execute_process()用于在配置步骤中运行命令。

以下是说明中步骤的抽象CMake代码段:

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()文件发生更改时,
  • .cfg都会重新触发CMake
    • 如果您实际使用.cfg文件作为execute_process()中的命令行参数,则应使用当前二进制目录中生成的.tmp版本
  • execute_process()可以做很多事情
    • 我用它来回显stdout并将输出写入文件
    • 默认WORKING_DIRECTORY这里是当前的二进制目录
  • file()读取源文件列表
    • 每个完整路径,新行分开
  • 我已将生成的文件按目的写入二进制输出目录
    • 它使清理构建更容易,只需删除整个二进制输出目录
    • 和CMake对此有内置支持;它将在当前源中首先搜索没有绝对路径的源文件,然后在当前二进制目录中搜索
  • 我没有使用GENERATED源文件属性
    • 因为只有源是由之前的构建步骤生成的
    • 才需要
    • 并且当源文件列表中的文件实际丢失时,CMake本身不再认识