【问题标题】:How does CMake determine the fallback build configuration for target dependencies?CMake 如何确定目标依赖项的后备构建配置?
【发布时间】:2017-02-23 01:58:38
【问题描述】:

背景

在 Windows 上,我使用 CMake (3.2.3) 和 Visual Studio 2015(社区)来构建一个名为 Foo 的 C++ 项目。 Foo 由一个名为 foo 的共享库组成。我在调试和发布配置中构建和安装 Foo。我将CMAKE_DEBUG_POSTFIX设置为_d,这样Foo的安装就包含foo.dllfoo_d.dll,以及CMake配置文件FooConfig.cmakeFooTargets.cmakeFooTargets-debug.cmakeFooTargets-release.cmake

现在,我开始构建一个单独的 CMake 项目 Bar,它由一个可执行的“bar”组成,并且依赖于库 foo。但是我在 RelWithDebInfo 配置中构建了 bar。当我尝试从 Visual Studio 运行 bar 时,它会查找 foo_d.dll 而不是 foo.dll

也就是说,如果 RelWithDebInfo 配置下不存在依赖项,则 RelWithDebInfo 配置会退回到 Debug 配置。

这是 Foo 的 CMakeLists.txt:

project(Foo)
cmake_minimum_required(VERSION 3.2.3)
add_library(foo SHARED foo.h foo.cpp)
install(TARGETS foo EXPORT FooTargets DESTINATION
    RUNTIME DESTINATION bin LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)
configure_package_config_file(FooConfig.cmake.in
    "${CMAKE_BINARY_DIR}/FooConfigToInstall.cmake"
    INSTALL_DESTINATION cmake)
install(FILES ${CMAKE_BINARY_DIR}/FooConfigToInstall.cmake"
        DESTINATION cmake RENAME FooConfig.cmake)
install(EXPORT FooTargets DESTINATION cmake)

这是 Bar 的 CMakeLists.txt:

project(Bar)
cmake_minimum_required(VERSION 3.2.3)
find_package(Foo)
add_executable(bar bar.cpp)
target_link_libraries(bar foo)

问题

如果所需的配置对依赖项不可用,CMake 如何确定依赖项依赖哪个配置?

跟进:是否有可能控制这种回退?理想情况下,不会有回退。我希望 CMake 给出一个错误,例如“无法在 RelWithDebInfo 配置中构建栏,因为依赖项 foo 在该配置中不可用(可用配置:调试、发布)。

【问题讨论】:

  • 请提供一些代码。目前还不清楚FooBar 项目是如何相关的——一个是包含另一个,还是你独立构建它们。您如何准确地bar 可执行文件与foo 库链接起来?
  • 我分别构建 Foo 和 Bar。我会添加更多细节。
  • 我现在在原帖中添加了更多细节。

标签: c++ visual-studio dll cmake


【解决方案1】:

使用Foo包生成的脚本FooConfig.cmake提供了IMPORTED库目标fooBar用于链接。

CMake 有一个关于“从项目配置映射到 IMPORTED 目标的配置”的概念,这是由属性MAP_IMPORTED_CONFIG_<CONFIG> 确定的:

将此设置为可用于当前项目配置的导入目标的配置列表。从另一个项目导入的目标可能不会提供当前项目中可用的相同配置名称集。设置此属性会告诉 CMake 在构建 配置时适合使用哪些导入的配置。列表中找到的由导入的目标提供的第一个配置被选中。如果设置了该属性并且没有可用的匹配配置,则认为未找到导入的目标。

您可以在脚本末尾添加FooConfig.cmake.in 之类的内容

set_target_property(foo PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO "prohibited")

因此在 RelWithDebInfo 配置中无法与 foo 链接(因为 foo 目标不提供名为“禁止”的配置)。

【讨论】:

  • 太棒了!这正是我想要的。顺便说一句,你是如何发现关于 CMake 的呢?您只是在 Sphinx 网站上搜索框吗?
  • 澄清一下,我想我想做一些不同的事情:set_target_property(bar PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo)
  • how do you discover things like that about CMake? - 我前段时间偶然发现了这个属性。知道包的导出机制我只是记得它。您确定该属性应该应用于可执行文件,而不是吗? (我没有测试过,但你的解释看起来很合理)。如果是这样,您可能会考虑设置 variable MAP_IMPORTED_CONFIG_RELWITHDEBINFO:它为 所有目标 上的属性提供默认值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多