cmake - 当目标位于子目录中时,替代 CMake POST_BUILD 命令

标签 cmake

通常需要确保 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/

相关文章:

c++ - Linux 上的 CMake FindJNI 问题

c++ - 在 cmake C++ 项目中使用 mongodb cxx 驱动程序

c - Android Studio : include an other path in a c file

c++ - Qt 带 Cmake : set(QT_USE_QTWEBKIT TRUE) not working

c++ - 最佳实践 - 在单元测试中链接到 lib 或编译源代码

cmake - 如何调查 imp.load_module 上的 python2 段错误

c++ - 如何让CMake在/usr/local下使用boost

c++ - CMakeLists.txt 中的 GLM 链接

c++ - 使用 CMake 强制进行 32 位编译的正确方法

cmake - 为什么 CMake 检查 C++ 编译器?