Nat! bio photo

Nat!

Senior Mull.

Twitter RSS

Github

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. 1. In the executable of the Framework 2. 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.

As @loader_path for Apps is the same as @executable_path, using @loader_path would 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

The @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 @executable_path/../Frameworks again.

The value of @loader_path for the Bundle will be different than that of the App. You can't optimize the LD_RUNPATH_SEARCH_PATHS setting for the Bundle away.

The $(inherited) is just a Xcode setting mechanism. The observed LD_RUNPATH_SEARCH_PATHS inheritance behaviour is not due to $(inherited)


You can check out my test project yourself:

man dyld tells you that you can use DYLD_PRINT_RPATHS=YES to debug @rpath problems.

git clone /repositories/FrameworkEmbeddingTest
cd FrameworkEmbeddingTest
xcodebuild -configuration Release OBJROOT=build SYMROOT=build
cd build/Release/Foo.app/Contents/MacOS/
DYLD_PRINT_RPATHS=YES ./Foo

Post a comment

All comments are held for moderation; basic HTML formatting accepted.

Name:
E-mail: (not published)
Website: