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

vngu2lb8  于 2023-08-05  发布在  Hive
关注(0)|答案(5)|浏览(264)

我有一个项目,曾经是一个巨大的源文件集,所有得到编译,然后链接为一个可执行文件。作为使项目更加模块化的第一步,我将构建分解为几个较小的块,并使它们成为静态库。有一个层次结构,所以Exe1将链接到静态库Lib2ALib2BLib2A将依赖于静态Lib3Alib3Blib3C等。这里的数字显示它们在层次结构中的层。
问题是我需要在链接时使用--whole-archive,否则找不到底层库中的一些符号。
当我添加下面的链接Exe1

target_link_libraries(Exe1 -Wl,--whole-archive Lib2A Lib2B -Wl,--no-whole-archive)

字符串
最后,我得到了一个实际的link stage命令,如下所示:

g++ -o Exe1 -Wl,--whole-archive libLib2A.a libLib2B.a -Wl,--no-whole-archive libLib3A.a libLib3B.a libLib3C.a


不可避免地,一些第3层静态库中的符号丢失了,我得到了丢失符号的错误。
因为Lib2ALib3*库作为依赖项,所以我希望它们也在链接器命令的--whole-archive部分的“内部”,但它们显示在外部。
我尝试了很多不同的组合(例如:将--whole-archive放在较低层),但还没有遇到使用CMake的方法。我做错了什么?
谢啦,谢啦

vh0rcniy

vh0rcniy1#

对于3.12和更新版本的CMake,我将使用对象库。
我为更早的版本找到的解决方法是创建一个中间静态库,它使用一些属性魔术将所有链接依赖项放置在--whole-archive部分中。对我来说,顶级静态库被称为“源代码”。它本身实际上什么都不包含,但它依赖于一堆其他静态库。我创建了'source-combined'如下:

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作为围绕整个静态库集的书挡,这些静态库是'source'的链接依赖项。我花了很长时间才偶然发现这个技术,所以我分享它。

6vl6ewon

6vl6ewon2#

以下为我工作。考虑两个库:

  • 我的平台
  • 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
)

字符串

czq61nw1

czq61nw13#

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

# Lib2A/CMakeLists.txt
    add_library(Lib2A OBJECT ${Lib2A_SRC})

个字符
它是可移植的,不需要使用链接器选项--whole-archive

64jmpszr

64jmpszr4#

作为上述答案的另一种选择,我需要得到一些快速和肮脏的东西,以查看添加整个归档目标标志(或将代码库转换为对象库...)的努力是否是正确的解决方案。通过遵循默认链接命令的CMake源代码,我修改了我的项目命令:

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")

字符串
它工作了一个治疗!虽然不是最好的解决方案,但至少会很快得到一些结果。

nom7f22z

nom7f22z5#

CMake 3.24添加了一个官方的方法来使用LINK_LIBRARY:WHOLE_ARCHIVE生成器表达式来完成此操作:

add_library(lib1 STATIC ...)
add_library(lib2 ...)
target_link_libraries(lib2 PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,lib1>")

字符串
也就是说,使用对象库通常是一种更简单的解决方案。这样,您所链接的库中的已编译目标文件列表就可以在最终的链接器命令中按原样使用,而不是首先创建静态库文件。

相关问题