加载相对于可执行路径的共享对象

加载相对于可执行路径的共享对象

我正在尝试让 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'

相关内容