C++ Linux 可执行文件一直尝试使用不存在的库

C++ linux executable keeps trying to use library that does not exist

本文关键字:不存在 Linux 可执行文件 一直 C++      更新时间:2023-10-16

我正在尝试在Linux上使用GLFW编写一个简单的应用程序。现在主文件(唯一的文件)基本上只有几行代码,以确保动态库正确链接。在这里:

#include <GLFW/glfw3.h>
#include <iostream>
int main()
{
glfwInit();
std::cout << "It works this far!" << std::endl;
glfwTerminate();
}

包含文件存储在标记为"include"的目录中,库文件存储在标记为"lib"的目录中。截至目前,我正在使用以下行编译程序:

g++ -Wl,-Rlib -Iinclude -Llib test.cpp -o test -lglfw.3.2

它可以很好地编译和链接,但是当我尝试执行它时,我收到以下错误:

./test: error while loading shared libraries: libglfw.so.3: cannot open shared object file: No such file or directory

现在,在你急于否决这个问题并将其标记为重复之前,至少请允许我解释为什么我认为我的问题足够不同,不会重复。我已经尝试了其他问题提出的解决方案,但没有成功。如您所见,我尝试在与-Wl,-Rlib标签链接期间设置库的路径。我还尝试将LD_LIBRARY_PATH设置为指向我的库的位置("lib"文件夹),但它仍然抛出了相同的错误。(路径是相对的还是绝对的并不重要。

因此,我尝试的下一件事是在可执行文件上运行ldd命令。我得到了一些其他的依赖项,它们工作得很好,但重要的是,我得到了这个:

libglfw.so.3 => not found

出于某种原因,它坚持寻找libglfw.so.3.它不会有任何其他方式。将库从libglfw.3.2.so重命名为libglfw.so.3后,程序执行得很好,打印It works this far!好像根本没有问题。

为什么会这样?

出于某种原因,它坚持寻找libglfw.so.3。将库从 libglfw.3.2.so 重命名为 libglfw.so.3 后......

ELF 可执行文件包含所用动态库的确切名称。

如果可执行文件包含库名称"libglfw.so.3",则文件的名称必须完全按照这个方式命名。

文件命名方案有意以未将"完整"版本编码到文件名中的方式完成:这样,更高版本("libglfw.so.3.15")将与可执行文件一起使用。

通常应该有一个符号链接到已安装的最新版本的库:

libglfw.so.3->libglfw.so.3.2

您的计算机上似乎缺少此符号链接。我会说这是一个安装问题!

编辑

问题可能是:为什么存储在可执行文件中的文件名不是libglfw.3.2.so而是libglfw.so.3

答案与安装新版本库时的向后兼容性有关:

通常,您将使用开关-lglfw并查找名为libglfw.so的符号链接。

如果您将文件名libglfw.so存储在可执行文件中,并且安装了新的不兼容版本(libglfw.so.4),则没有机会通过安装两个版本的库来运行程序。

要通过安装两个版本的库来实现向后兼容性,库的"真实"符号链接名称(libglfw.so.3)必须存储在可执行文件中。

因此,库的"预期"文件名存储在库本身中:在文件libglfw.so.3.2中,您会发现文件希望自己存储为libglfw.so.3的一些信息。

链接器将使用有关文件名的此信息,因为它假定链接器开关(-lglfw)中给出的库名称不如存储在库本身中的名称"精确"。

出于某种原因,它坚持寻找libglfw.so.3。它不会有任何其他方式。

这是共享库的 Linux 约定,此处在其他地方进行了描述。 对于 Linuxlibfoo.so.x.y.z被认为具有与libfoo.so.x相同的 ABI。 通常,当安装共享库时(例如通过rpm,dpkg等),会发生ldconfig调用,以便刚刚安装的库具有遵循引用库的约定的符号链接。 此外,出于性能原因,这些库(如果安装到"受信任位置")将添加到链接器缓存中。

它可以很好地编译和链接,但是当我尝试执行它时,我收到以下错误:

./test:加载共享库时出错:libglfw.so.3:无法打开共享对象文件:没有这样的文件或目录

libglfw.so.3不在ld-linux.so的道路上。

如您所见,我尝试在与 -wl,-Rlib 链接期间设置库的路径

还是找不到——libglfw.so.3不在ld-linux.so的道路上。 您可以通过执行以下操作来添加它:

ldconfig -n /path/to/lib

这应该为您的库输出必要的libglfw.so.3符号链接。 IIRC 设置 rpath 可能需要完整路径。

我还尝试将LD_LIBRARY_PATH设置为指向我的库的位置

同样,libglfw.so.3不在ld-linux.so的道路上。