Multi-config Generators generate wrong build scripts when sources for OBJECT libraries are generated and their names depend on $<CONFIG>
While investigation issue #21144 (closed) I realized that sometimes multi-config generators generate build-scripts which only work for the default CONFIG
type but fail for other configured CONFIG
types, because they try to link object-files that are not available for that specific CONFIG
.
This problem is very specific to and occurs with OBJECT
libraries and generated source files whose names depend on the $<CONFIG>
generator expression.
As examples are always easier to understand, here is the simple CMakeLists.txt
script that demonstrates the problem:
cmake_minimum_required(VERSION 3.18)
project(Test VERSION 1.0.0)
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_$<CONFIG>.cpp" CONTENT "// content")
add_library(test-obj OBJECT)
target_sources(test-obj PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/Generated_$<CONFIG>.cpp")
add_library(test-lib SHARED)
target_link_libraries(test-lib PRIVATE test-obj)
Note:
Instead of usingfile(GENERATE ...)
you could replace that line with the following,set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/Generated_$<CONFIG>.cpp" PROPERTIES GENERATED 1)
and create the source-files (
Generated_Debug.cpp
,Generated_Release.cpp
...) by hand in the build-directory before cmaking.
CMaking with a multi-config generator (e.g. Ninja Multi-Config
) succeeds without errors, as well as building the default CONFIG
(e.g. Debug
). But building another CONFIG
(e.g. Release
) fails:
$ cd /tmp/cmake-problem/build
$ make -G "Ninja Multi-Config" ../source/
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/cmake-problem/build
$ cmake --build . --config Debug
[2/2] Linking CXX shared library Debug/libtest-lib.so
$ cmake --build . --config Release
ninja: error: 'CMakeFiles/test-obj.dir/Release/Generated_Debug.cpp.o', needed by 'Release/libtest-lib.so', missing and no known rule to make it
Note, that ninja
is expecting the Generated_Debug.cpp.o
object-file in the Release
build directory when building Release
.
This cannot be correct!
This problem, however, only occurs with OBJECT
libraries. If I make target test-obj
a STATIC
library, this failure does not occur. (But I do not know if that static library was then built from the correct sources or not.)
This problem is not specific to the Ninja Multi-Config
generator, because I was able to reproduce it on Windows with the Visual Studio 16 2019
generator. The error-message then reads (translated from German):
LINK : fatal error LNK1181: Cannot open input file "...\cmake-problem\build\test-obj.dir\Release\Generated_Debug.obj". [...\cmake-problem\build\test-lib.vcxproj]