Saturn

The devil is in the details.

0%

How to fix lib.so file not found problem

问题

在debug DAOS的过程中,gdb在执行可执行文件时,未能正确的加载libdaos的动态链接库。

什么是动态链接库

Linux中的共享库为程序提供了各种可重用函数。

假设我们想编写一个以压缩文件为输入的程序。为此,我们可以使用zlib等现有库,而不是自己实现解压缩函数。

程序在启动时加载共享库。

查看可执行文件使用了哪些动态链接库

1
2
3
4
5
6
7
8
9
10
11
$ ldd /usr/bin/clang
/usr/bin/clang:
linux-vdso.so.1 (0x00007ffd34a90000)
libclang-cpp.so.13 => /usr/bin/../lib/libclang-cpp.so.13 (0x00007f24c5a94000)
libLLVM-13.so => /usr/bin/../lib/libLLVM-13.so (0x00007f24c1548000)
libstdc++.so.6 => /usr/bin/../lib/libstdc++.so.6 (0x00007f24c12d6000)
libm.so.6 => /usr/bin/../lib/libm.so.6 (0x00007f24c11f8000)
libgcc_s.so.1 => /usr/bin/../lib/libgcc_s.so.1 (0x00007f24c11dd000)
libc.so.6 => /usr/bin/../lib/libc.so.6 (0x00007f24c0fc4000)
/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007f24c95d4000)
libz.so.1 => /usr/bin/../lib/../lib/libz.so.1 (0x00007f24c0fad000)

查找未能找到的库

1
2
3
4
5
$ apt search zstd
Sorting... Done
Full Text Search... Done
zstd/stable 1.5.0 aarch64
Zstandard compression.

LD_LIBRARY_PATH 环境变量

我们可以指定在LD_LIBRARY_PATH环境变量中搜索共享库的目录。

LD_LIBRARY_PATH是一个冒号分隔的目录列表,就像PATH变量一样。

默认搜索路径通常仅限于/usr/lib和/usr/local/lib。

假设我们有一个链接到libfoo.so的程序,位于/home/baeldung/libs/libfoo.so,位于默认搜索路径之外。然后,我们可以使用此变量附加到搜索路径并解决问题。

首先,让我们使用ldd命令确认程序链接到的确切库:

1
2
3
4
5
6
7
8
$ ./program
./program: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
$ ldd ./program
./program:
linux-vdso.so.1 (0x00007ffce871b000)
libfoo.so => not found
libc.so.6 => /usr/lib/libc.so.6 (0x00007fdceadaf000)
/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007fdceafd3000)

现在,让我们将目录添加到LD_LIBRARY_PATH,并使我们的程序正常工作:

1
2
3
4
5
6
7
$ export LD_LIBRARY_PATH=/home/baeldung/libs
$ ldd ./program
./program:
linux-vdso.so.1 (0x00007ffe28dfd000)
libfoo.so => /home/baeldung/libs/libfoo.so (0x00007f8f0f7ba000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f8f0f59d000)
/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007f8f0f7c6000)

永久生效的配置

我们可以使用/etc/ld.so.conf文件永久设置库搜索路径。在这个文件中,我们指定了一个以换行符分隔的目录列表。

让我们再次修复libfoo.so错误:

1
2
3
4
5
6
7
8
9
10
11
$ ./program
./program: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
$ echo "/home/baeldung/libs" | sudo tee /etc/ld.so.conf
/home/baeldung/libs
$ sudo ldconfig
$ ldd ./program
./program:
linux-vdso.so.1 (0x00007ffefc3db000)
libfoo.so => /home/baeldung/libs/libfoo.so (0x00007f021e88d000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f021e674000)
/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007f021e89e000)

我们必须运行一次ldconfig命令,以使系统意识到新路径。

ldconfig 指令

我们可能最近安装了新的共享库或修改了共享库搜索路径。因此,我们需要运行ldconfig命令。

它更新链接器的缓存,使其了解新的共享库。

链接器称为ld.so,加载程序的共享库。

我们可以使用-p标志调用ldconfig来检查当前缓存:

1
2
3
4
5
6
7
8
9
10
$ ldconfig -p
347 libs found in cache `/etc/ld.so.cache'
libzstd.so.1 (libc6,x86-64) => /usr/lib/libzstd.so.1
libzstd.so (libc6,x86-64) => /usr/lib/libzstd.so
libz.so.1 (libc6,x86-64) => /usr/lib/libz.so.1
libz.so (libc6,x86-64) => /usr/lib/libz.so
libx265.so.199 (libc6,x86-64) => /usr/lib/libx265.so.199
libx265.so (libc6,x86-64) => /usr/lib/libx265.so
libx264.so.157 (libc6,x86-64) => /usr/lib/libx264.so.157
libx264.so (libc6,x86-64) => /usr/lib/libx264.so

在编译时设置库路径

如果我们可以访问程序的源代码,我们可以在链接过程中使用特殊标志编译它,以便找到共享库。

我们可以在运行时使用ld’s-rpath标志将库路径传递给动态链接器。

让我们编译一个基本程序并将其链接到我们的库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ pwd
/home/baeldung/libs
$ ls
libfoo.so
$ echo "int main() {}" > program.c # Dummy program
$ cc program.c libfoo.so # Link to our library
$ ./a.out
./a.out: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
$ ldd ./a.out
./a.out:
linux-vdso.so.1 (0x00007ffcbc1f8000)
libfoo.so => not found
libc.so.6 => /usr/lib/libc.so.6 (0x00007feb0ee04000)
/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007feb0f029000)

我们可以看到程序无法加载我们的共享库。

现在,让我们尝试使用-rpath标志编译它,将/home/baeldung/libs添加到库搜索路径中:

1
2
3
4
5
6
7
$ gcc program.c libfoo.so -Wl,-rpath=/home/baeldung/libs
$ ldd ./a.out
./a.out:
linux-vdso.so.1 (0x00007ffd0fbad000)
libfoo.so => /home/baeldung/libs/libfoo.so (0x00007fba09d99000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fba09b7b000)
/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007fba09da5000)

在这里,我们使用gcc的-Wl标志将参数传递给ld。

libdaos未找到的解决方案

1
echo "/home/kuhan/daos/build/release/gcc/src/client/api/" | sudo tee /etc/ld.so.conf

参考

https://www.baeldung.com/linux/solve-shared-object-error