我有一个需要dynamic链接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
?
除非通过$LD_LIBRARY_PATH
明确指向加载器,否则加载器从不检查当前目录中的共享对象。 有关更多详细信息,请参阅ld.so(8)
手册页。
虽然你可以设置LD_LIBRARY_PATH让dynamic链接器知道在哪里看,有更好的select。 您可以将共享库置于其中一个标准位置,请参阅/etc/ld.so.conf
(在Linux上)和/usr/bin/crle
(在Solaris上)以获取这些位置的列表
在构build二进制文件时,可以将-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"); }
hello.c中:
#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!
要从与您的可执行文件相同的目录加载共享对象,只需执行:
$ LD_LIBRARY_PATH=. ./binary
注意:它不会修改您的系统的LD_LIBRARY_PATHvariables。 改变只影响到这一点,只有这一点,执行你的程序。
对于那些还没有回答的人来说,我发现自己有以下的build议:
您可以尝试使用以下sudo ldconfig -v
更新ld.so.cache: sudo ldconfig -v
为我工作。