简体   繁体   中英

How does CMake determine the fallback build configuration for target dependencies?

Background

On Windows, I use CMake (3.2.3) with Visual Studio 2015 (Community) to build a C++ project named Foo. Foo consists of a single shared library, named foo. I build and install Foo in both the Debug and Release configurations. I set CMAKE_DEBUG_POSTFIX to _d so that the installation of Foo contains both foo.dll and foo_d.dll , as well as CMake config files FooConfig.cmake , FooTargets.cmake , FooTargets-debug.cmake , and FooTargets-release.cmake .

Now, I start building a separate CMake project Bar, which consists of an executable 'bar', and which depends on the library foo. But I build bar in the RelWithDebInfo configuration. When I try to run bar from Visual Studio, it looks for foo_d.dll instead of foo.dll .

That is, the RelWithDebInfo configuration falls back onto the Debug configuration if a dependency does not exist under the RelWithDebInfo configuration.

Here is the CMakeLists.txt for Foo:

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)

Here is the CMakeLists.txt for Bar:

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

Question

How does CMake determine which configuration to fall back on for dependencies, if the desired configuration is unavailable for a dependency?

Followup: Is it possible to control this fallback? Ideally, there would be no fallback. I want CMake to give an error like "Cannot build bar in RelWithDebInfo configuration, because dependency foo is not available in that configuration (available configurations: Debug, Release).

Script FooConfig.cmake which is generated with Foo package provides IMPORTED library target foo , which is used by Bar for link with.

CMake has a notion about "Map from project configuration to IMPORTED target's configuration.", which is determined by properties MAP_IMPORTED_CONFIG_<CONFIG> :

Set this to the list of configurations of an imported target that may be used for the current project's configuration. Targets imported from another project may not provide the same set of configuration names available in the current project. Setting this property tells CMake what imported configurations are suitable for use when building the <CONFIG> configuration. The first configuration in the list found to be provided by the imported target is selected. If this property is set and no matching configurations are available, then the imported target is considered to be not found.

You may add to the end of script FooConfig.cmake.in something like

set_target_property(foo PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO "prohibited")

so it will be impossible to link with foo in RelWithDebInfo configuration (because foo target doesn't provide configuration named "prohibited").

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM