生成自己的 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)
假设我有一个脚本,它生成一组源文件,形成我想在 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)