c - ld链接器在创建共享库时从静态库中删除目标文件

标签 c linux linker ld

我有许多静态库,我将它们链接到一个共享库中。其中一个,比如说 libUsefulFunc.a 包含一个目标文件 usefulFunc.o 和一个函数 usefulFunc() ,它只能从另一个静态库中使用,比如说 usingFunc(),驻留在 libUsingFunc.a 中托管的 usingFunc.c 中

问题是链接器丢弃了 usefulFunc.o 并且我得到错误“undefined reference”。我尝试了两种链接顺序。

我使用我能想到的最简单的文件重现了这种情况:

啊啊

extern int foo();

交流

#include "a.h"
int foo()
{
    return 13;
}

公元前

#include "a.h"

extern int b()
{
  return print("a = %d\n", foo());
}

构建一切:

gcc -c a.c -o a.o
gcc -c b.c -o b.o
ar q b.a b.o
ar q a.a a.o
ld -shared -o test.so ./b.a ./a.a
nm ./test.so 
00001034 A __bss_start
00001034 A _edata
00001034 A _end

如果我提供目标文件而不是存档:

ld -shared -o test.so ./a.o ./b.o
nm ./test.so 
00001220 a _DYNAMIC
00000000 a _GLOBAL_OFFSET_TABLE_
00001298 A __bss_start
00001298 A _edata
00001298 A _end
000001a0 T b
00000194 T foo
         U print

有没有办法在不必列出所有目标文件的情况下告诉链接器不要丢弃他认为未使用的目标文件?我知道有一个 --whole-archive 选项,但我将库构建为 Android NDK 项目的一部分,但没有找到为特定库传递此选项的方法。

更新 我已经完全理解我原来的问题并找到了正确的解决方案。首先是我上面的示例:链接器从入口点开始并搜索它们使用的所有符号。这些在当前库中查找。一旦找到,它就会将他们使用的符号添加到它的列表中,从而强制执行。这些库只处理一次,并按照它们在命令行中出现的顺序进行处理。因此,如果第二个库使用第一个库中的符号 - 该符号将保持未定义状态,因为链接器不会返回。所以在我的示例中,我应该告诉他 b() 将在外部调用,我可以使用 --undefined=b:

ld -shared -o test.so --undefined=b ./b.a ./a.a

在最初的问题中,我遇到了两个静态库之间的循环引用。 就好像我在 b 存档中有一个文件 b1.c,其中包含从 foo() 调用的函数 foo_b()。对于这种情况,我发现了 3 种可能的解决方案:

  1. 列出 b 两次:ld -shared -o test.so --undefined=b ./b.a ./a.a ./b.a
  2. 使用 --whole-archive
  3. 使用--start-group archives --end-group 选项。重复搜索指定的文件,直到没有新的 创建 undefined reference 。

对于 Android NDK 库,似乎只有第一个和第二个选项可用,因为 NDK 的 makefile 不提供指定存档组的方法

希望这对其他人也有用!

最佳答案

尝试使用 --whole-archive 选项:

ld -shared -o test.so --whole-archive ./a.a ./b.a

关于c - ld链接器在创建共享库时从静态库中删除目标文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14091669/

相关文章:

c - ST32 HAL SPI 从机中断溢出

c - 如何在 JavaScript 中保存指针并进一步检索

linux - 在 expect 脚本中运行 bash 脚本

linker - --unresolved-symbols=ignore-in-shared-libs 和 --allow-shlib-undefined 标志有什么区别

c++ - GNU C 和 C++ 链接错误

c - 如何查找是否设置了 MORE FRAGMENTS 字段?

c - 如何通过静态分析检测大量C代码中的内存泄漏(不使用任何工具)

linux - 我正在尝试使用 OR 运算符运行 if-elif 条件

python - anaconda3/bin/python : undefined symbol: archive_errno

c++ - 获取导致 g++ 中链接器错误的文件