Build iPhone static library with Xcode
Question: Our project team has a new iPad/iPhone 4 project. We want to put some business logic and generic functionality into a common library but the Xcode 3.2.2 SDK does not allow us to create custom Frameworks unlike for Mac OS X. Is there a way to build a dynamic library for iPhone apps too? We have already opened our App Store account.
Answer: Welcome to the iPhone world and its static libraries! Due to the Apple’s policy dynamic libraries are not allowed to be used in iPhone or iPad applications when you want to sell them on the App Store. Currently the only way to create re-usable code amongst different projects is to create static libraries. 3rd party frameworks as in Mac OS X are not supported in the iPhone SDK.
Building a library is a good idea when you have a large project or you must manage more projects. There is always a lot of code that is very generic and could be placed in their own shared libraries.
With Xcode you can build your own static library that you can share with your co-workers or clients, so that they could link it directly into their own app. You can find good tutorials over the Internet. Major steps are:
1. Create an Xcode project for your static library.
2. Create a static library target with the appropriate configurations (see Xcode documentation).
3. Pack and distribute your files. You have to add the headers and any other resources (like images) that it uses.
4. Copy the library package to a handy local folder to easily keep track of future changes. In Xcode drag the header(s), other resource files if any, and the library file from this distribution folder into your project and choose that you DO NOT want it to be copied. Xcode automatically adds the library to the target. The static library package will be included in the app bundle.
Cross-project reference
If the static library and its source code is being distributed among your collegues as an Xcode project by using a “cross-project reference”, the building of the common libraries “on-demand” can be flowless for all of you. In this case libraries are built dynamically and you are using your own app’s current build configuration. The benefit is the simple setup: it allows you to both reuse shared source code and avoid the headache of managing multiple versions of the library. The drawback is the references may not be automatically updated, so that code modifications need to be refreshed at dependent projects manually.
1. The shared code of the static library resides in its own Xcode project that, when built, results in one or more static libraries. You must create an Xcode environment variable with a path to the folder that contains the static library’s *.xcodeproj file. See Xcode -> Preferences -> “Source Tree”. Add your variable that Xcode can use to dynamically find the static library project.
2. Add the library project as a sub-project to your own Xcode project. It is a reference only. See Xcode -> Project -> Add to Project.
Your applications must now set this environment variable to cross-reference the library’s Xcode project, including any static library in that project and the related header and other resource files. See Xcode -> Click on the sub-project -> File -> Get Info -> Path Type. Change the relative path to your environment variable.
Select your main application target and hit Cmd+i (Get Info). At the General tab add the static library(ies) your project needs from the shared static library project by clicking the “+” button under “Direct Dependencies”.
Add your library’s path to the User Header Search Paths (at Build tab). You can use this syntax: $(ENVVARIABLE), where ENVVARIABLE is your environment variable of the path to the static library (see step 1). Add -ObjC and -all_load flag to the Other Linker Flags key.
Now drag and copy the static library(ies) from the cross-project reference to “Targets > {your app target} > Link Binary with Libraries.” This ensures that that the .a file(s) will be passed to the linker when you do the build.
3. Each time you build your project for a specific runtime configuration, the shared project library will also be built.
-ObjC and -all_load flags
Do not forget to add these flags to the application target’s “Other Linker Flags” build key.
Objective-C only generates one symbol per class. We must force the linker to load the members of the class too. This is what flag -ObjC does. We must also force inclusion of all our objects from our static library by adding the linker flag -all_load. If you skip these flags sooner or later you will run into the error of “unrecognized selector” or get other exceptions.
We’ve been using this approach from the very beginning and it’s definitely saved us a lot of time.
Useful links:
How to build and use multiple resource bundles
Apple’s iPhone Developer Center
Visit Apple’s discussion forum for iPhone and iPad issues