Brian Dunagan

December 12 2011
Ad-Hoc and App Store IPAs with xcrun

Xcode 4’s “Build and Archive” feature is extremely convenient. With it, I can build a distribution version of an app and archive it away, so that later, in Xcode Organizer, I can click on that instance and submit it to the App Store. Brilliant for individual developers. But at my work, we wanted a bit more: automation and multiple IPAs from a single binary. Both are easy with xcrun, part of Apple’s Developer Tools. (Thanks to Stackoverflow for the pointer!)

Standardized Keys and Certificates

At work, we wanted a standard set of keys and certificates to use for official builds. I went through the standard Apple Developer Center process of creating a certificate signing request with Keychain Access to generate the local keypair, and I created a distribution certificate with that signing request and loaded that into Keychain Access. Then in Keychain Access, I exported the certificate as distribution.cer and the private key as distribution.p12. Xcode needs these two files to correctly use the provisioning profile.

One small hiccup was “login” versus “System” in Keychain Access. I easily imported those two exported files into the “login” keychain in Keychain Access. However, Keychain Access would not import the private key into the “System” keychain and gave the following error: “An error has occurred. Unable to import an item.” I needed to use the “System” keychain, as our build system runs with elevated privileges. To get around this error, I simply needed to import the certificate and private key via Terminal instead:

# Run in Terminal.
sudo security import /path/to/distribution.cer -k /Library/Keychains/System.keychain
sudo security import /path/to/distribution.p12 -k /Library/Keychains/System.keychain

Don’t forget to change the “Access Control” for the private key to “Allow any application to access this item” for “System.keychain”. Otherwise, you’ll get a build error about “user interaction is not allowed”.

At this point, I had a copy of the certificate and private key in “login” and “System” in Keychain Access. I simply needed two provisioning profiles based on that certificate: an ad-hoc profile and an app store profile. I generated both in the iOS Provisioning Profile, Adhoc.mobileprovision and Appstore.mobileprovision, and imported those into Xcode.

With the certificate, private key, and two provisioning profiles loaded up, automating the build was straight-forward. In fact, by selecting the correct default configuration (Xcode 3.2.6), I can simply run Xcodebuild with no arguments to generate an App Store distribution app bundle.

Multiple IPAs from a single binary

Automated builds are nothing new or novel. There are some great suggestions for how to structure your Xcode configurations to simplify automation. What I really wanted were two files at the end: App.AdHoc.ipa and App.AppStore.ipa, ready to be tested ad-hoc or submitted to the App Store. Enter xcrun.

Apple distributes xcrun as part of its Xcode Developer package. The command line utility will take an app bundle and convert it into an IPA file with the supplied provisioning profile. The key part is the supplied provisioning profile can be different from the original one. Here is how I call it:

xcrun -sdk iphoneos PackageApplication 
   -o /path/to/bundle/AppName.ipa 
   --sign "iPhone Distribution" 
   --embed /path/to/certificate

With this command, I can run a build and then generate two IPA files: one for ad-hoc distribution or one for App Store submission. All with the same binary. The community and the tools have progressed a bit since furbo’s “The final test” in 2008.

Over-The-Air ad-hoc distribution

Apple added support for over-the-air (OTA) distribution in iOS 4. It’s the best way to distribute builds to QA, much better than syncing through iTunes. These instructions worked perfectly for me. You don’t need an Enterprise iOS account to do this; I think that simply lets you get around managing UDIDs. Seriously, it’s easy and awesome.

Deleting large AWS S3 buckets Modal views in universal iOS apps
LinkedIn GitHub Email