我该如何指定dylib中的rpath?

4
我有一个名为libfoo.dylib的库。问题在以下命令中说明:
$ install_name_tool -id "@rpath/libfoo.dylib" libfoo.dylib
$ install_name_tool -add_rpath "@executable_path/" libfoo.dylib
$ gcc -o foo foo.c -lfoo
$ ./foo #<==== 我希望这个命令能够运行
dyld: Library not loaded: @rpath/libfoo.dylib
  Referenced from: ~/./foo
  Reason: image not found
$ install_name_tool -add_rpath "@executable_path/" foo #<=== 我不想在这里指定查找库的位置
$ ./foo
Hello World
如何实现目标,即不必在可执行文件编译时指定库的位置?

我认为你需要使用-headerpad_max_install_names编译和链接libfoo.dylib,以确保有足够的空间添加你正在尝试添加的名称。一旦libfoo.dylib有了它的安装名称,那么无论程序的位置在哪里,foo都将能够链接到它。 - jww
2个回答

2
我必须承认,我有点困惑你想要实现什么。使用runpath搜索路径的整个目的是当加载库的图像定义搜索路径时使用它们来加载库。你所要求的是让库定义可执行文件应该在哪里找到它。通过将dylib的安装名称设置为适当的值,可以在不使用runpath搜索路径的情况下完成此操作。根据您的特定示例,听起来您想将安装名称设置为类似于@loader_path/libfoo.dylib的内容。考虑以下与您的示例类似的内容:
$ cat a.c 
int a(void)
{
    return 1;
}
$ cc -install_name "@loader_path/liba.dylib" -dynamiclib -o liba.dylib a.c 
$ cat main.c
#include <stdio.h>

extern int a(void);

int main(int argc, char **argv)
{
    fprintf(stderr, "A: %d\n", a());
    return 0;
}
$ cc -L. -la -o main main.c
$ ./main
A: 1
$ 

这个库会通过设置其安装名称告诉链接到它的可执行文件如何找到它,在链接可执行文件时不需要做任何特殊处理,以便在运行时找到该库。


是的,您的示例做到了我想要的(将库设置在应该找到而不是可执行文件中)。唯一的问题(也是我想使用rpath的原因)是我想指定3个搜索位置:/usr/lib../Framework/和像您展示的可执行文件路径。根据我的阅读,仅使用install_name无法实现这一点,对吗? - chacham15
如果您想指定多个位置,则需要使用运行路径搜索路径,因此可执行文件将指定要查找库的位置。请注意,如果无法在加载命令引用的位置找到库,则默认情况下将搜索/usr/lib,因此可能不必显式引用该位置。 - bdash

-1

你需要做的就是告诉链接器在你的二进制文件中添加rpath。实际上,你可以通过以下方式告诉gcc来告诉链接器:

$ gcc -o foo foo.c -lfoo -Wl,-rpath=/some/path

现在如果你使用objdump来查看里面的内容:

$ objdump -x ./foo | less

Dynamic Section 下,您会看到类似于 RPATH /some/path 的内容。

如果每次都要输入相同的 -Wl,-rpath=... 太麻烦了,ld 接受 @file 选项(我不知道 dyld 是否也接受):

$ echo "-rpath=/some/path" > ./ld-options
$ gcc ./foo.c -o foo -Wl,@ld-options

1
我想我应该再解释一下,我的情况是有很多可执行文件需要编译,但只有一个库文件。我希望将构建可执行文件的命令保持在1行范围内,以便更容易查看警告信息。为每个可执行文件编译命令添加“rpath = ...”会使命令变得非常长,并超过1行标记。这更多是出于方便而非必要性的考虑。 - chacham15
没有起作用,所以我尝试了原始的方式:ld: unknown option: -rpath=@executable_path/ - chacham15
3
这些指令似乎适用于GCC和GNU binutils而不是OS X工具链。这就是为什么像“-Wl,-rpath=/foo”这样的选项会导致gcc报错。 - bdash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接