How to embed a Framework in a Plugin in an App
This is not completely straightforward, or in other words it didn’t ran with the default Xcode setting straight out of the box.
So I set up a test app, that should look like this
Foo.app Frameworks A.framework B.framework Plugins C.plugin Frameworks D.framework
Where Foo links against A, and C links against B and D.
The frameworks being linked must have a @rpath prefix
DYLIB_INSTALL_NAME_BASE = @rpath. Otherwise the whole dyld search mechanism isn’t used. This value is used at link time to generate the proper
INSTALL_NAME for the shared library. Only with this set, will the loader at runtime get the idea to use
LD_RUNPATH_SEARCH_PATHS to search for it.
Remember that the INSTALL_NAME occurs in two places.
- In the executable of the Framework
- In the executable, that is linking this Framework.
The App searches @executable_path/../Frameworks
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks
This value is used at runtime. Since the app is always the “root”
@executable_path is correct.
@loader_pathfor Apps is the same as
@loader_pathwould be equally correct.
The Bundle searches @loader_path/../Frameworks
This should also work for frameworks, which embed other frameworks.
LD_RUNPATH_SEARCH_PATHS = $(inherited) @loader_path/../Frameworks
@loader_path is used for the frameworks embedded into the bundle. Interestingly the bundle
LD_RUNPATH_SEARCH_PATHS will be added to the Apps
LD_RUNPATH_SEARCH_PATHS, so it is neither necessary nor productive to specify
The value of
@loader_pathfor the Bundle will be different than that of the App. You can’t optimize the
LD_RUNPATH_SEARCH_PATHSsetting for the Bundle away.
$(inherited)is just a Xcode setting mechanism. The observed
LD_RUNPATH_SEARCH_PATHSinheritance behaviour is not due to $(inherited)
You can check out my test project yourself:
git clone https://www.mulle-kybernetik.com/repositories/FrameworkEmbeddingTest cd FrameworkEmbeddingTest xcodebuild -configuration Release OBJROOT=build SYMROOT=build cd build/Release/Foo.app/Contents/MacOS/ DYLD_PRINT_RPATHS=YES ./Foo
man dyld tells you that you can use
DYLD_PRINT_RPATHS=YES to debug @rpath problems.