file(GET_RUNTIME_DEPENDENCIES) logic for `@loader_path` is incomplete
cmBinUtilsMacOSMachOLinker::ScanDependencies
assumes that the replacement for @loader_path
when resolving RPATHs is simply the parent directory of the library being scanned. However, if the library is embedded as part of a framework (as in /PREFIX/lib/QtGui.framework/Versions/Versions/5/QtGui
), the loader path should be the parent directory of the framework rather than the binary library file (should be /PREFIX/lib
but CMake sets loaderPath = /PREFIX/lib/QtGui.framework/Versions/Versions/5
). This causes libraries like Qt that load fine through dyld
to be rejected by CMake:
CMake Error at cmake_install.cmake:209 (file):
file Could not resolve runtime dependencies:
@rpath/QtCore.framework/Versions/5/QtCore
@rpath/QtGui.framework/Versions/5/QtGui
@rpath/QtWidgets.framework/Versions/5/QtWidgets
From the dyld
documentation:
@loader_path/
This variable is replaced with the path to the directory
containing the mach-o binary which contains the load command using
@loader_path. Thus, in every binary, @loader_path resolves to a
different path, whereas @executable_path always resolves to the
same path. @loader_path is useful as the load path for a
framework/dylib embedded in a plug-in, if the final file system
location of the plugin-in unknown (so absolute paths cannot be
used) or if the plug-in is used by multiple applications (so
@executable_path cannot be used). If the plug-in mach-o file is at
/some/path/Myfilter.plugin/Contents/MacOS/Myfilter and a framework
dylib file is at
/some/path/Myfilter.plugin/Contents/Frameworks/Foo.framework/Versions/A/Foo,
then the framework load path could be encoded as
@loader_path/../Frameworks/Foo.framework/Versions/A/Foo and the
Myfilter.plugin directory could be moved around in the file system
and dyld will still be able to load the embedded framework.
(I had to add a lot of debugging code to diagnose what libraries were failing and why... so it would be really nice to have some improved failure messages too ;) )