It is evolutionary, not revolutionary, for most iOS developers to go from copying the same set of “library” files from project to project, to creating a static library which is then shared between projects to finally creating a universal framework. From my humble point of view the universal framework is the ideal solution because it gives you the ability to just hand off a single framework (which is really a directory), which keeps code implementation hidden, and still have access to a static library that can be edited and shared within a shared workspace.
Having read a few different tutorials on creating a universal iOS framework the task seemed quite daunting and quite honestly over engineered. However, with a project that I am going to be working on shortly I needed to be able to have both options: static lib and framework. So I dove back into the documentation. Of all the blogs and tutorials that I came across the one that helped the most was written by Justin DeWind over at Atomic Object.
The instructions were very straightforward and setting up a project was extremely easy. However, when I went to build the framework I got the following error
lipo: can’t open input file: /Users/cwiles/Library/Developer/Xcode/DerivedData/StaticFramework-akqynrxfwazyswaujkdqvysbbznj/Build/Products/Release-iphonesimulator/libStaticFramework.a (No such file or directory)
Command /bin/sh failed with exit code 1
I checked and rechecked my steps and Xcode project settings, but I kept getting this damn error message. 24 comments and a sample project later, Justin tracked it down. The issue was in the original bash script for building and moving files around assumed that there was a custom build directory inside the project and not using the standard DerivedData directory. Justin kindly updated his scripts and everything ran great. The benefits of using the standard DerviedData build directory is that you can run clean the directory for a specific target for a given project. The benefits of using a custom build directory are:
- Makes it consistent between xcodebuild and Xcode
- The directory is always known
- It is configurable
The way the order of importance works is this:
“GUI” Project Build Settings overwritten by “GUI” Target Build Settings” and “Config” Build Settings
“Config” Build Settings overwritten by “Config” Target Settings
The basic setup I implemented for using the xcconfig files is creating a Project-(Shared, Debug, Release) and Aggregate-(Shared, Debug, Release). This might have been overkill or not have followed best practices, but it did allow for a large range of flexibility for the project and targets.
Two of the most recognizable customizations that are in direct relation to this project are the target’s name and build directory. You can set them in the project level configs or the target level configs. I have set in the target level so that if you create other targets then they those can inherit project level settings or have specifics just for that particular target.
Canonical list of Xcode variables
A huge thanks for Justin DeWind and the rest of the Atomic Object crew for the original post and taking the time to help me troubleshoot this. I hope my sample project is a welcomed addition. If you haven’t you should check out the rest of their posts...lots of great stuff.
If you have a feature request, find a bug or have a tip, especially with the xcconfigs PLEASE let me know.