linux - 链接时 LD_LIBRARY_PATH 和 -L 有什么区别?

标签 linux gcc linker shared-libraries

我在链接时遇到了LD_LIBRARY_PATH的问题(这个问题与运行时无关)。

当我运行 make 时,链接行看起来像这样(这是一个使用 g++ 版本 4.1.x 的 Linux 系统):

g++ a.o b.o c.o -o myapp \
 -L/long/path/to/libs/ \
 -L/another/long/path/ \
 -labc -ldef -lghi

-l 选项引用存在于 -L 选项指定目录中的共享库(例如,libabc.so)。这些目录也出现在 LD_LIBRARY_PATH 中。通过该配置,链接成功,我可以运行该应用程序。

如果我从 LD_LIBRARY_PATH 中删除目录,那么我会得到一个错误行,例如:

/usr/bin/ld: cannot find -labc

另一方面,如果我从 -L 选项列表中删除目录,则会收到许多警告,例如:

/usr/bin/ld: warning: libabc.so, needed by /long/path/to/libs/libxyz.so,
    not found (try using -rpath or -rpath-link)

然后还有更多错误,例如:

/long/path/to/libs/libdef.so: undefined reference to `Foo::Bar<Baz>::junk(Fred*)'

谁能解释一下 LD_LIBRARY_PATH-L 之间的区别?我想深入了解这些东西,因此非常感谢引用!

此外,我必须向链接行添加什么才能避免使用 LD_LIBRARY_PATH

编辑:-L 中缺少目录时,编译器建议“尝试使用 -rpath 或 -rpath-link”。我认为我以前从未在 makefile 中看到过这些选项。你?不过不确定这是否有助于解决 LD_LIBRARY_PATH 问题。

最佳答案

这个问题有两个答案,部分答案在于编译时链接(即 gcc -lfoo -L/usr/lib ... 反过来调用 ld) 和运行时链接器查找。

当你编译你的程序时,编译器检查语法,然后链接器确保执行所需的符号存在(即变量/方法/等),等等。如前所述,LD_LIBRARY_PATH 具有改变 gcc/ld 行为方式以及运行方式的副作用 -时间链接器通过修改搜索路径来运行。

当您运行您的程序时,运行时链接器实际上获取共享库(在磁盘上或如果可能的话从内存中),并加载共享符号/代码/等。同样,LD_LIBRARY_PATH隐含地影响此搜索路径(如前所述,有时不是一件好事。)

在大多数 Linux 系统上不使用 LD_LIBRARY_PATH 的正确解决方法是将包含共享库的路径添加到 /etc/ld.so.conf(或在某些发行版中,在 /etc/ld.so.conf.d/ 中创建一个文件,其中包含路径)并运行 ldconfig (/sbin/ldconfig 作为 root) 来更新运行时链接器绑定(bind)缓存。

Debian 上的示例:

jewart@dorfl:~$ cat /etc/ld.so.conf.d/usrlocal.conf 
/usr/local/lib

然后当程序执行时,运行时链接器将在这些目录中查找您的二进制文件已链接到的库。

如果您想知道运行时链接器知道哪些库,您可以使用:

jewart@dorfl:~$ ldconfig -v 

/usr/lib:
libbfd-2.18.0.20080103.so -> libbfd-2.18.0.20080103.so
libkdb5.so.4 -> libkdb5.so.4.0
libXext.so.6 -> libXext.so.6.4.0

而且,如果您想知道一个二进制文件链接到哪些库,您可以像这样使用 ldd,它会告诉您您的运行时链接器将选择哪个库:

jewart@dorfl:~$ ldd /bin/ls
linux-vdso.so.1 =>  (0x00007fffda1ff000)
librt.so.1 => /lib/librt.so.1 (0x00007f5d2149b000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00007f5d2127f000)
libacl.so.1 => /lib/libacl.so.1 (0x00007f5d21077000)
libc.so.6 => /lib/libc.so.6 (0x00007f5d20d23000)

关于linux - 链接时 LD_LIBRARY_PATH 和 -L 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1904990/

相关文章:

c - 什么是 *ABS* 部分以及何时使用?

C 非阻塞键盘输入

linux - Bash 在远程上下文中使用之前在本地解析变量

linux - Makefile:需要执行的命令存储在一个列表中

C 字符串使用索引或指针复制字符

c++ - GCC 错误 : explicit specialization in non-namespace scope

c - 为什么我的输出错误? C新手

c - Visual Studio 无法在 32 位上链接,但可以在 64 位上链接

c++ - 在 Qt Creator 中使用静态库

linux - Linux 上的文件服务器