我正在尝试让 C 应用程序从相对目录加载共享对象,无论我从哪里调用它。到目前为止,只有当我调用它时与可执行文件位于同一目录中时,它才有效:
~/prog$ ./my_program
Success
~/prog$ cd ..
~$ ./prog/my_program
./prog/my_program: error while loading shared libraries: libs/libmysharedobject.so: cannot open shared object file: No such file or directory
从上面的输出可以猜到,共享对象存储在该~/prog/libs/
目录下。以下是相关 gcc 调用的样子:
gcc -std=c99 -ggdb -Wall -pedantic -Isrc
-fPIC -shared -Wl,-soname,libs/libmysharedogbject.so
-o libs/libmysharedobject.so libs/mysharedobject.c
[...]
gcc [CFLAGS omitted] -o my_program main.c
build/src/my_program.o build/src/common.o
-lm -Llibs -lmysharedobject
这是输出的顶部readelf -d my_program
:
Dynamic section at offset 0x6660 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libs/libmysharedobject.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
我尝试添加-Wl,-z,origin,-rpath='$ORIGIN'
,这会导致以下几行显示在readelf
的输出中:
0x000000000000000f (RPATH) Library rpath: [$ORIGIN]
[...]
0x000000006ffffffb (FLAGS_1) Flags: ORIGIN
但这似乎并不能解决我的问题。我也尝试过设置rpath
为$ORIGIN/libs
、.
、 和./libs
,但均无济于事。 (更新:$(CURDIR)
也没有任何效果。这让我感到惊讶,因为它扩展为绝对路径。)
有没有一种方法可以让我的可执行文件找到其共享对象,而不管调用它的目录如何,最好不需要最终用户LD_LIBRARY_PATH
每次都进行设置?或者我正在尝试做一些 Linux 不支持的事情?
答案1
将 rpath 设置为 $ORIGIN/libs 并将 soname 设置为 libsharedobject 而不是 libs/libsharedobject。我的 makefile 如下。
all: my_program
libs/libmysharedobject.so: Makefile success.c
gcc -fPIC -shared -Wl,-soname,libmysharedobject.so \
-o libs/libmysharedobject.so success.c
my_program: Makefile libs/libmysharedobject.so
gcc -o my_program main.c -Llibs -lmysharedobject -Wl,-R,'$$ORIGIN/libs'