Tagged with cocoa

Creating Static iOS Libraries

This is part 2 of a 2 part series on using and creating static iOS libraries. See part one: Using static iOS Libraries. for info on how to use static libraries in your own projects.

All of the below steps can be applied to create and package your own static libraries for distribution.

General Procedure

  • Create a new Xcode project of the iOS > “Cocoa Touch Static Library” variety.
  • Add your relevant source files to the project. (.h & .m)
  • I like to add a single .h file that includes all other public headers e.g. <staticLibName>.h
  • Select your newly created target.
  • Select “Build Phases”.
  • Delete the Auto Generated “Copy Files” Phase. (Xcode defaults to adding this, however i prefer to use an actual copy headers phase, which we will add in a second.)
  • Now add a new “Copy Headers” phase.
  • Add your public headers to the public section & your private headers to the private section.
  • Add any other dependant frameworks to the “Link Binary With Libraries” phase. (e.g. Addressbook.framework or CoreLocation.framework)
  • Select “Build Settings”.
  • Find Public Headers Folder Path and set it to include/$(TARGET_NAME) we also want to set Private Headers Folder Path to $(PUBLIC_HEADERS_FOLDER_PATH)/Private. This allows users of our library to find and include our headers. (We include the $(TARGET_NAME) variable so that users can include our headers using the standard framework idiom #include <folder/header.h>.)

  • Find Installation Directory and set it to /.
  • Find Skip Install and set it to Yes.
  • Make sure -all_load -ObjC is added to the Other Linker Flags section. (This makes sure everything in the static library is linked, even if not used at compile time. i.e. making it available at run time.)

Other Things To Consider

Trouble Finding Headers

Your users may have trouble finding headers in their projects even though they have added include/ to their Header Search Paths.They are likely running into an issue whereby the static library is being built with one configuration name and their project is building with another. (i.e. Debug vs DebugStaging)

Xcode will, on finding a matching configuration name in a sub-project use that configuration to build the sub-projects targets, however if it can’t find a matching configuration it uses the projects default config. This can lead to problems finding the matching headers. (i.e. Xcode is looking in Build/Products/DebugStaging-iphonesimulator and your library is being built into Build/Products/Debug-iphonesimulator)

To work around this you can set your public / private headers folder paths to be ../../Headers/$(TARGET_NAME), i.e. in the folder above the config specific folder that Xcode creates when building projects. If you choose to do this your users will instead need to add this folder to their header search paths instead of include/.

Headers being included in Xcode archives

If the path your static library is putting its headers into starts with a slash i.e. /include/$(TARGET_NAME), Xcode will include the headers in archived builds (because it’s a fully rooted path). This leads to app store validation failing when trying to upload a build. The solution to this problem is to change your public headers folder path in your library to no longer include the /.

Ideally you would set Public Headers Folder Path to include/$(TARGET_NAME) and Private Headers Folder Path to $(PUBLIC_HEADERS_FOLDER_PATH)/Private.

Specific Build Settings

Your Static Library Project

PUBLIC_HEADERS_FOLDER_PATH="include/$(TARGET_NAME)"; /*Public Headers Folder Path*/

Users Projects

HEADER_SEARCH_PATHS="include/**"; /*Header Search Paths (the ** indicates recursive)*/
Tagged , ,