Now that we’re a little more familiar with targets. How about we actually stopped being lazy and created a shared library?
How to do it
- Select File > New > Target (can also click on the project to open the target list and select the (+) symbol at the bottom left)
- Pick ‘Framework & Library’ in iOS templates.
- Select ‘Cocoa Touch Static Library’
I have a few files that I find useful whatever project I’m working on; for now I have just removed these files from all my existing targets, and added them to my newly created ‘utilities’ library target. This builds without issues.
Next, I opened the Build Phases tab for a target that should use the library. I drag and drop the library in the ‘Link Binary With Libraries’ section. Ordering is sensitive, so I add my library at the bottom of the list, after the frameworks.
Remember that the library should be listed by every target that uses the library. If your main target depends on a test target, and somehow your test code implies using the library as well, then both the main target and the test target should link against the library.
OK, how do I include the headers in my project?
- Click on your project (the project that you want to use your library with) to open the build related stuff.
- Select the project. It’s especially useful to include headers at project level if you have tests or use several targets.
- search for ‘User Header Search Paths’.
- Add the path to the library source file. It’s better to add a relative path. So if your project is under foo/myProj.xcodeproj and the library headers are under foo/myLib/myLib, then typically the path would be ../myLib/myLib
- You may need to set the matching target settings (the user header search path in each target) to $(inherited). This explicitly tells a target to inherit the setting from project level.
I feel there should be a cleaner way to do it, but I’ve seen it done by other devs, works for me.
Why do it?
Maybe you have qualified reasons for using a static library instead of sharing files across targets. Or maybe you just want to create a library that other developers can use.
However, even if we’re working on small projects and the ‘dev team’ is just one guy, the bottom line is that static libraries are the better way as soon as you want to share code between your apps.
Even if you define your apps using several products in the same project (a lightweight, moderately evil technique I describe in my previous post), that changes little to the fact that editing target associations in xcode is a manual process that requires patience. So rather than having to add every other code file to a new target whenever we start a new project (or removing undesirable files from a cloned target), we just add our files to the library, and link the library against our project, once and for all.
What cannot be included in a static library?
Pictures, text files, nib files and other non code files cannot be included in a library target. Code and header files can be included. It is interesting that Test and Library targets both allow *.h files, whereas product targets do not.
Can I get my static library to build automatically whenever I rebuild my product target?
Yes; it works the same as target dependencies for test targets.
Under ‘build phases’, drag the library target into the ‘target dependencies’ list. Ben Artin explained very nicely (here) that ‘dependencies are orthogonal to linking, if you want both, you need to specify both’
You may find this article useful (from “The Carbon Emitter”).