【发布时间】:2016-10-27 21:02:25
【问题描述】:
通常需要确保 CMake 构建项目在编译后最终位于某个位置,而 add_custom_command(..POST_BUILD...) 命令是实现此目的的常用设计模式:
add_custom_command(
TARGET mytarget
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:mytarget> ${CMAKE_BINARY_DIR}/final_destination
)
遗憾的是,当相关目标位于相对于包含 add_custom_command 调用的文件的子目录中时,它不起作用,该调用是通过 add_subdirectory() 命令递归编译的。尝试这样做会导致以下错误消息:
CMake Warning (dev) at CMakeLists.txt:4 (add_custom_command):
Policy CMP0040 is not set: The target in the TARGET signature of
add_custom_command() must exist. Run "cmake --help-policy CMP0040" for
policy details. Use the cmake_policy command to set the policy and
suppress this warning.
TARGET 'mytarget' was not created in this directory.
This warning is for project developers. Use -Wno-dev to suppress it.
在许多情况下,有一个简单的解决方法:只需确保add_custom_command() 调用发生在子目录的CMakeLists.txt 文件中,一切都会正常工作。
但是,这并不总是可能的!子目录可能是我们无法控制的外部依赖项的 CMake 项目。例如,将 CMake 递归编译与 Git 子模块相结合是很常见的,在这种情况下,无法永久存储对子项目构建系统的修改。
然后我的问题归结为以下几点:CMake 是否提供另一种机制来创建目标,该目标将在重建子项目的目标时自动触发,并可用于将最终的可执行文件或共享库复制到其他一些地点?
我的目标是自动发生这种情况,而无需使用另一个目标专门调用“make”/“ninja”。此外,副本仅应在实际需要时执行(根据 cmake 文档,一些 add_custom_* 命令不跟踪它们是否实际需要运行,并且保守地假设目标始终是陈旧的)。
【问题讨论】:
-
所有子目录
CMakeLists.txt文件都是同一个/你的项目吗?我们是否谈论所有目标,例如可执行类型还是您只想将其应用于特定目标?在我的项目中,我为所有标准 CMake 调用创建了自己的function(),因此我可以修改例如add_executable()用于我的项目(例如自动为所有此类调用添加构建后步骤)。 -
子目录通常是共享库,作为从 github 克隆的 git 子模块分发(例如
pugixml)。这些项目有自己的 CMake 项目,我不能(也不想)改变。父项目可以生成可执行或共享库的混合——我并不认为它对这个问题特别重要。
标签: cmake