【问题标题】:Generator expressions cmake: copying works in debug but not release mode生成器表达式cmake:复制在调试但不是发布模式下工作
【发布时间】:2020-02-09 21:15:15
【问题描述】:

我试图弄清楚如何根据 cmake 中的配置复制一些库。

我试过了:

add_custom_command(TARGET Myapp
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy_if_different
  $<$<CONFIG:Debug>:${_LIBS_DEBUG}> 
  $<$<CONFIG:Release>:${_LIBS_RELEASE}> 
  $<TARGET_FILE_DIR:MyApp>)

它在 Debug 中复制库,但在 release 中不复制:

  1. 这应该是合法的并且应该有效吗?
  2. 如果不合法(我没有收到错误),我怎样才能达到同样的效果?

【问题讨论】:

  • 如果_LIBS... 只包含一个文件,对我来说看起来是合法的。如果没有在add_custom_command() 周围添加foreach() 循环。我们谈论makefile环境吗?因为你例如需要知道默认配置只是空的。能否请您添加用于生成构建环境的命令行?或者,这些库是否也使用 CMake 构建?然后你可以有一个通用的 _LIBS 列表,其中包含像 $&lt;TARGET_FILE:libA&gt; 这样的生成器表达式。
  • 我的命令行是针对 Visual Studio 的,所以里面没有 -DCMAKE_BUILD_TYPE。我正在用 CMake 编译一组 46 个项目,但我要安装的库只是指向库的字符串,而不是我项目的一部分。
  • 感谢您提供更多信息。只是一个猜测:您是否尝试过删除两个生成器表达式之间的空格/换行符?我通常用来调试这些情况的方法是在有问题的实际行之前添加另一个COMMAND,它只是回显命令行。在你的情况下COMMAND ${CMAKE_COMMAND} -E echo $&lt;$&lt;CONFIG:Debug&gt;:${_LIBS_DEBUG}&gt;$&lt;$&lt;CONFIG:Release&gt;:${_LIBS_RELEASE}&gt; $&lt;TARGET_FILE_DIR:MyApp&gt;。也许还添加一个COMMAND ${CMAKE_COMMAND} -E echo Copying libs for config $&lt;CONFIG&gt; 来验证配置的名称。

标签: c++ cmake


【解决方案1】:

将我的 cmets 变成答案

我通常用来调试这些情况的方法是在有问题的实际行之前添加另一个COMMAND,它只是回显命令行。在你的情况下:

COMMAND ${CMAKE_COMMAND} -E echo 
    $<$<CONFIG:Debug>:${_LIBS_DEBUG}>
    $<$<CONFIG:Release>:${_LIBS_RELEASE}> 

我已经运行了几个测试,你会发现 $&lt;1:...&gt;$&lt;0:...&gt; 表达式没有被计算。

看到这一点,我正在搜索 CMake 的错误跟踪数据库,这是一个已知问题,但(对于 CMake 3.5.2)尚未解决:0009974: CMake should support custom commands that can vary by configuration.

此票证中提出了几种适用于现有 CMake 版本的方法。


在你的情况下——直到这个问题得到解决并且如果你想让它独立于外壳——我会用“旧方式”来做,并调用一个 CMake 脚本:

CopyLibsByConfig.cmake.in

if (_CONFIG STREQUAL "Debug")
    file(COPY @_LIBS_DEBUG@ DESTINATION "${_DEST_PATH}")
else()
    file(COPY @_LIBS_RELEASE@ DESTINATION "${_DEST_PATH}")
endif()

CMakeLists.txt

...
configure_file(CopyLibsByConfig.cmake.in CopyLibsByConfig.cmake @ONLY)
add_custom_command(TARGET MyApp
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} 
    -D _CONFIG=$<CONFIG> 
    -D _DEST_PATH="$<TARGET_FILE_DIR:MyApp>"
    -P "${CMAKE_CURRENT_BINARY_DIR}/CopyLibsByConfig.cmake"
)

但解决方案在很大程度上取决于您要复制到二进制输出文件夹的文件。而且有很多方法可以做到,比如使用install()

install(FILES ${_LIBS_DEBUG} CONFIGURATIONS Debug DESTINATION $<TARGET_FILE_DIR:MyApp>)
install(FILES ${_LIBS_RELEASE} CONFIGURATIONS Release DESTINATION $<TARGET_FILE_DIR:MyApp>)

set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)

显然这不是install() 的使用方式,因此请考虑正确使用INSTALLPACKAGE 目标来分发您的应用程序及其所有依赖项。

如果我们谈论的是 Visual Studio 运行时 DLL,您很可能想看看 InstallRequiredSystemLibraries CMake 模块。

【讨论】:

  • 谢谢。这有帮助。我已经用 install + an installer 打包了我的应用程序。但是我现在的用例是将复制的库添加到目标 exe 文件夹中,以便在工作时支持正确的调试。所以自定义命令是正确的做法。
【解决方案2】:

其他解决方案是使用generator expression

例如,我有cppzmq(共享库)和cppzmq-static(具有静态依赖项的静态库)。我想要更快的调试构建,所以我在调试构建和(其他)例如使用cppzmq发布我想要一位大胖子。

target_link_libraries(CommunicationCommonLib PUBLIC
    $<IF:$<CONFIG:Debug>,cppzmq,cppzmq-static>
    Dexode::EventBus
    gcpp
    protobuf::libprotobuf
    )

【讨论】:

  • 我早就厌倦了所有这些杂耍。我切换到介子。无论如何感谢您的信息:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 2012-04-07
  • 1970-01-01
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多