【问题标题】:Symbols from a static library are not exported while linking to a shared library链接到共享库时,不会导出静态库中的符号
【发布时间】:2020-04-16 22:01:02
【问题描述】:

共享库的代码是模块化的,由几个独立的单元组成。每个单元都内置在一个静态库中。


unit1.c

#include <stdio.h>

void HelloWorld() {
  printf("Hello World!\n");
}

unit2.c

#include <stdio.h>

void GoodbyeWorld() {
  printf("Goodbye World!\n");
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)

add_library(unit1 STATIC unit1.c)
target_compile_options(unit1 PRIVATE -fPIC)

add_library(unit2 STATIC unit2.c)
target_compile_options(unit2 PRIVATE -fPIC)

add_library(merged SHARED)
target_link_libraries(merged unit1 unit2)
set_target_properties(merged PROPERTIES LINKER_LANGUAGE C)

构建步骤:

cmake . && cmake --build .

libmerged.so 导出的符号:

$ nm -D --defined-only libmerged.so 
0000000000201020 B __bss_start
0000000000201020 D _edata
0000000000201028 B _end
00000000000005a0 T _fini
0000000000000458 T _init

Q 为什么符号HelloWorld 和GoodbyeWorld 没有导出?如何解决?

  • 我试过--version-script 没有成功。

    CMakeLists.txt 中的附加设置

    set_target_properties(merged PROPERTIES LINK_FLAGS -Wl,--version- 
    script=merged.version)
    

    合并的版本

    merged {
      global: HelloWorld; GoodbyeWorld;
      local: *;
    };
    
  • 还尝试强制加载静态库但未成功
    set_target_properties(merged PROPERTIES LINK_FLAGS -Wl,-force_load,libunit1.a)
    

【问题讨论】:

  • --whole-achive 是怎么回事?
  • 抱歉,打错了。选项是--whole-archive
  • @Tsyvarev 谢谢。 -Wl,-whole-archive libunit1.a libunit2.a -Wl,--no-whole-archive 解决了我的问题。现在正在考虑如何在 CMakeLists.txt 中执行此操作,因此将 -Wl,--no-whole-archive 附加到链接器命令,而不是前缀。
  • 只是谷歌,例如cmake "--whole-archive"。 Stack Overflow 上有很多关于这个主题的问题。 (但没有一个包含理想的解决方案)。

标签: c cmake clang


【解决方案1】:

您需要将--whole-archive 选项传递给链接器。 在 CMake 中,你可以这样做。

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)

add_library(unit1 STATIC unit1.c)
target_compile_options(unit1 PRIVATE -fPIC)

add_library(unit2 STATIC unit2.c)
target_compile_options(unit2 PRIVATE -fPIC)

add_library(merged SHARED)
set_target_properties(merged PROPERTIES LINKER_LANGUAGE C)
target_link_libraries(merged
        "-Wl,--whole-archive libunit1.a libunit2.a -Wl,--no-whole-archive"
        unit1 unit2
)

注意:target_link_libraries 命令也可用于指定链接器标志,而不仅仅是库名称。引号很重要,否则 CMake 可能会重新排列标志并删除重复项。

导出的符号

$ nm libmerged.so | grep " T "
000000000000065d T GoodbyeWorld
000000000000064a T HelloWorld
0000000000000670 T _fini
0000000000000520 T _init

为避免该问题,另一种选择是为unit1unit2 创建 OBJECT 库,而不是 STATIC 库。

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)

add_library(unit1 OBJECT unit1.c)
target_compile_options(unit1 PRIVATE -fPIC)

add_library(unit2 OBJECT unit2.c)
target_compile_options(unit2 PRIVATE -fPIC)

add_library(merged SHARED $<TARGET_OBJECTS:unit1> $<TARGET_OBJECTS:unit2>)
set_target_properties(merged PROPERTIES LINKER_LANGUAGE C)

【讨论】:

    猜你喜欢
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-09
    相关资源
    最近更新 更多