15

我正在将现有系统从 Windows 移植到 Linux。该构建由多个静态库构成。我遇到了一个链接错误,在 libB 的对象中找不到符号(在 libA 中定义)。链接器行看起来像

g++ test_obj.o -lA -lB -o 测试

问题当然是当链接器发现它需要来自 libA 的符号时,它已经通过了它,并且不会重新扫描,所以即使符号在那里,它也会简单地出错。

我最初的想法当然是简单地交换链接(到 -lB -lA),以便之后扫描 libA,并拾取 libA 中缺少的 libB 中的任何符号。但后来我发现 libA 和 libB 之间实际上存在递归依赖关系!我假设 Visual C++ 链接器以某种方式处理这个问题(默认情况下会重新扫描吗?)。

我考虑过的处理方法:

  • 使用共享对象。不幸的是,从需要 PIC 编译的角度来看,这是不可取的(这是对性能敏感的代码,丢失 %ebx 来保存 GOT 确实会受到伤害),并且不需要共享对象。

  • 构建一个所有对象的巨型 ar,避免问题。

  • 重构代码以避免递归依赖(这显然是正确的做法,但我正在尝试以最小的更改来完成此端口)。

你有其他想法来解决这个问题吗?有什么方法可以说服 binutils 链接器在缺少符号时重新扫描它已经查看过的库?

4

2 回答 2

19

只需这样做:

g++ test_obj.o -lA -lB -lA       -o test

当链接器在命令行读取第一个 libA 时,它会丢弃其中没有人依赖的对象/符号,例如 libB 需要但 test_obj.o 不需要的所有符号。所以你只需让它再次读取 libA,它也会拾取这些符号。

于 2010-04-29T15:01:45.160 回答
10

虽然@nos 提供了一个简单的解决方案,但当涉及多个库并且相互依赖更复杂时,它无法扩展。对问题进行梳理ld提供--start-group archives --end-group

在您的特定情况下:

g++ test_obj.o --start-group -lA -lB --end-group -o test
于 2013-02-13T21:44:33.753 回答