在CMake中使用--whole-archive链接器选项,以及具有其他库依赖项的库

时间:2018-10-30 19:48:50

标签: c++ cmake g++

我有一个项目,该项目以前是一组庞大的源文件,所有源文件都经过编译,然后链接为一个可执行文件。作为使项目更具模块化的第一步,我将构建分为几个较小的块,并将它们变成静态库。有一个层次结构,因此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的方法。我在做什么错了?

谢谢

3 个答案:

答案 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_platform
  • my_clib

我们需要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 的书挡。静态库集,它们是“源”的链接依赖项。花了很长时间才偶然发现这项技术,所以我要分享它。