I've tried to build a rather large shared library on Windows with cmake + ninja + msvc, that is composed of multiple static libs from subfolders. So a root CMakeLists.txt
looks like:
project (sharedlib CXX)
include(${CMAKE_CURRENT_LIST_DIR}/staticlib1/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/staticlib2/CMakeLists.txt)
add_library(sharedlib SHARED)
target_link_libraries(sharedlib
staticlib1
staticlib2
)
set_target_properties(wux PROPERTIES LINK_FLAGS "/WHOLEARCHIVE")
Where the CMakeLists.txt
in sub-folders staticlib1 and staticlib2 both look something like:
add_library(staticlib1 STATIC)
target_sources(staticlib1 PUBLIC
${CMAKE_CURRENT_LIST_DIR}/sourceA.cpp
${CMAKE_CURRENT_LIST_DIR}/sourceB.cpp
)
target_include_directories(staticlib1 PUBLIC
${CMAKE_CURRENT_LIST_DIR}/inc
)
target_compile_options(staticlib1 PUBLIC
/flag1
/flag2
)
When I run cmake --build
both staticlib1 and staticlib2 get built no problem. Cool. But when the linker tries to build sharedlib, the cmake-generated rsp file has:
CMakeFiles\sharedlib.dir\staticlib1\sourceA.cpp.obj
CMakeFiles\sharedlib.dir\staticlib1\sourceB.cpp.obj
CMakeFiles\sharedlib.dir\staticlib2\sourceC.cpp.obj
CMakeFiles\sharedlib.dir\staticlib2\sourceD.cpp.obj
staticlib1.lib
staticlib2.lib
So I get linker errors because symbols are defined twice. How do I get cmake to stop adding both the objects and the final libs to the linker rsp?
Technically I don't need the static libs after the fact. However, I cannot simply switch to using OBJECT libraries. The actual project has ~250 static libs, comprising ~3500 object files. The linker dies (out of memory) with just a fraction of the object files.
I must build up the static libs first and then link just them into the shared lib after the fact, to get around the memory limitations of the linker. Our current build scripts follow this pattern just fine, so I know it works. I just need cmake to follow the same pattern.