简体   繁体   中英

stop cmake target_link_libraries linking both object files of static lib in addtion to the static lib itself

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.

This is the effect of target_sources command: with PUBLIC keyword it adds sources both for the library (static) and for anyone who links that library.

You should instead use PRIVATE keyword, or, better, add sources in the add_library call itself:

add_library(staticlib1 STATIC
    ${CMAKE_CURRENT_LIST_DIR}/sourceA.cpp
    ${CMAKE_CURRENT_LIST_DIR}/sourceB.cpp
)

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