LD_LIBRARY_PATH和-L在链接时间的区别是什么?

时间:2022-03-23 13:21:31

I'm having problems with LD_LIBRARY_PATH at link time (this question has nothing to do with run time).

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

The link line looks like this when I run make (this is a Linux system using g++ version 4.1.x):

运行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

The -l options reference shared libraries (e.g., libabc.so) which exist in the directories specified by the -L options. Those directories also appear in LD_LIBRARY_PATH. With that configuration, the link is successful, and I can run the application.

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

If I remove the directories from LD_LIBRARY_PATH, then I get a single error line such as:

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

/usr/bin/ld: cannot find -labc

On the other hand, if I remove the directories from the list of -L options, then I get many warnings such as:

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

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

and then many more errors, such as:

还有更多的错误,比如:

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

Can someone explain the difference between LD_LIBRARY_PATH and -L? I would like to understand this stuff in depth, so references are greatly appreciated!

有人能解释一下LD_LIBRARY_PATH和-L之间的区别吗?我很想深入了解这个问题,所以非常感谢你的推荐!

Also, what do I have to add to the link line to avoid using LD_LIBRARY_PATH?

另外,为了避免使用LD_LIBRARY_PATH,需要向链接行添加什么?

EDIT: When directories were missing from -L, the compiler suggested to "try using -rpath or -rpath-link". I don't think I've ever seen those options in a makefile before. Have you? Not sure if that would help the LD_LIBRARY_PATH problem though.

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

5 个解决方案

#1


17  

The settings of LD_LIBRARY_PATH has the highest precedence, so when it is set, the set of directories mentioned by LD_LIBRARY_PATH are searched first even before the standard set
of directories. So in your case setting of LD_LIBRARY_PATH is influencing the lookup of
the libraries mentioned with -l option. Without LD_LIBRARY_PATH some of the dependencies
might have been resolved from the standard set of directories.

LD_LIBRARY_PATH的设置优先级最高,因此在设置时,甚至在标准目录集之前,首先搜索LD_LIBRARY_PATH提到的目录集。因此,在您的案例中,LD_LIBRARY_PATH的设置正在影响使用-l选项提到的库的查找。如果没有LD_LIBRARY_PATH,一些依赖项可能已经从标准目录集解析。

Though setting of LD_LIBRARY_PATH help with debugging and to try out a newer version of
a library its usage in the general development environment setup and deployment is considered bad.

虽然LD_LIBRARY_PATH的设置有助于调试,并尝试使用一个新版本的库,但它在总体开发环境设置和部署中的使用被认为是糟糕的。

Also refer this HOWTO from Linux Documentation for more details on Shared Libraries

关于共享库的更多细节,请参考Linux文档中的这个how

#2


30  

There are two answers to this question, part of the answer lies in the compile-time linking (i.e gcc -lfoo -L/usr/lib ... which in turn calls ld), and run-time linker lookups.

这个问题有两个答案,部分答案在于编译时链接(i)。e gcc -lfoo -L/usr/lib…然后调用ld)和运行时链接器查找。

When you compile your program, the compiler checks syntax, and then the linker ensures that the symbols required for execution exist (i.e variables / methods / etc), among other things. LD_LIBRARY_PATH, as has been noted, has the side-effect of altering the way gcc/ld behave as well as the way the the run-time linker behaves by modifying the search path.

编译程序时,编译器检查语法,然后链接器确保执行所需的符号存在(i)。除其他外,还有e变量/方法等。如前所述,LD_LIBRARY_PATH的副作用是修改gcc/ld的行为方式以及运行时链接器通过修改搜索路径的行为方式。

When you run your program, the run-time linker actually fetches the shared libraries (on disk or from memory if possible), and loads in the shared symbols / code / etc. Again, LD_LIBRARY_PATH affects this search path implicitly (sometimes not a good thing, as has been mentioned.)

当您运行您的程序时,运行时链接器实际上会从磁盘或内存中获取共享库,并装入共享符号/代码/等等。

The correct fix for this without using LD_LIBRARY_PATH on most Linux systems is to add the path that contains your shared libraries to /etc/ld.so.conf (or in some distributions, create a file in /etc/ld.so.conf.d/ with the path in it) and run ldconfig (/sbin/ldconfig as root) to update the runtime linker bindings cache.

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

Example on Debian:

在Debian的例子:

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

Then when the program is executed, the run-time linker will look in those directories for libraries that your binary has been linked against.

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

If you want to know what libraries the run-time linker knows about, you can use:

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

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

And, if you want to know what libraries a binary is linked against, you can use ldd like such, which will tell you which library your runtime linker is going to choose:

而且,如果你想知道二进制文件链接的库是什么,你可以使用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)

#3


8  

LD_LIBRARY_PATH is intended for finding shared libraries when running an application. It is a side effect that it's impacting your link, and you should not rely on that.

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

As an often unwanted side effect, LD_LIBRARY_PATH will also be searched at link (ld) stage after directories specified with -L (also if no -L flag is given).

作为一种通常不受欢迎的副作用,LD_LIBRARY_PATH也将在链接(ld)阶段中搜索,然后在用-L指定的目录中进行搜索(如果没有-L标志的话)。

Why LD_LIBRARY_PATH is bad

为什么LD_LIBRARY_PATH是不好的

#4


2  

If I were to guess, I would say that the linker is falling back to using LD_LIBRARY_PATH to resolve libraries that your direct links (e.g., libabc.so, libdef.so, and libghi.so) are dynamically linked against. Looking at the manual page for ld, it looks like linking against an .so that was built using -rpath would affect how the lookup of dynamically bound symbols works.

如果我猜的话,我会说链接器回到使用LD_LIBRARY_PATH来解析直接链接的库(例如libabc)。所以,libdef。所以,和libghi.so)是动态链接的对象。看一下ld的手动页面,它看起来像是链接到。so,使用-rpath构建的,会影响动态绑定符号的查找。

#5


1  

Checking the man for g++, I found out that -lxxxxx option is looking for libxxxxx.a in the provided path -L so at linking time , only .a file will be loaded. At run time, if a library is missing then only library as shared object so .so will be loaded and then it will look in LD_LIBRARY_PATH. On the executable I am working on , I see that in some library directory, there is the version libxxxx.a and libxxxx.so so I think it means that the library can be linked at the linking time or linked at the run time as a shared object.

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

If a library exists only as shared object , then it means that the library directory path needs to be LD_LIBRARY_PATH to be found at the run time. If a library exists only as an archived so .a , then it means that it needs to be linked at the build of the executable and then -L directorypath and -lxxxxx need to be provided at g++ at compilation time .

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

This is my understanding .... and at least it is in line with your observations

这是我的理解....至少它与你的观察一致。

#1


17  

The settings of LD_LIBRARY_PATH has the highest precedence, so when it is set, the set of directories mentioned by LD_LIBRARY_PATH are searched first even before the standard set
of directories. So in your case setting of LD_LIBRARY_PATH is influencing the lookup of
the libraries mentioned with -l option. Without LD_LIBRARY_PATH some of the dependencies
might have been resolved from the standard set of directories.

LD_LIBRARY_PATH的设置优先级最高,因此在设置时,甚至在标准目录集之前,首先搜索LD_LIBRARY_PATH提到的目录集。因此,在您的案例中,LD_LIBRARY_PATH的设置正在影响使用-l选项提到的库的查找。如果没有LD_LIBRARY_PATH,一些依赖项可能已经从标准目录集解析。

Though setting of LD_LIBRARY_PATH help with debugging and to try out a newer version of
a library its usage in the general development environment setup and deployment is considered bad.

虽然LD_LIBRARY_PATH的设置有助于调试,并尝试使用一个新版本的库,但它在总体开发环境设置和部署中的使用被认为是糟糕的。

Also refer this HOWTO from Linux Documentation for more details on Shared Libraries

关于共享库的更多细节,请参考Linux文档中的这个how

#2


30  

There are two answers to this question, part of the answer lies in the compile-time linking (i.e gcc -lfoo -L/usr/lib ... which in turn calls ld), and run-time linker lookups.

这个问题有两个答案,部分答案在于编译时链接(i)。e gcc -lfoo -L/usr/lib…然后调用ld)和运行时链接器查找。

When you compile your program, the compiler checks syntax, and then the linker ensures that the symbols required for execution exist (i.e variables / methods / etc), among other things. LD_LIBRARY_PATH, as has been noted, has the side-effect of altering the way gcc/ld behave as well as the way the the run-time linker behaves by modifying the search path.

编译程序时,编译器检查语法,然后链接器确保执行所需的符号存在(i)。除其他外,还有e变量/方法等。如前所述,LD_LIBRARY_PATH的副作用是修改gcc/ld的行为方式以及运行时链接器通过修改搜索路径的行为方式。

When you run your program, the run-time linker actually fetches the shared libraries (on disk or from memory if possible), and loads in the shared symbols / code / etc. Again, LD_LIBRARY_PATH affects this search path implicitly (sometimes not a good thing, as has been mentioned.)

当您运行您的程序时,运行时链接器实际上会从磁盘或内存中获取共享库,并装入共享符号/代码/等等。

The correct fix for this without using LD_LIBRARY_PATH on most Linux systems is to add the path that contains your shared libraries to /etc/ld.so.conf (or in some distributions, create a file in /etc/ld.so.conf.d/ with the path in it) and run ldconfig (/sbin/ldconfig as root) to update the runtime linker bindings cache.

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

Example on Debian:

在Debian的例子:

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

Then when the program is executed, the run-time linker will look in those directories for libraries that your binary has been linked against.

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

If you want to know what libraries the run-time linker knows about, you can use:

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

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

And, if you want to know what libraries a binary is linked against, you can use ldd like such, which will tell you which library your runtime linker is going to choose:

而且,如果你想知道二进制文件链接的库是什么,你可以使用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)

#3


8  

LD_LIBRARY_PATH is intended for finding shared libraries when running an application. It is a side effect that it's impacting your link, and you should not rely on that.

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

As an often unwanted side effect, LD_LIBRARY_PATH will also be searched at link (ld) stage after directories specified with -L (also if no -L flag is given).

作为一种通常不受欢迎的副作用,LD_LIBRARY_PATH也将在链接(ld)阶段中搜索,然后在用-L指定的目录中进行搜索(如果没有-L标志的话)。

Why LD_LIBRARY_PATH is bad

为什么LD_LIBRARY_PATH是不好的

#4


2  

If I were to guess, I would say that the linker is falling back to using LD_LIBRARY_PATH to resolve libraries that your direct links (e.g., libabc.so, libdef.so, and libghi.so) are dynamically linked against. Looking at the manual page for ld, it looks like linking against an .so that was built using -rpath would affect how the lookup of dynamically bound symbols works.

如果我猜的话,我会说链接器回到使用LD_LIBRARY_PATH来解析直接链接的库(例如libabc)。所以,libdef。所以,和libghi.so)是动态链接的对象。看一下ld的手动页面,它看起来像是链接到。so,使用-rpath构建的,会影响动态绑定符号的查找。

#5


1  

Checking the man for g++, I found out that -lxxxxx option is looking for libxxxxx.a in the provided path -L so at linking time , only .a file will be loaded. At run time, if a library is missing then only library as shared object so .so will be loaded and then it will look in LD_LIBRARY_PATH. On the executable I am working on , I see that in some library directory, there is the version libxxxx.a and libxxxx.so so I think it means that the library can be linked at the linking time or linked at the run time as a shared object.

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

If a library exists only as shared object , then it means that the library directory path needs to be LD_LIBRARY_PATH to be found at the run time. If a library exists only as an archived so .a , then it means that it needs to be linked at the build of the executable and then -L directorypath and -lxxxxx need to be provided at g++ at compilation time .

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

This is my understanding .... and at least it is in line with your observations

这是我的理解....至少它与你的观察一致。