Can I include a framework in another framework?

I’m writing a framework (called Lighthouse.framework) that, in turn, uses code from another framework (RegexKit.framework, to be precise). I have copied RegexKit.framework into my own framework, so that it has a structure like the following:

Lighthouse.framework/
  Versions/
    A/
      Frameworks/
        RegexKit.framework
      Lighthouse

However, when I try to run an application that uses Lighthouse.framework (my framework), I get the following error:

  • throwing an exception in objective-c/cocoa
  • Building a backwards compatible OS X app, when a new API is present?
  • Enqueue a selector to the run loop - is the way to go?
  • How does NSDocumentController slot into my document based app?
  • comparing arrays in objective-c
  • What does “@private” mean in Objective-C?
  • dyld: Library not loaded: @executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit

    Referenced from: /Users/mdippery/Developer/Projects/Current/lighthouse/build/Debug/Lighthouse.framework/Versions/A/Lighthouse

    Reason: image not found

    Obviously, the loader isn’t finding RegexKit.

    Here’re the paths the loader expects to load, courtesy otool:

    build/Debug/Lighthouse.framework/Versions/A/Lighthouse:
        /Users/mdippery/Library/Frameworks/Lighthouse.framework/Versions/A/Lighthouse (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
        @executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit (compatibility version 0.4.0, current version 0.6.0)
        /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.4)
        /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
        /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.19.0)
        /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 677.26.0)
    

    Can I include a framework in another framework? Is this the proper way to do it? How can I resolve my error?

    3 Solutions Collect From Internet About “Can I include a framework in another framework?”

    The easiest way is to use @rpath. Your configuration should look like:

    1. Set RegExKit.framework’s Installation Directory to @rpath
    2. Set Lighthouse.frameworks’s Installation Directory to @rpath
    3. Set Lighthouse.framework’s Runpath Search Paths to @loader_path/Frameworks
    4. Ensure that RegExKit.framework is copied into Lighthouse.framework’s Framework subfolder (use a custom build phase for this)

    Finally, any applications linking to Lighthouse.framework should set Runpath Search Paths to @loader_path/../Frameworks

    Yes, you can.

    However, you need the included framework to “know” what its installed location will be at the time that it is built; otherwise, dyld won’t be able to find it at run time, as you saw.

    The relevant settings in XCode, if I recall correctly, are “Installation Directory” and “Framework Install Name”. The latter probably won’t matter for your usage, but you’re going to need the former to be something along the lines of: @executable_path/../Frameworks/Lighthouse.framework/Versions/A/Frameworks/RegexKit.framework/Versions/A/

    I discovered a fix for this problem. I incorporated some ideas from sbooth’s answer, but the fix was simpler. I ran this script:

    install_name_tool -change @executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit @loader_path/Frameworks/RegexKit.framework/Versions/A/RegexKit "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.framework/Versions/A/${PRODUCT_NAME}"
    

    as a Run Build Script phase.

    Note that, for the general case, you have to change @executable_path/../ to @loader_path/, and all is well.