Both ios-x86_64-simulator and ios-arm64-simulator represent two equivalent library definitions. XCFramework for iOS simulator on M1 & Intel Mac? How?

I now have an M1 Mac and an Intel Mac. I have an XCFramework that targets the iOS simulator and devices. My XCFramework works fine but I'd like to be able to run my app (which uses the XCFramework) on the iOS simulator on both my Macs (m1 & intel).

Now my M1 Mac complains about the x86_64 architecture when I try to run it on the simulator. So I rebuilt the XCFramework (recompiling the simulator version on the M1 Mac).

I'm compiling the source code from Terminal (building OpenSSL). There is no .xcarchive here. Anyway now the app runs on the simulator on the M1 Mac but on the Intel Mac it won't build (basically the same problem in reverse).

So... I made three versions of the library now (for iOS devices, iOS simulator on m1 Mac, and for the iOS simulator on Intel Macs). When I try to make an XCFramework to wrap all three static libraries I get the following error:

Both "ios-x86_64-simulator" and "ios-arm64-simulator" represent two equivalent library definitions.

I found another thread where the accepted answer was to lipo the x86_64 and arm simulators together, then build the xcframework. I've seen posts from Apple engineers that say using lipo is not supported (reference: https://developer.apple.com/forums/thread/709812?answerId=719667022#719667022 )

So where am I going wrong? I try to make the xcframework like so:

xcodebuild -create-xcframework
-library build/sim/openssl-1.1.1q/libcrypto.a -headers build/sim/openssl-1.1.1q/crypto
-library build/phones/openssl-1.1.1q/libcrypto.a -headers build/phones/openssl-1.1.1q/crypto
-library build/intelsim/openssl-1.1.1q/libcrypto.a -headers build/intelsim/openssl-1.1.1q/crypto
-output build/Crypto.xcframework

Accepted Reply

Every post from Apple on the developer forums seems to strongly recommend against using lipo

Hmmm, I think you’re misinterpreting Apple’s position here. The key points to note are:

  • All the architectures within a single universal binary must be for the same platform.

  • iOS and the iOS Simulator are different platforms.

You should never use lipo to merge, say, an arm64 iOS slice with an x86_64 iOS Simulator slice, because those slices are for different platforms. However, using lipo to merge an arm64 iOS Simulator slice (for the simulator running on an Apple silicon Mac) with an x86_64 iOS Simulator slice (for the simulator running on an Intel Mac) is standard operational procedure.

If you want to build a framework that supports iOS and the iOS Simulator, construct an XCFramework with:

  • One element for iOS containing just the arm64 architecture

  • Another element for the iOS Simulator containing both arm64 and x86_64 architectures

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Replies

So I ended up using lipo to combine the Simulator builds into one (M1 and Intel), then created the XCFramework and everything worked fine. Every post from Apple on the developer forums seems to strongly recommend against using lipo but I could not find another way to make this work.

Since I build OpenSSL from Terminal, I'm not sure if there is an option I could use to build for both M1/Intel iOS simulators in one shot. Do command line tool provide a way to build for the Intel simulator even on an M1 Mac? I built the library for the simulator on the Intel machine and Air dropped it over so I could lipo them together. Feels like this should be easier though.

  • Hi Macho!

    Thank you for asking this question, I am actually having the same issue at the moment with only one architecture building successfully on simulator at a time, either arm64 or x86_64 but not both because it produces the same error Both 'ios-arm64-simulator' and 'ios-x86_64-simulator' represent two equivalent library definitions..

    Could you elaborate on how to use lipo to combine both builds into one framework? Seems lipo is being progressively abandoned

  • Managed to achieve what this thread is about, first by duplicating one element then using command: xcrun lipo -create -output <duplicatedElementPath> <arm64Path> <x86_64Path> Then created a new framework containing architectures for simulators and iOS with command: xcodebuild -create-xcframework \ -framework <iosArm64Path> \ -framework <duplicatedElementPath> \ -output <destinationPath> To wrap this up, I agree with Macho that it feels like this should be easier.

Add a Comment

Every post from Apple on the developer forums seems to strongly recommend against using lipo

Hmmm, I think you’re misinterpreting Apple’s position here. The key points to note are:

  • All the architectures within a single universal binary must be for the same platform.

  • iOS and the iOS Simulator are different platforms.

You should never use lipo to merge, say, an arm64 iOS slice with an x86_64 iOS Simulator slice, because those slices are for different platforms. However, using lipo to merge an arm64 iOS Simulator slice (for the simulator running on an Apple silicon Mac) with an x86_64 iOS Simulator slice (for the simulator running on an Intel Mac) is standard operational procedure.

If you want to build a framework that supports iOS and the iOS Simulator, construct an XCFramework with:

  • One element for iOS containing just the arm64 architecture

  • Another element for the iOS Simulator containing both arm64 and x86_64 architectures

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks a lot for clarifying!