[Update] Xcode 10.2 Beta 1 does not change the behavior that is described below.
Learn how to distribute your iOS app with the arm64e
CPU architecture slice.
Introduction
This yearâs incarnation of Appleâs iOS devices features the new Apple A12 Bionic CPU. Performance improvements aside, it is the first commercially available 7nm silicone, and the first CPU with the arm64e
CPU architecture (as usual, AnandTech covers Appleâs new CPU extensively). Its new security extensions might require you to make adjustments to your code. Apple explains the various usecases and provides necessary steps in their documentation. The new pointer authentication requirements of arm64e
resulted in additional work for my team at App Center as well.
It turns out to be quite challenging to distribute an app with an arm64e
slice today. While Xcode 10.1 added support for developers to test their app with new architecture, it is not possible to submit an app to the App Store or TestFlight. In fact, the arm64e
architecture will be stripped away if you use Xcodeâs Organizer window. This happens even when exporting for AdHoc or Enterprise distribution (see the Xcode 10.1 release notes), and even when exporting from the commandline via xcodebuild
.
In this post, I will show you how you can circumvent this limitation and export an iOS app with the arm64e
slice. You can distribute it to your testers (using one of the alternatives to TestFlight of course).
Export the .xcarchive with the new architecture
First, you need Xcode 10.1 installed on your machine. Open your appâs project or workspace in Xcode 10.1 and add the arm64e
architecture as described in the documentation.
Once you have done that, archive your application the same way you normally would.
This assumes that your app’s dependencies support the arm64e architecture. We recently added arm64e support to the App Center SDK for iOS. I plan on covering our journey in another post.
After Xcode has finished archiving the app, the Organizer window will open. Right-click on the archive that you just created and select âShow in Finderâ.
I prefer to copy the .xcarchive
 package somewhere where I can find it easily. For my example, Iâm choosing a folder on the desktop. To check if the binary in your .xcarchive
 package contains the slice for the arm64e
architecture, run
lipo -info $PATH_TO_THE_BINARY_INSIDE_THE_XCARCHIVE
.
The easiest way to get the path to the binary is: right-click on the .xcarchive
 package that you created, select âShow Package Contentsâ, and locate your .app
package inside Products/Applications/
. Then right-click on the .app
 package, select âShow Package Contentsâ once more, and find your appâs binary.
In my example, I need to run:
lipo -info /Users/benny/Desktop/AwesomeApp/AwesomeApp.xcarchive/Products/Applications/AwesomeApp.app/AwesomeApp
.
This prints out the following:
Architectures in the fat file: /Users/benny/Desktop/AwesomeApp/AwesomeApp.xcarchive/Products/Applications/AwesomeApp.app/AwesomeApp are: arm64 arm64e
Awesome, the .xcarchive
 already contains the arm64e
slice!
Create the .ipa file
The next step is to create the .ipa
 file that you can install on your new iPhone/iPad.
My initial idea was to switch back to Xcode 9.4.1, run xcodebuild -exportArchive -archivePath ./AwesomeApp.xcarchive/ -exportPath ./ -exportOptionsPlist ExportOptions.plist
, and trick xcodebuild
into exporting an .ipa
 file which contains the arm64e
slice.
Unfortunately, this doesn’t work; signing the .dylibs
 and .frameworks
 will fail because Xcode 9.4.1âs code_sign
tool will not be able to do itâs job â the .xcarchive
 was created in Xcode 10.1, after all.
Luckily, I learned about the ditto
tool from a co-worker the other day. cd
 into the folder that contains your appâs .xcarchive
 and create a temporary directory structure:
mkdir -p tmp/app/Payload
.
Copy your .app
 package into the directory using:
ditto AwesomeApp.xcarchive/Products/Applications/AwesomeApp.app tmp/app/Payload/AwesomeApp.app
,
followed by:
ditto -ck --rsrc --sequesterRsrc --keepParent tmp/app/Payload/ AwesomeApp.ipa
Congratulations, you’re pretty much done. Use lipo -info
on the appâs binary inside the .ipa
package (unzip the .ipa
, then use âShow Package Contentsâ ) to verify that it contains the arm64e
architecture. It should print something like this:
/Users/benny/Desktop/AwesomeApp/Payload/AwesomeApp.app/AwesomeApp is architecture: arm64 arm64e
Now, go distribute your .ipa
 with the new arm64e
architecture to your testers and squash all those bugs!