I built an audio plugin. I am targeting .app and .component .
I am dynamically linking to the brew -installed library, libfluidsynth .
I copied libfluidsynth to .app / .component .
I used install_name_tool to re-link the binary to point to the associated libfluidsynth .
libfluidsynth depends on glib , gthread , intl .
I copied these libraries into a package, re-linked libfluidsynth to prefer a bundled copy.
I also did the same for these libraries and their dependencies.
Here's a quick look at what it looks like:
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)
This worked great for .app . Here's a look at the file ( 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 only searches for dylib inside its packed Frameworks folder. Perfect.
Then I made the same copies and duplicate links to my .component target. This did not work.
I load .component into the host of the audio plugin and check if the file opens:
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
He is looking for libraries under /usr/local . What for? As a health check, I used otool to confirm that I really connected correctly:
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)
I thought I connected this correctly. I used the exact same script (it is automated and parameterized). What am I doing wrong? How is the host of the audio plugin for finding dependencies in /usr/local known? Why were my library links ignored?
I released binaries for: https://github.com/Birch-san/juicysfplugin/releases/tag/1.0.1
My relinking script is here: https://github.com/Birch-san/juicysfplugin/blob/master/Builds/MacOSX/relink-build-for-distribution.sh
The main difference between using .app and .component :
.app is standalone.component is an Audio Unit plugin that you load into the DAW / audio host module.
So, is it possible the resolution of the runtime dependency is different when the parent process is responsible for loading our executable?