为什么库的顺序有时会导致GCC的错误? [英] Why does the order in which libraries are linked sometimes cause errors in GCC?

查看:93
本文介绍了为什么库的顺序有时会导致GCC的错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么链接库的顺序有时会导致GCC错误?

Why does the order in which libraries are linked sometimes cause errors in GCC?

推荐答案

在这个答案获得更精致的文本,但我现在认为读者更容易看到真正的命令行)。

所有以下命令共享的公共文件

Common files shared by all below commands

$ cat a.cpp
extern int a;
int main() {
  return a;
}

$ cat b.cpp
extern int b;
int a = b;

$ cat d.cpp
int b;



链接到静态库



Linking to static libraries

$ g++ -c b.cpp -o b.o
$ ar cr libb.a b.o
$ g++ -c d.cpp -o d.o
$ ar cr libd.a d.o

$ g++ -L. -ld -lb a.cpp # wrong order
$ g++ -L. -lb -ld a.cpp # wrong order
$ g++ a.cpp -L. -ld -lb # wrong order
$ g++ a.cpp -L. -lb -ld # right order

链接器从左到右搜索并注释未解析的符号走。只有库解析该符号,它需要该库的目标文件来解析符号(在这种情况下b.o出于libb.a)。

The linker searches from left to right, and notes unresolved symbols as it go. Only a library resolves the symbol, it takes the object files of that library to resolve the symbol (b.o out of libb.a in this case).

静态库相对于彼此的依赖性相同 - 需要符号的库必须是第一个库,然后是解析符号的库。

Dependencies of static libraries against each other work the same - the library that needs symbols must be first, then the library that resolves the symbol.

如果一个静态库依赖于另一个库,而另一个库又依赖于前一个库,那么就有一个循环。您可以通过 - ( - )包含循环依赖库来解决此问题,例如 - (-la -lb - )(您可能需要转义括号,例如 -\( -\))。链接器然后多次搜索附带的lib以确保循环依赖性得到解决。或者,您可以多次指定库,因此每个都在前一个: -la -lb -la

If a static library depends on another library, but the other library again depends on the former library, there is a cycle. You can resolve this by enclosing the cycling dependent libraries by -( and -), such as -( -la -lb -) (you may need to escape the parens, such as -\( and -\)). The linker then searches those enclosed lib multiple times to ensure cycling dependencies are resolved. Alternatively, you can specify the libraries multiple times, so each is before one another: -la -lb -la.

$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -L. -ld -o libb.so # specifies its dependency!

$ g++ -L. -lb a.cpp # wrong order (works on some distributions)
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong order
$ g++ -Wl,--as-needed a.cpp -L. -lb # right order



这里是一样的 - 库必须遵循程序的目标文件。与静态库的区别在于,您不必关心库之间的依赖关系,因为动态库会整理出它们的依赖关系。

一些最近的发行版显然默认使用 - 根据需要的链接器标志,强制程序的对象文件在动态库之前。如果该标志通过,链接器将不链接到可执行文件实际上不需要的库(并且它从左到右检测这个库)。我最近的archlinux分发默认情况下不使用这个标志,所以没有给出一个错误,不按照正确的顺序。

Some recent distributions apparently default on using the --as-needed linker flag, which enforces that the program's object files come before the dynamic libraries. If that flag is passed, the linker will not link to libraries that are not actually needed by the executable (and it detects this from left to right). My recent archlinux distribution doesn't use this flag by default, so it didn't give an error for not following the correct order.

这是不正确的省略创建前者时, b.so d.so 的依赖。当链接 a 时,需要指定库,但 a 不需要整数 b 本身,因此不应该关心 b 自己的依赖关系。

It is not correct to omit the dependency of b.so against d.so when creating the former. You will be required to specify the library when linking a then, but a doesn't really need the integer b itself, so it should not be made to care about b's own dependencies.

这里是一个例子,如果你错过指定依赖关系 libb.so

Here is an example of the implications if you miss to specify the dependencies for libb.so

$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -o libb.so # wrong (but links)

$ g++ -L. -lb a.cpp # wrong, as above
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong, as above
$ g++ a.cpp -L. -lb # wrong, misses libd.so
$ g++ a.cpp -L. -ld -lb # wrong order (works on some distributions)
$ g++ -Wl,--as-needed a.cpp -L. -ld -lb # wrong order (like static libs)
$ g++ -Wl,--as-needed a.cpp -L. -lb -ld # "right"

如果现在查看二进制文件的依赖关系,二进制本身也取决于 libd ,而不仅仅是 libb 。如果 libb 稍后取决于另一个库,如果这样做,二进制将需要重新链接。如果有人在运行时使用 dlopen 加载 libb (想动态加载插件),调用将失败。所以right真的应该是错误 aswell。

If you now look into what dependencies the binary has, you note the binary itself depends also on libd, not just libb as it should. The binary will need to be relinked if libb later depends on another library, if you do it this way. And if someone else loads libb using dlopen at runtime (think of loading plugins dynamically), the call will fail aswell. So the "right" really should be a wrong aswell.

这篇关于为什么库的顺序有时会导致GCC的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆