将 --whole-archive 链接器选项与 CMake 和具有其他库依赖项的库一起使用

Ric*_*ehe 12 c++ g++ cmake

我有一个项目,它曾经是一组巨大的源文件,所有这些源文件都经过编译然后链接为一个可执行文件。作为使项目更加模块化的第一步,我将构建分解为几个更小的块,并使它们成为静态库。有一个层次结构,因此Exe1将链接到静态库Lib2ALib2B. Lib2A将取决于 static Lib3Alib3Blib3C等。此处的数字显示了它们在层次结构中的层。

问题是我需要--whole-archive在链接时使用,否则找不到底层库中的某些符号。

当我添加以下链接时Exe1

target_link_libraries(Exe1 -Wl,--whole-archive Lib2A Lib2B -Wl,--no-whole-archive)
Run Code Online (Sandbox Code Playgroud)

我最终得到了一个实际的链接阶段命令,例如:

g++ -o Exe1 -Wl,--whole-archive libLib2A.a libLib2B.a -Wl,--no-whole-archive libLib3A.a libLib3B.a libLib3C.a
Run Code Online (Sandbox Code Playgroud)

不可避免地,某些第 3 层静态库中的符号会丢失,并且会出现丢失符号错误。

我期望因为Lib2ALib3*库作为依赖项,所以它们也会--whole-archive在链接器命令的“内部”部分,但它们出现在外部。

我尝试了许多不同的组合(例如将--whole-archive东西放在较低层),但还没有遇到使用 CMake 的方法。我究竟做错了什么?

谢谢

Ric*_*ehe 15

对于 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
)
Run Code Online (Sandbox Code Playgroud)

现在,当我通过链接到这个源组合库来创建可执行文件或共享库时,我得到了 --whole-archive 和 --no-whole-archive 作为整个静态库集的书挡,这些静态库是'来源'。偶然发现这种技术花了很长时间,所以我正在分享它。

  • 可以使用有关 $&lt;TARGET_PROPERTY:source,INTERFACE_LINK_LIBRARIES&gt; 中“源”的更多信息。至少对我来说,没有足够的信息来了解如何进行这项工作。另外,在我的情况下,相关的(静态)库是在 CMake 之外构建的。 (2认同)

S.M*_*.M. 6

如果您需要使用链接器选项--whole-archive,那么您肯定应该使用对象库:

    # Lib2A/CMakeLists.txt
    add_library(Lib2A OBJECT ${Lib2A_SRC})
Run Code Online (Sandbox Code Playgroud)
    # Lib2B/CMakeLists.txt
    add_library(Lib2B OBJECT ${Lib2B_SRC})
Run Code Online (Sandbox Code Playgroud)

它是可移植的并且不需要使用链接器选项--whole-archive