![在与可执行文件相同的目录中找不到 .so 吗?](https://linux22.com/image/552081/%E5%9C%A8%E4%B8%8E%E5%8F%AF%E6%89%A7%E8%A1%8C%E6%96%87%E4%BB%B6%E7%9B%B8%E5%90%8C%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%AD%E6%89%BE%E4%B8%8D%E5%88%B0%20.so%20%E5%90%97%EF%BC%9F.png)
我有一个需要动态链接的可执行文件libtest.so
,因此我将它们放在同一个目录中,然后:
cd path_to_dir
./binary
但得到了这个:
error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
它怎么会找不到libtest.so
已经与可执行文件本身位于同一目录中的文件呢?
答案1
加载程序永远不会检查当前目录中的共享对象,除非通过 明确指定$LD_LIBRARY_PATH
。ld.so(8)
有关更多详细信息,请参阅手册页。
答案2
虽然您可以设置 LD_LIBRARY_PATH 让动态链接器知道在哪里查找,但还有更好的选择。您可以将共享库放在标准位置之一,请参阅/etc/ld.so.conf
(在 Linux 上)和/usr/bin/crle
(在 Solaris 上)以获取这些位置的列表
您可以-R <path>
在构建二进制文件时将其传递给链接器,这将添加<path>
到扫描共享库的目录列表中。以下是示例。首先,展示问题:
libtest.h:
void hello_world(void);
libtest.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
你好ç:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Makefile(必须使用制表符):
all: hello
hello: libtest.so.0
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o $@ $<
libtest.so.0.0.1: libtest.o
$(CC) -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
libtest.so.0: libtest.so.0.0.1
ln -s $< $@
clean:
rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0
让我们运行它:
$ make
cc -fPIC -c -o libtest.o libtest.c
cc -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
ln -s libtest.so.0.0.1 libtest.so.0
cc hello.c libtest.so.0 -o hello
$ ./hello
./hello: error while loading shared libraries: libtest.so.0: cannot open shared object file: No such file or directory
如何修复?添加-R <path>
到链接器标志(此处通过设置LDFLAGS
)。
$ make clean
(...)
$ make LDFLAGS="-Wl,-R -Wl,/home/maciej/src/tmp"
(...)
cc -Wl,-R -Wl,/home/maciej/src/tmp hello.c libtest.so.0 -o hello
$ ./hello
Hello world, I'm a library!
查看二进制文件,您可以发现它需要libtest.so.0
:
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
二进制文件将在标准位置之外,在指定目录中查找其库:
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
如果希望二进制文件位于当前目录中,可以将 RPATH 设置为$ORIGIN
。这有点棘手,因为您需要确保 make 不会解释美元符号。以下是其中一种方法:
$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
RPATH $ORIGIN
$ ./hello
Hello world, I'm a library!
答案3
要从与可执行文件相同的目录加载共享对象,只需执行:
$ LD_LIBRARY_PATH=. ./binary
注意:它不会修改系统的 LD_LIBRARY_PATH 变量。更改仅影响此程序的执行。
答案4
对于那些仍然苦苦挣扎却没有答案的人,我自己找到了一个答案,并提出了以下建议:
您可以尝试使用以下方法更新 ld.so.cache:sudo ldconfig -v
对我有用。