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

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

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

 g++ ao bo co -o myapp \ -L/long/path/to/libs/ \ -L/another/long/path/ \ -labc -ldef -lghi 

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

如果我从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丢失,编译器build议“尝试使用-rpath或-rpath-link”。 我不认为我曾经在makefile中看过这些选项。 你有吗? 不知道这是否会帮助LD_LIBRARY_PATH问题。

Solutions Collecting From Web of "链接时LD_LIBRARY_PATH和-L有什么区别?"

LD_LIBRARY_PATH的设置具有最高的优先级,所以当它被设置时, LD_LIBRARY_PATH提到的目录集甚至在标准集之前被搜索
的目录。 所以在你的情况下LD_LIBRARY_PATH设置正在影响查找
-l选项提到的库。 没有LD_LIBRARY_PATH一些依赖关系
可能已经从标准的目录集中解决了。

虽然设置LD_LIBRARY_PATH帮助调试,并尝试更新版本的
在通用开发环境设置和部署中使用它的库被认为是不好的。

另请参阅Linux文档中的HOWTO以获取有关共享库的更多详细信息

这个问题有两个答案,答案的一部分在于编译时链接(即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/创建一个文件/etc/ld.so.conf.d/的路径),并运行ldconfig/sbin/ldconfig作为root)来更新运行时链接程序绑定缓存。

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) 

LD_LIBRARY_PATH用于在运行应用程序时查找共享库。 这是一个副作用,它影响到你的链接,你不应该依靠这个。

作为一种常常不需要的副作用,LD_LIBRARY_PATH也将在链接(ld)阶段后用-L指定的目录(同样如果没有给出-L标记)搜索。

为什么LD_LIBRARY_PATH不好

如果我猜测,我会说链接器回退到使用LD_LIBRARY_PATH来解决您的直接链接(例如, libabc.solibdef.solibghi.so )动态链接的库。 查看ld的手册页,它看起来像使用-rpath构建的.so链接会影响动态绑定符号查找的工作方式。

检查g ++的人,我发现-lxxxxx选项是在提供的路径-L查找libxxxxx.a ,所以在链接时,只有.a文件将被加载。 在运行时,如果缺少一个库,那么只有库作为共享对象so .so将被加载,然后它将在LD_LIBRARY_PATH查找。 在我正在处理的可执行文件上,我看到在某个库目录中有libxxxx.alibxxxx.so版本,所以我认为这意味着库可以在链接时链接,或者在运行时链接为共享对象。

如果库仅作为共享对象存在,则意味着库路径在运行时需要LD_LIBRARY_PATH 。 如果一个库只作为一个存档的.a存在,那么就意味着它需要在可执行文件的构建中被链接,然后需要在编译时在g ++中提供-L directorypath和-lxxxxx

这是我的理解….至少它符合你的意见