我正在寻找一种方法来允许可执行文件找到其共享库,但为了避免与可能使用同一共享库的不同版本的任何包发生冲突,我更喜欢将这些库保留在“私有路径”中(而不是/usr/lib)。
可能的方法似乎是:
- 在可执行文件中嵌入 rpath
- 启动可执行文件时设置 LD_LIBRARY_PATH
- 在 ld.so.conf.d 文件中的 ldconfig 配置中添加库路径
rpath 将目标结构链接到构建,ld.so.conf.d 配置系统路径,LD_LIBRARY_PATH 需要调用者进程知道它。
所以我想知道是否可以使用仅应用于可执行文件的 ld.so.conf.d (或类似的加载器配置)?
答案1
不容易。ld.so.conf
文件的格式非常简单:它们只是路径列表。
您可以通过使用不同的方式构建可执行文件来完成某些操作口译员;正常的值类似于/lib64/ld-linux-x86-64.so.2
1,它实际上负责执行动态链接。因此,您的自定义动态链接器可以查看不同的ld.so.conf
,或者执行任何操作。但这听起来比 rpath 差得多!
一个更简单的解决方案是包装器。将二进制文件安装为program.real
,或者更好的是,安装在/usr/local/lib/
某处(即不在$PATH
)。然后输入一个简单的 shell 脚本/usr/local/bin/program
:
#!/bin/sh
export LD_LIBRARY_PATH=/path/to/libs
exec /usr/local/lib/program/program.real
现在,您的库位置与构建无关,但调用程序不需要了解它。
1:快速查找系统上通常存在的内容的方法:readelf /bin/bash -p .interp
。尝试一些不同的可执行文件;您会发现至少 32 位和 64 位程序使用不同的程序。
答案2
可以使用相对 rpath 使用$ORIGIN
.
将可执行文件链接到-Wl,-rpath,'$ORIGIN/../lib'
允许可执行文件找到其安装的库:
- 可执行文件在
<base>/bin/
- 共享库位于
<base>/lib/
像这样继续操作,仅允许为这些可执行文件配置此链接,并且该<base>
目录可以位于任何位置。
答案3
filename
的参数可以dlopen
是绝对路径(以“ /
”开头)。
因此,将“私有路径”存储在配置文件中,并从中构建库的全名。或者,如果您知道私有库将与可执行文件位于同一目录中,请在可执行文件的路径上执行简单的字符串操作以找到它......
#include <dlfcn.h>
#include <unistd.h>
#include <string.h>
static int (*foo)();
/* ... */
char buf[BUFSIZ];
char *lastslash;
void *handle;
realpath(argv[0],buf);
lastslash = strrchr(buf,'/');
strcpy(lastslash,"foo." VERSION_BUILD ".so");
dlopen(buf,RTLD_LOCAL | RTLD_LAZY);
*(void **)(&foo) = dlsym(handle, "foo");
/* ... */
printf("%d\n",foo());