OSX中动态链接优先级冲突?

18
在OSX系统中,不同的libjpeg动态库之间存在动态链接冲突。首先存在一个标准的本地libJPEG.dylib(位于/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/)。但是,如果您正在使用MacPorts,则还可以在/opt/local/lib中安装与端口相关的libjpeg.dylib。例如,后者可能已被安装为某些其他端口的依赖关系。 这会在链接到系统libJPEG(首选)时创建问题。然后,如果DYLD_LIBRARY_PATH中包含/opt/local/lib路径,则在搜索动态库时将优先考虑该路径,导致加载符号时出现运行时错误。
dyld: Symbol not found: __cg_jpeg_resync_to_restart
 Referenced from:
/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
 Expected in: /opt/local/lib/libJPEG.dylib
in /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
Trace/BPT trap: 5

所以我有两个问题(可能相关):

  1. 解决实际问题的好方法是什么(显然,从 DYLD_LIBRARY_PATH 中移除 /opt/local/lib 可以解决问题,但会给其他依赖项带来问题)?

  2. 其他哪些路径用于搜索动态库(即,“/System/Library”路径在哪里指定),为什么 DYLD_LIBRARY_PATH 在优先级方面排名更高?

6个回答

34

在使用OpenCV时,我在MacOS El Capitan上遇到了类似的问题。使用链接中的解决方案解决了问题。

解决方案是删除/usr/local/lib目录中的某些dlylib,并创建到相关文件/System/Library/Frameworks/ImageIO.framework/Resources/的符号链接。

cd /usr/local/lib
rm libgif.dylib
ln -s /System/Library/Frameworks/ImageIO.framework/Resources/libGIF.dylib libGIF.dylib
rm libjpeg.dylib
ln -s /System/Library/Frameworks/ImageIO.framework/Resources/libJPEG.dylib libJPEG.dylib
rm libtiff.dylib
ln -s /System/Library/Frameworks/ImageIO.framework/Resources/libTIFF.dylib libTIFF.dylib
rm libpng.dylib
ln -s /System/Library/Frameworks/ImageIO.framework/Resources/libPng.dylib libPng.dylib

2
救命啊!!!非常感谢。顺便说一下,在我的系统中,没有libgif.dylib需要删除。 - Diego Pamio
谢谢!libgif 已经在我的系统上了。 - kilojoules
2
这很危险。实际上,链接到该位置并期望使用由苹果提供的dylibs的macOS应用程序将会出现故障。 - jennykwan
答案中的链接已失效(请原谅俏皮话) - jtlz2
@jennykwan 非常危险 - 但有效 - 你有解决方案吗,特别是在*nix升级期间? - jtlz2
@mdemirst - 这个方法之前对我起过作用,但下次系统升级时可能会带来麻烦。 - jtlz2

12

不应使用DYLD_LIBRARY_PATH设置库路径。如您所发现的那样,这往往会导致问题。可执行文件和库应在链接时将其库需求内置于其中。使用otool -L查找文件正在寻找什么:

$ otool -L /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO:
    /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO (compatibility version 1.0.0, current version 1.0.0)
    ...
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

这是我自己编写的一个程序的例子:

$ otool -L /usr/local/bin/gifcolor
/usr/local/bin/gifcolor:
    /usr/local/Cellar/giflib/4.1.6/lib/libgif.4.dylib (compatibility version 6.0.0, current version 6.6.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)

注意它引用了/usr/local。如果您已经构建了它并引用了错误的库,我建议重新构建并将其指向正确的库。

如果这是不可能的,则可以使用install_name_tool编辑使用的路径,但有些情况下这样做无效,例如如果新路径比旧路径长,并且您没有使用-header_pad_max_install_names链接它。优先选择使用正确路径进行重建。

请注意,有一些“特殊”路径可用于相对于其加载器找到库。请参见@executable_path/及其在dyld(1)手册页面上的同类项。


谢谢您的回复。otoolinstall_name_tool确实很有用。我没有在链接时为所有库使用完整路径的原因是二进制文件将分发到没有brew或ports的系统上。我希望尽可能多地使用系统库,其余的库将与应用程序一起打包。但是,在开发过程中,目录结构看起来与已安装的应用程序不同,因此我使用相对路径链接非系统库(与要分发的版本相同),但在发布/打包之前,将/opt/local/添加到DYLD中。 - kamjagin
1
但是看起来正确的做法是尽量避免使用DYLD_LIBRARY_PATH。 - kamjagin
1
我还为需要特定树形结构的Mac系统可执行文件进行开发。我使用的解决方案是双重的:我在Xcode中使用INSTALL_PATHDSTROOTDEPLOYMENT_LOCATION安装到一个看起来像最终树形结构的树中。对于任何依赖相对路径(@executable_path)的内容,这已经足够了。对于需要绝对路径的内容,我在我的开发机上从“真实”的安装路径到我的Xcode DSTROOT建立了一个符号链接。 - Rob Napier

10
如果使用Qt Creator,则需要在Projects选项卡下的Run部分取消勾选Add build library search path to DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH选项:

qtcreator


2
谢谢您的回复,这对我帮助很大!我猜这个复选框是在最新版本的QtCreator中引入的。 - Steakfly
@Steakfly,很有趣,发帖后它也对我有所帮助。 - Iulian Onofrei

9

当我尝试在macOS Sierra上运行Apache Celix时,遇到了类似的错误。如果您使用Homebrew安装libjpeg、libtiff和libpng,则可能会混淆链接器使用macOS imageIO库。简单的解决方法是取消链接这些库:

brew unlink libpng
brew unlink libtiff
brew unlink libjpeg

重新链接这些库,每当我们需要时:
brew link libpng
brew link libtiff
brew link libjpeg

1
我在使用Qt Creator时遇到了这个问题。上述方法是一个好的解决方案,而且很容易撤销。如果您还遇到libgif的问题,您还需要执行brew unlink giflib - Albin Stigo
1
这比另一个答案建议的手动设置符号链接要好得多/更安全。 - ms611

3

我遇到了类似的错误,并通过将以下变量添加到我的bash_profile文件中解决了它:

export DYLD_LIBRARY_PATH=/usr/lib/:$DYLD_LIBRARY_PATH

0

我按照mdemirst建议的步骤操作,解决了我的问题。我正在使用OS X Sierra。

我创建了一个Gist,以防其他人遇到相同的问题。

修复Spidermonkey错误的Gist链接


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