我的应用程序正在链接到位于 /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
, make
和 make 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/