If we plan on releasing some of our own code for reuse as a static library there are several things we should do to make sure that the process described above is as easy and simple as possible for our library’s users.
Namespace classes appropriately
Use an appropriate prefix for classes, protocols, functions, and constants in the library to prevent collisions with names in the library’s user’s project.
Create a build target
Provide a static library build target in the project for our users to link against. Xcode provides templates for creating projects with static libraries or adding static library build targets to existing projects.
Expose public headers
Determine which header files should be visible to users of the library. Provide a clearly named group containing these headers so that our library’s users can easily locate them as part of the workaround described in “Fixing Indexing” above. This also helps us clarify what the public interface our library provides is and what classes are implementation details which are likely to change as the library evolves.
For each public header file make sure it is set as “public” in the “Target Membership” section of the inspector pane. Only public headers are going to be available for our users to import.
Making a header file public
Set installation directory
Our static library build target is going to be a member of a user’s workspace and subject to that workspace’s installation rules. Our static library build product could therefore be installed in a location set by Xcode’s preferences, in the derived data path, or in a path specified by our build target. Since we can’t control the user’s settings we should make sure our library is well behaved in all cases. I set the “Installation Directory” build setting to “$(BUILT_PRODUCTS_DIR)” so that the static library build product can be found in a known location and set the “Skip Install” build setting to “Yes” to avoid accidentally installing iOS libraries into “/usr/local/lib”.
Setting the installation directory
Set the public header path
We need to specify a location to copy our static library’s public headers to so that they can be included in our users’ header search paths. Setting the “Public Headers Folder Path” to “$(TARGET_NAME)” will create a folder named after our static library build target in the workspace’s shared build directory and be indexed by the “User Header Search Paths” setting described above.
Setting the public headers path for the static library
Exclude user specific files from VCS
Our workspace and project include a number of files which contain data relevant only to our user account; window positions, open files, and so on. There’s no need to check these into source control, at least not in our release branch, so let’s set some reasonable ignore rules in git or whatever VCS we are using. Github provides a convenient set of .gitignore files
Future Improvements
Hopefully Xcode 4 will eventually live up to the promise of it’s documentation and consistently auto-detect implicit dependencies and index files across the workspace correctly. There certainly seem to be a number of other developers struggling with this behavior:[1], [2], [3], [4], [5], [6], [7], [8]. Until that indexing improves I find that this process is at least somewhat simpler and cleaner than trying to maintain simulator and device compatible static library builds in Xcode 3.
I’ve found this pattern preferable to copying third party classes directly into my projects as it allows me to easily keep version history and make updates to static library projects in my workspace and avoids coupling my project too closely to the private structure and contents of the static library.
Please let me know if you can see any areas where this pattern could be improved or if you’ve found your own alternative means of sharing code.