gcc嵌套依赖项上的共享库“未定义引用”

时间:2020-05-13 13:20:12

标签: c++ linker shared-libraries

g ++ 5.4.0

Ubuntu 16.04

我有几个共享库,这是它们的抽象:

libtest0.so: definition of `void foo()`
libtest1.so: `extern void foo()`, and not depends on libtest0.so
libtest2.so: use libtest1.so and depends on libtest1.so

现在我有一个二进制文件:

a.out: use libtest2.so

当然a.out具有未定义的符号foo()。为了解决这个问题,我尝试过:

g++ main.cc -L. -ltest2 -ltest0

因为libtest0.so具有foo()的定义。

但是,它不起作用:

$g++ -g main.cc -L. -ltest2 -ltest0
libtest1.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status

我的问题是:

  1. 为什么会发生这种“未定义引用”?
  2. 告诉链接器libtest0.so是否具有foo()定义的解决方案?

谢谢。

更新1:

如果我在编译libtest2时链接libtest0,则进行编译:

g++ -g main.cc -L. -ltest2

现在一切都很好。但是,在现实世界中,我无法更改libtest2.so的链接。

Update2

clang ++使用此cmd :(链接器是ld,不是lld)

# clang version 11.0.0
clang++ -g main.cc -L. -ltest2 -ltest0

Update3

一个例子是:https://gist.github.com/xgwang/da93edcc06542264157f600eb64bc082

只需在Linux上对其进行重击即可。在Ubuntu 16上进行了测试。

1 个答案:

答案 0 :(得分:2)

首先,引用here中的一个引号(强调是我的意思):

最终链接失败,未定义符号

这是使用--as-needed时最常见的错误。它发生在可执行文件的最后链接阶段(库不会造成问题,因为允许它们具有未定义的符号)。可执行链接阶段之所以消失,是因为在馈送到命令行的库之一中存在未定义的符号。但是,可执行文件本身未使用该库,因此它会被--as-needed删除。 这通常意味着一个库没有链接到另一个库,而是在使用它,然后依赖最终的可执行文件将它们链接在一起。对于使用该库的开发人员来说,这种行为也是一种额外的负担,因为他们必须检查要求。

一种解决方法,而不是

g++ main.cc -L. -ltest2 -ltest0

尝试

g++ main.cc -L. -ltest2 -Wl,--no-as-needed -ltest0

禁用--as-needed行为。

最适合我的最小示例:

#!/bin/bash

export LD_LIBRARY_PATH=.

g++ -fPIC -shared test0.cc -o libtest0.so
g++ -fPIC -shared test1.cc -o libtest1.so
g++ -fPIC -shared test2.cc -o libtest2.so -L. -ltest1

g++ main.cc -L. -ltest2 -Wl,--no-as-needed -ltest0