通常需要确保 CMake 构建项目在编译后最终位于某个位置,并且 add_custom_command(..POST_BUILD...)
command 是一种常见的设计模式来实现这一点:
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_* 命令不跟踪它们是否实际需要运行,并且保守地假设目标始终是陈旧的)。
最佳答案
只需使用 add_custom_command
的常用组合即可和 add_custom_target
,当第一个为第二个生成文件时:
# Because OUTPUT option may not use generator expressions,
# extract name of file from target's properties.
get_target_property(mytarget_basename mytarget OUTPUT_NAME)
get_target_property(mytarget_suffix mytarget SUFFIX)
set(mytarget_filename ${mytarget_basename}${mytarget_suffix})
# make copied file be dependent from one which is build.
# Note, that DEPENDS here creates dependencies both from the target
# and from the file it creates.
add_custom_command(OUTPUT
${CMAKE_BINARY_DIR}/final_destination/${mytarget_filename}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:mytarget>
${CMAKE_BINARY_DIR}/final_destination
DEPENDS mytarget
)
# Create target which consume the command via DEPENDS.
add_custom_target(copy_files ALL
DEPENDS ${CMAKE_BINARY_DIR}/final_destination/${mytarget_filename}
)
与使用 POST_BUILD 相比,此代码使用了额外的目标。但你别无选择:add_custom_command
不能附加到在其他目录中创建的目标。通常,通过
CMAKE_<TYPE>_OUTPUT_DIRECTORY
指定该目录而不是将可执行文件/库复制到其他二进制目录中更简单。多变的。
关于cmake - 当目标位于子目录中时,替代 CMake POST_BUILD 命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40294146/