I was fortunate enough to attend WWDC this year and while I was there I spoke to a few Apple Engineers about command line builds and how painful it was to try to replicate what the Xcode App did to archive and export the ipa files (see this previous post for details).
Good News! Xcode 7 has a solution hidden within. It’s bundled with an updated version of xcodebuild which enables archiving and generating ipa files correctly as the Xcode App does.
Now for the bad news - this feature is not yet documented but I suspect it will be in a future update. Its fairly simple and self documenting (once you find the right option).
While Xcode 7 is still in its beta phase, I have experimented with it and it looks promising. It appears to also work for Archives generated with previous versions of Xcode - which means you won’t have to wait till September to leverage this. That being said I would err on the side of the caution.
The short version (TL;DR)
-exportArchive step, the flag to test out is
exportOptionsPlist which takes a path to a plist file with some configuration information regarding the build.
# Switch xcrun to leverage Xcode 7 # Note: This won't be needed once Xcode 7 is released # and becomes the primary Xcode in use. export DEVELOPER_DIR=/Applications/Xcode-beta.app/Contents/Developer/ # Export Archive xcrun xcodebuild -exportArchive -exportOptionsPlist exportPlist.plist -archivePath /path/to/app.xcarchive -exportPath /path/to/ipa/dir
Here’s a sample export options plist file.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>teamID</key> <string>MYTEAMID123</string> <key>method</key> <string>app-store</string> <key>uploadSymbols</key> <true/> </dict> </plist>
Let’s assume we have an app with the original name MyApp that is written in Swift and has a Watch App bundled with it. The following steps will be all that is needed to get an ipa which can be uploaded to the App Store.
# Archive xcodebuild -scheme MyApp -archivePath builds/MyApp.xcarchive archive
2) Export Archive
# Switch xcrun to leverage Xcode 7 # Note: This won't be needed once Xcode 7 is released and is the # primary Xcode in use. export DEVELOPER_DIR=/Applications/Xcode-beta.app/Contents/Developer/ # Export Archive xcrun xcodebuild -exportArchive -exportOptionsPlist exportPlist.plist -archivePath builds/MyApp.xcarchive -exportPath builds
Now for the moment of truth. Let’s examine the contents of the ipa and verify what’s there.
# Unzip the ipa file to verify contents cd builds unzip -q MyApp.ipa ls -al # We should see the following folders # - Payload # - SwiftSupport # - Symbols # - WatchKitSupport
If all went well, we should see the following directories
We can also verify the signatures on the app and the extension.
cd Payload #Verify Watch App xcrun codesign -dv MyApp.app/PlugIns/MyApp\ WatchKit\ Extension.appex/MyApp\ WatchKit\ App.app #Verify Watch Extension xcrun codesign -dv MyApp.app/PlugIns/MyApp\ WatchKit\ Extension.appex #Verify main app xcrun codesign -dv MyApp.app
The Export Options Plist
Here’s are the options I know of so far:
- method: (String) The method of distribution, which can be set as any of the following:
- teamID: (String) The development program team identifier.
- uploadSymbols: (Boolean) Option to include symbols in the generated ipa file.
- uploadBitcode: (Boolean) Option to include Bitcode.
If you discover any more options, a comment below would be much appreciated!
Edit: as of the latest Xcode7 - these options are now documented within
It’s great to see some traction on this front! This will simplify a lot of workflows and should hopefully future proof our build scripts for all the upcoming new features, such as App Thining and watchOS 2.