RPATH未能扩展

时间:2014-03-07 21:51:55

标签: macos dyld rpath

我在OS X上构建了一个总是无法加载的可执行文件(名为demux),我找不到原因:

$ ./demux
RPATH failed to expanding     @rpath/sfeMovie.framework/Versions/2.0/sfeMovie to: @executable_path/sfeMovie.framework/Versions/2.0/sfeMovie
dyld: Library not loaded: @rpath/sfeMovie.framework/Versions/2.0/sfeMovie
  Referenced from: …current_dir/./demux

框架紧挨着可执行文件。 Otool显示以下内容:

$ otool -L sfeMovie.framework/Versions/2.0/sfeMovie 
sfeMovie.framework/Versions/2.0/sfeMovie:
@rpath/sfeMovie.framework/Versions/2.0/sfeMovie (compatibility version 2.0.0, current version 2.0.0)

$ otool -L demux 
demux:
@rpath/sfeMovie.framework/Versions/2.0/sfeMovie (compatibility version 2.0.0, current version 2.0.0)

鉴于此,我认为将@executable_path添加到可执行文件的运行时搜索路径将允许它查看任何框架和库,其相对安装名称仅以@rpath为前缀(如@ rpath / sfeMovie.framework / ...)和可执行文件旁边的。要确保此运行时搜索路径正确无误:

$ otool -l demux | grep LC_RPATH -A 2
      cmd LC_RPATH
  cmdsize 32
     path @executable_path (offset 12)

但这失败了,我不知道为什么。对我来说@ executable_path / sfeMovie.framework / Versions / 2.0 / sfeMovie看起来是正确的路径,但它仍然失败...是否有误用@rpath或@executable_path?

2 个答案:

答案 0 :(得分:4)

我能够通过快速测试项目重现您的问题。当我在LD_RUNPATH_SEARCH_PATH构建设置中附加一个尾部斜杠时修复了它。

而不是:

@executable_path

你应该试试

@executable_path/

otool -l的输出现在看起来像这样:

      cmd LC_RPATH
  cmdsize 32
     path @executable_path/ (offset 12)

通常,您可以使用我的dyld分析器脚本在https://github.com/liyanage/macosx-shell-scripts/blob/master/checklibs.py

检查您的顶级可执行文件(在本例中为“demux”)
./checklibs.py demux

此工具试图忠实地再现dyld的分辨率逻辑。它通常可以提供有关哪些引用不起作用的提示,但在这种情况下,它不会捕获缺少尾部斜杠的问题。我会相应地更新它以匹配dyld的行为。

答案 1 :(得分:0)

demux包含@rpath链接,RPATH包含@executable_path,但dyld man page表示,“您甚至可以添加LC_RPATH加载命令路径以@loader_path开头,这似乎意味着RPATH中不允许@executable_path

如果demux直接包含@executable_path而不是间接到RPATH,那么它就会有效。

有关详细信息,请参阅man dylddyld.cpp

如果是demux.c

#include <stdio.h>

int foo();

int main() {
    printf("%d\n", foo());
}

这是lib/sfeMovie.c

int foo() {
    return 42;
}

这是您的Makefile

run:
        $(MAKE) clean
        $(MAKE) demux
        cd .. && "$(shell pwd -P)/demux"

demux: demux.o lib/sfeMovie.dylib
        cc -o $@ $^
        install_name_tool \
            -change \
                'lib/sfeMovie.dylib' \
                 '@executable_path/lib/sfeMovie.dylib' \
            $@

lib/sfeMovie.dylib: lib/sfeMovie.o
        cc -shared -o $@ $<

clean::
        rm -f demux *.o lib/*.o lib/*.dylib

然后demux正确加载库,即使当前目录不是包含demux的目录。但是,如果sfeMovie引用了许多其他库,那么您可能仍需要RPATH。