我的目标是动态链接到来自 brew 的库。如何捆绑分发?
My target is dynamically linked against libraries from brew. How to bundle for distribution?
我构建了一个音频插件。我的目标是 .app
和 .component
.
我动态地 link 针对 brew 安装的库,libfluidsynth
。
我复制了libfluidsynth
到.app
/.component
.
我使用 install_name_tool
重新 link 二进制文件以指向捆绑的 libfluidsynth
.
libfluidsynth
依赖于 glib
, gthread
, intl
.
我将这些库复制到捆绑包中,重新linked libfluidsynth
以更喜欢捆绑副本。
我也对这些库及其依赖项做了同样的事情。
快速浏览一下它的样子:
ls /Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks
libfluidsynth.1.7.1.dylib
libglib-2.0.0.dylib
libgthread-2.0.0.dylib
libintl.8.dylib
libpcre.1.dylib
otool -L \
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/MacOS/juicysfplugin \
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/* \
| grep -vE '\t(/System/Library|/usr/lib)'
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/MacOS/juicysfplugin:
@executable_path/../Frameworks/libfluidsynth.1.7.1.dylib (compatibility version 1.0.0, current version 1.7.1)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libfluidsynth.1.7.1.dylib:
@loader_path/../Frameworks/libfluidsynth.1.dylib (compatibility version 1.0.0, current version 1.7.1)
@loader_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libglib-2.0.0.dylib:
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libgthread-2.0.0.dylib:
@loader_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libintl.8.dylib:
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libpcre.1.dylib:
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
这对 .app
非常有效。这里,看文件打开(opensnoop | grep 'dylib'
):
EXECNAME PATH
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/libfluidsynth.1.7.1.dylib
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/../Frameworks/libgthread-2.0.0.dylib
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/../Frameworks/libglib-2.0.0.dylib
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/../Frameworks/libintl.8.dylib
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/../Frameworks/../Frameworks/libpcre.1.dylib
.app
仅在其捆绑的 Frameworks 文件夹中查找动态库。完美。
然后我在我的 .component
目标上做了相同的副本并重新 links。 这没有用。
我将 .component
加载到音频插件主机中,并检查文件是否打开:
EXECNAME PATH
Plugin Host /Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/MacOS/juicysfplugin
Plugin Host /usr/local/lib/libfluidsynth.1.7.1.dylib
Plugin Host /usr/local/opt/glib/lib/libgthread-2.0.0.dylib
Plugin Host /usr/local/opt/glib/lib/libglib-2.0.0.dylib
Plugin Host /usr/local/opt/gettext/lib/libintl.8.dylib
Plugin Host /usr/local/opt/pcre/lib/libpcre.1.dylib
它正在寻找 /usr/local
下的图书馆。为什么?作为完整性检查,我使用 otool
来确认我确实 link 编辑正确:
otool -L \
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/MacOS/juicysfplugin \
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/* \
| grep -vE '\t(/System/Library|/usr/lib)'
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/MacOS/juicysfplugin:
@executable_path/../Frameworks/libfluidsynth.1.7.1.dylib (compatibility version 1.0.0, current version 1.7.1)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libfluidsynth.1.7.1.dylib:
@loader_path/../Frameworks/libfluidsynth.1.dylib (compatibility version 1.0.0, current version 1.7.1)
@loader_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libglib-2.0.0.dylib:
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libgthread-2.0.0.dylib:
@loader_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libintl.8.dylib:
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libpcre.1.dylib:
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
我认为我 link 编辑正确。我使用了完全相同的脚本(它是自动化和参数化的)。 我做错了什么?音频插件宿主如何知道在 /usr/local
下查找依赖项?为什么我的图书馆 links 被忽略了?
我已将二进制文件发布到:https://github.com/Birch-san/juicysfplugin/releases/tag/1.0.1
我重新link的脚本在这里:https://github.com/Birch-san/juicysfplugin/blob/master/Builds/MacOSX/relink-build-for-distribution.sh
.app
和 .component
目标使用方式的主要区别在于:
.app
是独立的
.component
是一个音频单元插件,您可以将其加载到 DAW/音频插件主机中。
那么,当父进程负责加载我们的可执行文件时,运行时依赖性解析可能会有所不同?
好的,我got it working。
macOS load-time 链接记录在 man dyld
。
问题是我告诉我的二进制文件查找与 @executable_path
相关的库。
这适用于 .app,因为 .app 的二进制文件是可执行文件。
但是对于我的 .vst 和 .component 插件,二进制文件被加载到不同的可执行文件中:音频插件主机。
因此,如果我们要查找与我们的 binary (juicysfplugin.component/Contents/MacOS/juicysfplugin
) 相关的库,我们需要使用 @loader_path
, 不是 @executable_path
.
现在,进入其他谜团……为什么 load-time 链接器忽略我的安装路径 (@executable_path/../Frameworks/libfluidsynth.1.7.1.dylib
),而是在 /usr/local/lib/libfluidsynth.1.7.1.dylib
下寻找 find fluidsynth?
因为DYLD_FALLBACK_LIBRARY_PATH
!
It is used as the default location for libraries not found in their install path. By default, it is set to $(HOME)/lib:/usr/local/lib:/lib:/usr/lib
.
我认为未能在安装路径中找到库。然后它在几个目录下查找叶文件名 — libfluidsynth.1.7.1.dylib
—,包括 /usr/local/lib
(成功)。
为什么我在 opensnoop 中没有看到失败的文件查找?可能它使用与 open
/open_nocancel
/open_extended
不同的系统调用。例如,文件上的 运行 stat
不会显示在 opensnoop 中。
也有可能 load-time 链接是由 dyld
进程完成的。 SIP 将不允许将 DTrace 附加到此进程。
我构建了一个音频插件。我的目标是 .app
和 .component
.
我动态地 link 针对 brew 安装的库,libfluidsynth
。
我复制了libfluidsynth
到.app
/.component
.
我使用 install_name_tool
重新 link 二进制文件以指向捆绑的 libfluidsynth
.
libfluidsynth
依赖于 glib
, gthread
, intl
.
我将这些库复制到捆绑包中,重新linked libfluidsynth
以更喜欢捆绑副本。
我也对这些库及其依赖项做了同样的事情。
快速浏览一下它的样子:
ls /Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks
libfluidsynth.1.7.1.dylib
libglib-2.0.0.dylib
libgthread-2.0.0.dylib
libintl.8.dylib
libpcre.1.dylib
otool -L \
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/MacOS/juicysfplugin \
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/* \
| grep -vE '\t(/System/Library|/usr/lib)'
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/MacOS/juicysfplugin:
@executable_path/../Frameworks/libfluidsynth.1.7.1.dylib (compatibility version 1.0.0, current version 1.7.1)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libfluidsynth.1.7.1.dylib:
@loader_path/../Frameworks/libfluidsynth.1.dylib (compatibility version 1.0.0, current version 1.7.1)
@loader_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libglib-2.0.0.dylib:
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libgthread-2.0.0.dylib:
@loader_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libintl.8.dylib:
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/git/juicysfplugin/Builds/MacOSX/build/Release/juicysfplugin.app/Contents/Frameworks/libpcre.1.dylib:
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
这对 .app
非常有效。这里,看文件打开(opensnoop | grep 'dylib'
):
EXECNAME PATH
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/libfluidsynth.1.7.1.dylib
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/../Frameworks/libgthread-2.0.0.dylib
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/../Frameworks/libglib-2.0.0.dylib
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/../Frameworks/libintl.8.dylib
juicysfplugin juicysfplugin.app/Contents/MacOS/../Frameworks/../Frameworks/../Frameworks/libpcre.1.dylib
.app
仅在其捆绑的 Frameworks 文件夹中查找动态库。完美。
然后我在我的 .component
目标上做了相同的副本并重新 links。 这没有用。
我将 .component
加载到音频插件主机中,并检查文件是否打开:
EXECNAME PATH
Plugin Host /Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/MacOS/juicysfplugin
Plugin Host /usr/local/lib/libfluidsynth.1.7.1.dylib
Plugin Host /usr/local/opt/glib/lib/libgthread-2.0.0.dylib
Plugin Host /usr/local/opt/glib/lib/libglib-2.0.0.dylib
Plugin Host /usr/local/opt/gettext/lib/libintl.8.dylib
Plugin Host /usr/local/opt/pcre/lib/libpcre.1.dylib
它正在寻找 /usr/local
下的图书馆。为什么?作为完整性检查,我使用 otool
来确认我确实 link 编辑正确:
otool -L \
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/MacOS/juicysfplugin \
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/* \
| grep -vE '\t(/System/Library|/usr/lib)'
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/MacOS/juicysfplugin:
@executable_path/../Frameworks/libfluidsynth.1.7.1.dylib (compatibility version 1.0.0, current version 1.7.1)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libfluidsynth.1.7.1.dylib:
@loader_path/../Frameworks/libfluidsynth.1.dylib (compatibility version 1.0.0, current version 1.7.1)
@loader_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libglib-2.0.0.dylib:
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libgthread-2.0.0.dylib:
@loader_path/../Frameworks/libgthread-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libglib-2.0.0.dylib (compatibility version 5401.0.0, current version 5401.3.0)
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libintl.8.dylib:
@loader_path/../Frameworks/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
/Users/me/Library/Audio/Plug-Ins/Components/juicysfplugin.component/Contents/Frameworks/libpcre.1.dylib:
@loader_path/../Frameworks/libpcre.1.dylib (compatibility version 4.0.0, current version 4.9.0)
我认为我 link 编辑正确。我使用了完全相同的脚本(它是自动化和参数化的)。 我做错了什么?音频插件宿主如何知道在 /usr/local
下查找依赖项?为什么我的图书馆 links 被忽略了?
我已将二进制文件发布到:https://github.com/Birch-san/juicysfplugin/releases/tag/1.0.1
我重新link的脚本在这里:https://github.com/Birch-san/juicysfplugin/blob/master/Builds/MacOSX/relink-build-for-distribution.sh
.app
和 .component
目标使用方式的主要区别在于:
.app
是独立的.component
是一个音频单元插件,您可以将其加载到 DAW/音频插件主机中。
那么,当父进程负责加载我们的可执行文件时,运行时依赖性解析可能会有所不同?
好的,我got it working。
macOS load-time 链接记录在 man dyld
。
问题是我告诉我的二进制文件查找与 @executable_path
相关的库。
这适用于 .app,因为 .app 的二进制文件是可执行文件。
但是对于我的 .vst 和 .component 插件,二进制文件被加载到不同的可执行文件中:音频插件主机。
因此,如果我们要查找与我们的 binary (juicysfplugin.component/Contents/MacOS/juicysfplugin
) 相关的库,我们需要使用 @loader_path
, 不是 @executable_path
.
现在,进入其他谜团……为什么 load-time 链接器忽略我的安装路径 (@executable_path/../Frameworks/libfluidsynth.1.7.1.dylib
),而是在 /usr/local/lib/libfluidsynth.1.7.1.dylib
下寻找 find fluidsynth?
因为DYLD_FALLBACK_LIBRARY_PATH
!
It is used as the default location for libraries not found in their install path. By default, it is set to
$(HOME)/lib:/usr/local/lib:/lib:/usr/lib
.
我认为未能在安装路径中找到库。然后它在几个目录下查找叶文件名 — libfluidsynth.1.7.1.dylib
—,包括 /usr/local/lib
(成功)。
为什么我在 opensnoop 中没有看到失败的文件查找?可能它使用与 open
/open_nocancel
/open_extended
不同的系统调用。例如,文件上的 运行 stat
不会显示在 opensnoop 中。
也有可能 load-time 链接是由 dyld
进程完成的。 SIP 将不允许将 DTrace 附加到此进程。