3

我在 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?

4

2 回答 2

4

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

代替:

@executable_path

你应该试试

@executable_path/

现在的输出otool -l如下所示:

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

通常,您可以在https://github.com/liyanage/macosx-shell-scripts/blob/master/checklibs.py使用我的 dyld 分析器脚本检查您的顶级可执行文件(在本例中为“demux”)

./checklibs.py demux

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

于 2014-03-08T00:26:00.023 回答
0

demux包含一个@rpath链接,并且 RPATH 包含@executable_path,但是dyld 手册页说,“您甚至可以添加一个LC_RPATH以 开头的加载命令路径 @loader_path”,这似乎暗示@executable_pathRPATH 中不允许这样做。

如果demuxcontains@executable_path直接而不是间接 to 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。

于 2014-03-07T23:14:40.633 回答