生成自己的 CMake 文件和目标的代码生成器

Code generator generating its own CMake files and targets

假设我有一个脚本,它生成一组源文件,形成我想在 CMakeLists.txt 中 link 反对的目标。如果后者知道文件名,那么通常的 add_custom_target()add_custom_command() 命令可以将生成的文件用作目标源。

不过,我们假设只有生成器脚本知道文件名和位置。如何生成目标库,以便父 CMakeLists.txt 可以在不知道实际文件名的情况下 link 反对它?

请注意,依赖主题不在此问题的范围内,因为脚本知道何时重新生成或不重新生成。这不是 CMake 的最佳用途,但在这个用例中已经足够了。

想法 #1

该脚本还生成一个 generated.cmake 文件,父文件使用 include(generated.cmake) 包含该文件。问题:CMake 找不到 generated.cmake,因为它在配置时不存在。

想法 #2

与想法 #1 类似,但脚本是使用 execute_process() 调用的,因此 generated.cmake 在配置时存在。问题:在后续构建中不再调用该脚本,因此忽略了对其输入的可能更改。

想法 #3

脚本传回目标和文件列表,以某种方式 被父 CMakeLists.txt 考虑。到目前为止,我找不到这样做的方法。

我提出的解决方案最终是所有三个想法的混合体。

想法 #1 问题的解决方案

execute_process() 实际上确保 generated_targets.cmake 在配置时存在。

想法 #2 和想法 #3 问题的解决方案

this answer to "Add dependency to the CMake-generated build-system itself" 中所述,可以编辑 CMAKE_CONFIGURE_DEPENDS 目录 属性 以添加触摸重新触发配置步骤的文件。

关键的成功因素是这个 属性 可以在初始 execute_process() 调用之后设置,以便脚本可以识别并列出其输入依赖项(在输出文件中),然后添加这些依赖项CMAKE_CONFIGURE_DEPENDS,因此也解决了输入依赖问题。

生成的伪代码

# The script generates:
# - <output_dir>/cmake/input_files
# - <output_dir>/cmake/generated_targets.cmake
execute_process(
  COMMAND myScript
    --output-dir ${CMAKE_CURRENT_BINARY_DIR}/generated
)

# Mark the input files as configure step dependencies so that the execute_process
# commands are retriggered on input file change.
file(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/generated/cmake/input_files _input_files)

set_property(
  DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
    ${_input_files}
)

# Add the generated CMake targets.
include(${CMAKE_CURRENT_BINARY_DIR}/generated/cmake/generated_targets.cmake)