我有一个需要libtest.so动态链接的可执行文件,所以我将它们放在同一目录中,然后:
cd path_to_dir
./binary
Run Code Online (Sandbox Code Playgroud)
但是得到了这个:
error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
Run Code Online (Sandbox Code Playgroud)
它怎么可能找不到libtest.so与可执行文件本身在同一目录中的内容?
aut*_*iej 68
虽然您可以设置 LD_LIBRARY_PATH 以让动态链接器知道在哪里查找,但还有更好的选择。您可以将共享库放在标准位置之一,请参阅/etc/ld.so.conf(在 Linux 上)和/usr/bin/crle(在 Solaris 上)以获取这些位置的列表
您可以-R <path>在构建二进制文件时传递给链接器,它将添加<path>到为您的共享库扫描的目录列表中。这是一个例子。首先,显示问题:
libtest.h:
void hello_world(void);
Run Code Online (Sandbox Code Playgroud)
libtest.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
Run Code Online (Sandbox Code Playgroud)
你好ç:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
让我们运行它:
$ 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
Run Code Online (Sandbox Code Playgroud)
如何解决?添加-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!
Run Code Online (Sandbox Code Playgroud)
查看二进制文件,您可以看到它需要libtest.so.0:
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
Run Code Online (Sandbox Code Playgroud)
除了标准位置之外,二进制文件将在指定目录中查找其库:
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
Run Code Online (Sandbox Code Playgroud)
如果您希望二进制文件在当前目录中查找,您可以将 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!
Run Code Online (Sandbox Code Playgroud)
Ign*_*ams 34
加载程序从不检查共享对象的当前目录,除非它明确定向到 via $LD_LIBRARY_PATH。有关ld.so(8)更多详细信息,请参阅手册页。
小智 25
要从与可执行文件相同的目录加载共享对象,只需执行:
$ LD_LIBRARY_PATH=. ./binary
Run Code Online (Sandbox Code Playgroud)
注意:它不会修改您系统的 LD_LIBRARY_PATH 变量。更改仅影响此,且仅此,程序的执行。
小智 7
对于使用CMake进行构建的任何人,您可以将其设置CMAKE_EXE_LINKER_FLAGS为以下内容:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
Run Code Online (Sandbox Code Playgroud)
这将正确传播所有构建类型(例如,调试、发布等)的链接器标志,以首先在当前工作目录中查找 .so 文件。
| 归档时间: |
|
| 查看次数: |
95331 次 |
| 最近记录: |