Ninja Multi-Config sets up wrong dependencies
If I configure my source tree using the Ninja Multi-Config generator, but have targets who's dependency list changes based on the configuration, the multi-config generator associates the wrong dependencies with targets.
cmake\3.22.1\bin\cmake.exe `
-G"Ninja Multi-Config" `
-S D:\builds\source `
-B D:\builds\cmake-build-w64 `
-DCMAKE_CROSS_CONFIGS="Release;Debug" `
-DCMAKE_DEFAULT_CONFIGS="Release;Debug" `
-DCMAKE_CONFIGURATION_TYPES="Release;Debug"
In my case, i have
- Debug: Library A -- built from source
- Release: Library A -- pre-built, imported as an import library
- Debug Exe B -- depends on Library A
- Release Exe B -- depends on Library A
What I'm seeing in the resulting build is that Debug-Exe-B depends on Debug-Library-A, and Release-Exe-B ALSO depends on Debug-Library-A
In this specific case, Library A happens to be OpenSSL (We don't use the OpenSSL build system, we wrote our own simplified cmakelists.txt for it, and that works 100% fine, so it is definately not the cause of this problem)
In Debug builds, we want access to the code for debugging purposes, so developers can throw asserts and other customizations in during development.
In Release builds, however, we must link to the OpenSSL binary that comes with our operating system (Amazon Linux 2) because it is certified for Fips.
The two versions of OpenSSL are given their own CMakeLists.txt file, and we don't even add the other sub-directory when not using it.
E.g.
if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_subdirectory(openssl_amzn)
else()
add_subdirectory(openssl)
endif()
When I go and look at my impl-Release.ninja file, I see that even the binary-only version of the OpenSSL library has the same build rules as the build-from-source version!!! I see nothing in the impl-Release.ninja file about the prebuilt static library that it should depend on.
project(libcrypto)
add_library(${PROJECT_NAME} STATIC IMPORTED GLOBAL)
set_target_properties(${PROJECT_NAME} PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../../x86_64/usr/lib64/libcrypto.so.10"
)
target_include_directories(${PROJECT_NAME} SYSTEM INTERFACE ../../usr/include)
project(openssl CXX)
add_library(${PROJECT_NAME} SHARED)
target_sources(${PROJECT_NAME} PRIVATE stub.cpp)
ininbuild_target_link_targets(${PROJECT_NAME} PUBLIC libcrypto)
But instead of having only a call to compile stub.cpp, and then link to the on-filesystem libcrypto.so.10, i see the logic for building the other libcrypto from source, and no reference to x86_64/usr/lib64/libcrypto.so.10
In this way, the Ninja Multi-Config generator is completely ignoring explicit checks for the build configuration, and cannot be used in a very large number of CMake builds that do so.
Changing the order of config types in the cmake commandline has no apparent effect on the behavior.
When we build with the normal Ninja generator, one config at a time, we do not have this problem. It only effects the multi-config generator.