我有一个项目,该项目以前是一组庞大的源文件,所有源文件都经过编译,然后链接为一个可执行文件。作为使项目更具模块化的第一步,我将构建分为几个较小的块,并将它们变成静态库。有一个层次结构,因此Exe1将链接到静态库Lib2A和Lib2B。 Lib2A将依赖于静态Lib3A,lib3B,lib3C等。此处的数字显示其在层次结构中的层。
问题是链接时我需要使用--whole-archive,否则找不到底层库中的某些符号。
当我为Exe1的链接添加以下内容时:
target_link_libraries(Exe1 -Wl,--whole-archive Lib2A Lib2B -Wl,--no-whole-archive)
最后我得到一个实际的链接阶段命令,例如:
g++ -o Exe1 -Wl,--whole-archive libLib2A.a libLib2B.a -Wl,--no-whole-archive libLib3A.a libLib3B.a libLib3C.a
不可避免地,一些第3层静态库中的符号会丢失,而我会丢失符号错误。
我希望因为Lib2A具有Lib3 *库作为依赖项,所以它们也将在链接器命令的--whole-archive部分内部,但它们将显示在外部。
我尝试了许多不同的组合(例如,将--whole-archive东西放在较低的层),但是还没有遇到使用CMake的方法。我在做什么错了?
谢谢
答案 0 :(得分:1)
作为上述答案的替代方法,我需要快速而又肮脏地查看添加整个归档目标标志(或将代码库转换为对象库...)的努力是否是正确的解决方案。通过遵循默认链接命令的CMake Source Code,我将项目的命令修改为:
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Wl,--start-group -Wl,--whole-archive <LINK_LIBRARIES> -Wl,--no-whole-archive -Wl,--end-group")
效果很好!虽然不是最佳解决方案,但至少会很快得到一些结果。
答案 1 :(得分:1)
以下内容对我有用。考虑两个库:
我们需要my_clib的完整档案,并有my_platform链接。
add_library(my_platform INTERFACE) # this could also be a regular library
add_library(my_clib STATIC)
target_sources(my_clib
PRIVATE
gcc_newlib_nano.c
gcc_newlib_nano_cpp.cc
)
# Link my_clib and any other libs
target_link_libraries(my_platform
INTERFACE
my_clib
)
# Ensure the whole archive is linked
target_link_options(my_platform
INTERFACE
-Wl,--whole-archive ${CMAKE_CURRENT_BINARY_DIR}/libmy_clib.a -Wl,--no-whole-archive
)
答案 2 :(得分:0)
对于3.12和更高版本的CMake,我将使用对象库。
我发现的早于该版本的解决方法是创建一个中间静态库,该库使用一些属性魔术将所有链接依赖项放在--whole-archive节中。对我而言,顶级静态库称为“源”。它实际上不包含任何内容,但是对其他静态库具有链接依赖性。我创建了“源组合”,如下所示:
add_library(source-combined STATIC "")
set_target_properties(source-combined PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(source-combined PUBLIC
--Wl,--whole-archive
$<TARGET_PROPERTY:source,INTERFACE_LINK_LIBRARIES>
-Wl,--no-whole-archive
)
现在,当我通过链接到这种源组合库来创建可执行文件或共享库时,我会得到--whole-archive和--no-whole-archive作为 entire 的书挡。静态库集,它们是“源”的链接依赖项。花了很长时间才偶然发现这项技术,所以我要分享它。