Orion Edwards Orion Edwards - 2 months ago 30
Swift Question

What is libswiftRemoteMirror.dylib and why is it being included in my app bundle?

I've got an iOS app which I've recently switched to Xcode 8.
As part of that we switched from swift 2.2 to 2.3 (swift 3 will come later).

I've got an automated build pipeline which essentially runs

xcodebuild
to produce a release binary on a dedicated build machine, and after I sorted all that out (Xcode 8's automatic code signing really screws everything up), now when I upload my app to iTunes connect, it fails with this error:


ERROR ITMS-90171: "Invalid Bundle Structure - The binary file 'MyApp.app/libswiftRemoteMirror.dylib' is not permitted. Your app can't contain standalone executables or libraries, other than the CFBundleExecutable of supported bundles. Refer to the Bundle Programming Guide at https://developer.apple.com/go/?id=bundle-structure for information on the iOS app bundle structure."


Sure enough, if I unzip the .ipa file and have a look, there's
libswiftRemoteMirror.dylib
sitting there.

If I archive/export for iTunes via Xcode, then it produces an app bundle which does not have
libswiftRemoteMirror.dylib
, however all other builds of my app appear to have it. Even just doing a debug build within Xcode, then looking at the output shows that libswiftRemoteMirror.dylib is sitting in my app's bundle, indicating that Xcode itself is definitely putting it there, not any part of my automated build script.

What is this file, why is it being put there, and what should I do about it?
I can modify my build script to delete this file for release builds, but I'm concerned that might affect the code signing process. I'll try it anyway and see what happens, but it feels like that's not quite the right thing to be doing.

Any advice would be appreciated.

Answer

I could never get command line xcodebuild to ever work with automatic code signing. I assume because the automated build machine runs as a different account which is only accessed via SSH - It's never had "full" Xcode run as that user account and it doesn't have any certificates in it's Login keychain or anything like that.

I didn't want to use something like shenzhen because I've had nothing but bad experiences from those kinds of things in the past. The Xcode build system is complicated and fragile enough without having to add in more scripts and things that could go wrong or out of date.

Here's what I ended up doing to fix the problem (it's horrible, but it was the only thing I could find that made it work in the end)

  1. In the automated build script, edit the .pbxproj to search and replace Provisioning Style = Automatic; with Provisioning Style = Manual;. Also replace iOS Developer with iOS Distribution for the code signing stuff in the same pbxproj file. These two things turn off automatic signing

  2. Run xcodebuild to build (but not archive) the project in the same way I did in Xcode7 . Xcode compiles the app and signs it, but it's not valid yet, as it contains libswiftRemoteMirror.dylib and also for some reason hasn't got any entitlements file

  3. Delete libswiftRemoteMirror.dylib from the app bundle (this invalidates the signature)

  4. Generate an Entitlements.plist in the app bundle folder by extracting the entitlements bit from the provisioning profile (Like what BlackBerry's SWSiOSResign.sh script does)

    1. Re-sign the app bundle using codesign --entitlements <file>

    2. From there, use a similar technique to what bq/package_ipa.sh does and copy the SwiftSupport folder, then zip the file into an ipa.

I couldn't actually use package_ipa.sh file, I needed to re-implement similar logic instead because I need to reference Swift_2.3.toolchain to get the SwiftSupport from as my app is still swift 2.3 - not XcodeDefault.toolchain (which is swift 3)

It seems like I should be able to use xcodebuild --archive in combination with some other things to avoid some of these steps. I could never get that to work under Xcode7, but I might try again with XC8 if I have time