当我无法设置 `DYLD_LIBRARY_PATH` 时,如何在 macOS 上可移植地安装 ImageMagick?

How to install ImageMagick portably on macOS when I can't set `DYLD_LIBRARY_PATH`?

我正在为 macOS (Mojave) 开发一个命令行实用程序,它使用 ImageMagick 处理图像。我想将它作为一个独立的应用程序共享,这样其他人就可以开箱即用,而无需安装任何额外的动态库或框架。 Homebrew 和 MacPorts 版本的 ImageMagick 似乎是 "hardwired" 到 Mac 的系统目录结构(分别为 /usr/local/opt/local)很难(不可能?)将 ImageMagick 及其委托库放入可移植应用程序包中的方式。所以我改为直接使用 ImageMagick website.

的分布

我按照该页面上的安装说明进行操作,并将 ImageMagick 文件夹放在我的主目录中(位于 ~myname)。按照指示,我做了 export DYLD_LIBRARY_PATH="/Users/myname/ImageMagick-7.0.8/lib/"。但是当我 运行 magick 时,我收到一条错误消息:

$ ~myname/ImageMagick-7.0.8/bin/magick logo: test.jpg
dyld: Library not loaded: /ImageMagick-7.0.8/lib/libMagickCore-7.Q16HDRI.6.dylib
  Referenced from: /Users/myname/ImageMagick-7.0.8/bin/magick
  Reason: image not found
Abort trap: 6
$

很明显 magick 没有找到它的动态库,即使我按照说明设置了 DYLD_LIBRARY_PATH 也是如此。事实上,我什至无法将 DYLD_LIBRARY_PATH 导出到环境中:

$ export MAGICK_HOME="/Users/myname/ImageMagick-7.0.8"
$ export DYLD_LIBRARY_PATH="$MAGICK_HOME/lib/"
$ echo $DYLD_LIBRARY_PATH
/Users/myname/ImageMagick-7.0.8/lib
$ printenv | grep DYLD_LIBRARY_PATH
   # (nothing)
$ printenv | grep ImageMagick
MAGICK_HOME=/Users/myname/ImageMagick-7.0.8
$ 

这是怎么回事?如何让 ImageMagick 变得便携?

首先,目前ImageMagick网站上的IM版本(7.0.8版)是针对macOS High Sierra的。因此,您在 Mojave 上安装它时遇到问题也就不足为奇了。 (FWIW,当前的 Homebrew 版本(IM 7)和 MacPorts(IM 6)确实可以在 Mojave 上工作。但是,像你一样,我不知道如何使这些版本对代表的处理真正可移植。)

无法导出DYLD_LIBRARY_PATH是因为Apple的"System Integrity Protection" (SIP), which it added to newer versions of macOS (El Capitan and later). By default, SIP prohibits doing things like changing the env variable DYLD_LIBRARY_PATH. Although it is possible to disable SIP,Apple不建议这样做。

但是,您可以使用 install_name_tool 手动修改 magick 及其动态库,以便 IM 7.0.8 在 Mojave 上正常工作。方法如下(bash):

# magick: set the correct path to libMagickCore.dylib 
install_name_tool -change \
    /ImageMagick-7.0.8/lib/libMagickCore-7.Q16HDRI.6.dylib \
    @executable_path/../lib/libMagickCore-7.Q16HDRI.6.dylib \
    /Users/myname/ImageMagick-7.0.8/bin/magick

# magick: set the correct path to libMagickWand.dylib 
install_name_tool -change \
    /ImageMagick-7.0.8/lib/libMagickWand-7.Q16HDRI.6.dylib \
    @executable_path/../lib/libMagickWand-7.Q16HDRI.6.dylib \
    /Users/myname/ImageMagick-7.0.8/bin/magick

# libMagickWand.dylib: set the correct ID
install_name_tool -id \
    @executable_path/../lib/libMagickWand-7.Q16HDRI.6.dylib \
    /Users/myname/ImageMagick-7.0.8/lib/libMagickWand-7.Q16HDRI.6.dylib

# libMagickWand.dylib: set the correct path
install_name_tool -change \
    /ImageMagick-7.0.8/lib/libMagickCore-7.Q16HDRI.6.dylib \
    @executable_path/../lib/libMagickCore-7.Q16HDRI.6.dylib \
    /Users/myname/ImageMagick-7.0.8/lib/libMagickWand-7.Q16HDRI.6.dylib

# libMagickCore.dylib: set the correct ID
install_name_tool -id \
    @executable_path/../lib/libMagickCore-7.Q16HDRI.6.dylib \
    /Users/myname/ImageMagick-7.0.8/lib/libMagickCore-7.Q16HDRI.6.dylib

现在可以使用了:

$ /Users/myname/ImageMagick-7.0.8/bin/magick logo: test.jpg
$ open test.jpg
$ # (Preview opens a nice picture of the ImageMagick logo.)

这会修改相对于 magick 命令位置的动态库路径。只要您保持 ImageMagick 文件夹的目录结构不变,它现在应该是完全可移植的。

您可以轻松地将这五个 install_name_tools 命令放入一个 bash 小脚本中。我将把它留作 reader 的练习。 :)