我尝试使用 cmake + ninja + msvc 在 Windows 上构建一个相当大的共享库,它由子文件夹中的多个静态库组成。那么一个根CMakeLists.txt
好像:
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")
哪里的CMakeLists.txt
在子文件夹 staticlib1 和 staticlib2 中都看起来像:
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
)
当我跑步时cmake --build
staticlib1 和 staticlib2 构建都没有问题。凉爽的。但是当链接器尝试构建sharedlib时,cmake生成的rsp文件具有:
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
所以我收到链接器错误,因为符号被定义了两次。如何让 cmake 停止将对象和最终库添加到链接器 rsp?
从技术上讲,事后我不需要静态库。但是,我不能简单地切换到使用 OBJECT 库。实际项目有约 250 个静态库,包括约 3500 个目标文件。链接器仅保留一小部分目标文件就终止了(内存不足)。
我必须首先构建静态库,然后将它们链接到共享库中,以解决链接器的内存限制。我们当前的构建脚本很好地遵循了这种模式,所以我知道它是有效的。我只需要 cmake 遵循相同的模式。