Including Frameworks in your Application
Apple recommends that any frameworks required by your application be distributed within the app wrapper of the application itself. Doing so is not 100% straightforward (and I couldn't find decent documentation on the subject).
I was recently faced with the need to distribute the Mulle Kybernetik XML-RPC frameworks inside of the application wrapper of the RadioService application.
What follows is a step by step description of what I did. The end result works fine for both deployment and development; development does require that you build the frameworks such that their *.framework product is present in the build products directory.
My build products preference is set to /tmp/bbum-products/. This should not affect the overall solution. In any case, it is generally a good idea to set the intermediate and product Build Results preferences to point to some location in /tmp/, preferably two different locations. It is faster than working against a mounted drive (if your home directory is mounted) and doesn't clutter up the project directory with a bunch of files that should not be revision controlled.
Modifying the Framework project(s)
- Add a new build style named Embedded.
- Set the following three variables:
COPY_PHASE_STRIP = YES
FRAMEWORK_INSTALLED_NAME = @executable_path$(/)..$(/)Frameworks$(/)$(PRODUCT_NAME).$(WRAPPER_EXTENSION)$(/)Versions$(/)$(FRAMEWORK_VERSION)$(/)$(PRODUCT_NAME)
INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/EmbeddedFrameworks
- Build & Install the framework from the Terminal:
pbxbuild -target -buildstyle Embedded install DSTROOT=
(Replace '' with the name of the target that builds the framework in your project)
You might need to either execute the pbxbuild step via sudo or create the /Library/EmbeddedFrameworks directory and change permissions on it accordingly.
Modifying the Application project(s)
- Add the framework(s) from /Library/EmbeddedFrameworks to the project as you would any other framework. PB will likely default to using an absolute path reference; this is fine.
- Add a Copy Files build phase to the target that builds the application.
- Add the frameworks to the new Copy Files build phase.
- Check the 'Copy only when installing' checkbox.
When in active development, you will need to build the framework(s) via project builder as normal because the application will need to find them in your build-products directory at runtime. This also ensures that the frameworks have debugging symbols, making debugging that much easier.
For deployment, simply install the application as you normally would. Typically, that would involve invoking something like...
pbxbuild -buildstyle Deployment install DSTROOT=/tmp/MyApplication
... from the terminal.
The end result will be an application that should contain the frameworks within the application wrapper. To test, do something like the following:
[localhost:sourceforge/mosxland/RadioService] bbum% pbxbuild -buildstyle Deployment install
[localhost:sourceforge/mosxland/RadioService] bbum% cd /tmp/RadioService.dst/RadioService.app/
[localhost:bbum/Applications/RadioService.app] bbum% ls Contents/Frameworks/
EDCommon.framework XMLRPC.framework
[localhost:bbum/Applications/RadioService.app] bbum% otool -L Contents/MacOS/RadioService
Contents/MacOS/RadioService:
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 7.0.0)
/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 122.0.0)
@executable_path/../Frameworks/EDCommon.framework/Versions/A/EDCommon (compatibility version 25.0.0, current version 28.0.0)
@executable_path/../Frameworks/XMLRPC.framework/Versions/A/XMLRPC (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 55.0.0)
9:54:05 AM
|