我在链接时遇到了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/