If you’re like me, you want to build your iOS apps from the command line. Luckily, there are many tools to help you do that. You can use Apple’s xcodebuild, or you can use Facebook’s drop-in replacement for xcodebuild, xctool.

However, while these tools seem to offer the same functionality as Xcode itself, there are some differences, specifically with Swift apps. If you’ve attempted to compile and archive a Swift app via a command line tool and distribute it to iTunes Connect, you may have gotten an email from Apple like this:

Dear developer,

We have discovered one or more issues with your recent delivery for “MyiOSApp”. To process your delivery, the following issues must be corrected:

Invalid Swift Support - The bundle contains an invalid implementation of Swift. The app may have been built or signed with non-compliant or pre-release tools. Visit developer.apple.com for more information.

Once these issues have been corrected, you can then redeliver the corrected binary.

Regards,

The App Store team

The key piece of information in this email is this:

Invalid Swift Support - The bundle contains an invalid implementation of Swift. The app may have been built or signed with non-compliant or pre-release tools. Visit developer.apple.com for more information.

After a bit of digging, I discovered that this is due to a change that Apple made to the internal structure of .ipa files for Swift apps. .ipa files (which are essentially just Zip archives) generated by Swift apps now contain a top-level directory named SwiftSupport. This directory contains all the runtime libraries that are required to run your Swift app.

Unfortunately, this folder is only automatically generated when the .ipa is packaged by Xcode.app itself. If you’re using a tool like xcodebuild or xcrun to package your .ipa, you’ll need to manually create this folder and copy over the runtime libraries.

Once you unzip your .ipa, create a folder alongside Payload named SwiftSupport. You can get a list of libraries to copy over by searching for all .dylib files within the Payload/*.app/Frameworks directory. It’s not quite as simple as copying these files to SwiftSupport, you’ll need to find the matching libraries within the Xcode.app package and copy those over. The libraries are located in the following directory within Xcode.app:

Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos/

For every .dylib in your Frameworks directory, copy over the corresponding .dylib from .../lib/swift/iphoneos to SwiftSupport. Then, zip the two folders back into an .ipa, and your app should be good to distribute to iTunes Connect.


We’ve completely automated this process at Ship.io. We offer continuous integration and delivery for iOS and Android apps that’s super simple to set up. We’re free to try out, so feel free to take a look! If you’re just interested in automating this process locally, BQ has written a nice script to handle this. Take a look at ipa-packager on GitHub.