linux - 为什么我需要在安装我的二进制文件后设置 LD_LIBRARY_PATH?

标签 linux linker shared-libraries ld

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

当我在构建目录中启动我的应用程序时,这工作正常。但是,在我将应用程序安装到 /usr/local/bin/ 之后它试图加载不兼容的系统 Qt 库,它没有所需的符号并失败。

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

如果我用 LD_LIBRARY_PATH=/usr/local/lib 启动我的应用程序它按预期工作。

最佳答案

Why do I need to set LD_LIBRARY_PATH after installing my binary?



简单的答案是,这是系统架构师和工具链的失败。在 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是根目录/ ,那么它是发行版使用的标准 Linux 文件系统(即 --prefix=/ )。如果 My_App/usr/local ,则它是用户使用的标准 Linux 文件系统(即 --prefix=/usr/local )。

如果您 configure , makemake 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 帖子,以便您自己阅读。

关于linux - 为什么我需要在安装我的二进制文件后设置 LD_LIBRARY_PATH?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57356509/

相关文章:

c++ - QSocketNotifier - 如何使用它来监视文件? - linux

linux - 分析非常长时间运行的任务

c++ - Boost 从 1.42 升级到 1.61

c - 链接器如何处理共享对象 (.so) 中的函数 main()?

java - 为什么我无法在运行 JAR 之前加载所需的库?

java - 创建和导入自定义 Spring 库,同时分离共享依赖项

linux - 如何下载一个 linux 镜像,解压并一次性写入 SD 卡?

Python subprocess.Popen "OSError: [Errno 12] Cannot allocate memory"

linux - 我的 Linux 可执行程序中的段 00 是什么(64 位)

c++ - Netbeans 7.1.1 中的 boost