为什么安装二进制文件后需要设置LD_LIBRARY_PATH?

时间:2019-08-05 10:14:56

标签: linux linker shared-libraries ld

我的应用程序链接到位于/usr/local/lib中的自编译Qt。

当我在构建目录中启动我的应用程序时,此方法工作正常。但是,在将我的应用程序安装到/usr/local/bin/之后,它尝试加载没有必需符号且不成功的不兼容系统Qt lib。

为什么?我的二进制文件的实际位置如何影响正在解决的Qt?

如果我使用LD_LIBRARY_PATH=/usr/local/lib启动我的应用,则它会按预期工作。

1 个答案:

答案 0 :(得分:2)

  

为什么安装二进制文件后需要设置LD_LIBRARY_PATH?

简单的答案是,这是系统架构师和工具链的失败。在Linux上,他们是维护Binutils和glibc的人。总体而言,维护人员认为可以针对一个版本的库进行编译和链接,然后针对错误版本的库进行运行或链接,或者丢失该库。他们确定这是第一个用例( q.v。)。事情开箱即用,您必须做一些特殊的事情才能进入良好状态。

考虑一下,我有一些Build Scripts可以构建和安装大约70个常见的Linux实用程序和库,例如cURL,Git,SSH和Wget。脚本将构建程序及其所有依赖项。有时我会尝试将它们用于安全测试和评估,例如Asan和UBsan。这个想法是在/usr/local中运行检测的程序和库,并检测未定义的行为,内存错误等。然后,将错误报告给项目。

尝试在Linux系统上运行已检测的构建是不可能的。例如,一旦使用工具构建了Bzip,iConv,Unicode,IDN,PRCE和其他几个密钥库,系统将不再起作用。 /usr/bin中的程序,例如/usr/bin/bash,将在/usr/local/lib中加载已检测的库。程序和库有很多错误,程序经常被杀死。您无法再运行脚本,因为/usr/bin中的程序使用了错误的库(并且bash之类的程序有很多错误)。

当然还有像您这样的问题,程序和库找不到自己的库。由于维护者的决定,网络上充满了屠杀。


要解决所构建程序的问题,请在LDFLAGS中添加以下内容:

-Wl,-R,/usr/local/lib -Wl,--enable-new-dtags

-R,/usr/local/lib告诉运行时链接程序在/usr/local/lib中查找其库。 --enable-new-dtags告诉链接器使用RUNPATH而不是RPATH

RUNPATH可以被LD_LIBRARY_PATH覆盖,而RPATH则不能。省略-Wl,--enable-new-dtags通常是一个坏主意。另请参见Use RPATH but not RUNPATH?

您还可以使用相对的运行时路径:

-Wl,-R,'$$ORIGIN/../lib' -Wl,--enable-new-dtags

-R,'$$ORIGIN/../lib'告诉运行时链接程序在../lib/中查找其库。假定您的二进制文件位于.../bin/中,因此../lib/会向上移动到lib/目录。

当您具有如下文件系统布局时,基于ORIGIN的链接器路径是很好的选择:

My_App
  |
  +-- bin
  |    |
  |    +- my_app.exe
  |
  +-- lib
  |    |
  |    +- my_lib.so
  |
  +-- share

您可以在文件系统中移动My_App文件夹,my_app.exe将始终能够找到其库my_lib.so。并且,如果My_App是根目录/,则它是发行版(即--prefix=/)使用的标准Linux文件系统。并且,如果My_App/usr/local,则它是用户(即--prefix=/usr/local)使用的标准Linux文件系统。

如果您使用configuremakemake test,则可以使用LD_LIBRARY_PATH设置用于测试的库的临时路径(例如.../My_App/lib) 。实际上,写得好的make test应该可以在测试期间为您做到这一点。


您无需添加-Wl,-R,/usr/local/lib -Wl,--enable-new-dtags,因为程序已编译并与/usr/local/lib中的库链接(大概使用-L<path>-l<lib>)。您必须这样做的原因是,维护人员不断重复犯同样的错误。这是完全的工程失败。

大约25年前,Linux架构师在决定要做什么时就警告这些路径问题。有两个阵营-一个希望开箱即用的东西,另一个想要用户做一些特殊的事情来使事情正常工作。后来赢得了辩论。他们选择了“让我们链接到错误的库”和“让我们丢失库”模式。希望我可以在讨论它的Usenet帖子中找到它,以便您自己阅读。