Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

ADGrant

macrumors 68000
Original poster
Mar 26, 2018
1,685
1,058
I have an iOS app that I developed years ago using an Intel Mac. I recently started also using an M1 Mac which allows me to run and debug the app directly on MacOS. What it does not let me do is run and debug the app in a simulator. The app fails to link to some dependencies with the error "building for iOS Simulator, but linking in object file built for iOS". The work around suggested is to use Rosetta to run the app in the x64 simulator. I have a simpler workaround which is to just keep using my Intel Mac which is fortunately a recent model.

Some links:



 

casperes1996

macrumors 604
Jan 26, 2014
7,485
5,649
Horsens, Denmark
Seems like it's not intended behaviour and just a bug. I've so far only tried building for Mac on my M1 Max so I've not personally had run-ins with this issue, but I'd imagine it'll get fixed
 

ADGrant

macrumors 68000
Original poster
Mar 26, 2018
1,685
1,058
Seems like it's not intended behaviour and just a bug. I've so far only tried building for Mac on my M1 Max so I've not personally had run-ins with this issue, but I'd imagine it'll get fixed
According to Apple documentation this is intended behavior.

See

TN3117: Resolving architecture build errors on Apple silicon​


 

casperes1996

macrumors 604
Jan 26, 2014
7,485
5,649
Horsens, Denmark
I didn’t see anything in there to suggest you can’t use the simulator. Simply that simulator targets must have the relevant frameworks/libraries made for it
 

ADGrant

macrumors 68000
Original poster
Mar 26, 2018
1,685
1,058
I didn’t see anything in there to suggest you can’t use the simulator. Simply that simulator targets must have the relevant frameworks/libraries made for it
From the documentation:

Note

A pre-compiled library must be built as an XCFramework to separate the device and simulator builds. Combining architectures for iOS, watchOS, or tvOS and their respective simulators into a single binary file is not supported.

So I can have an app that will build and run on an M1 iPad and on the iPad simulator on an Intel Mac and also run directly on an M1 Mac (targeting the Mac instead of the emulator) but not on the simulator on an M1 Mac. Why do I need two ARM64 builds, one for the simulator and one for an iOS device. Why can't the Simulator just run the native iOS build?

The docs also say:

Update pre-compiled libraries from vendors

If the library producing the build error is a pre-compiled library from a vendor and you don’t have the source code, contact the vendor for an updated XCFramework supporting Apple silicon. If an update isn’t available from the vendor, temporarily use the EXCLUDED_ARCHS build setting to exclude arm64 for the simulator SDK as shown in the figure below. Do not exclude arm64 for any other SDK.

Excluding ARM64 from the simulator build will use Rosetta to run the x64 simulator. So we have an x64 simulator build for an ARM64 app that is then translated to ARM64 the native architecture of the device being emulated.
 

casperes1996

macrumors 604
Jan 26, 2014
7,485
5,649
Horsens, Denmark
I think I misunderstood you earlier

This has always been a limitation then. You always needed to build separately for the simulator vs real iOS. Now yes, it's a valid argument to say that it no longer ought to be necessary since iOS and Macs with Apple Silicon are on the same architecture, so the simulator ought to just be like an iOS VM or something like that. But the Simulator, at least as of now, is not made that way and the binary generated for running in the simulator, even on the same AArch64 architecture, is not the same binary as is made for running on a real device, whether that be an iOS device or straight on the Mac. - I could be wrong about the following, but I don't even think the simulator runs in a hypervised environment. So it couldn't capture syscalls if they appear in the code of the application. It just gets calls to simulated behaviour functions embedded in the binary.
So your targets are
iOS, iOS Simulator (x86) and iOS Simulator (Aarch64) - Your dependency lacks the latter
 

ADGrant

macrumors 68000
Original poster
Mar 26, 2018
1,685
1,058
I think I misunderstood you earlier

This has always been a limitation then. You always needed to build separately for the simulator vs real iOS. Now yes, it's a valid argument to say that it no longer ought to be necessary since iOS and Macs with Apple Silicon are on the same architecture, so the simulator ought to just be like an iOS VM or something like that. But the Simulator, at least as of now, is not made that way and the binary generated for running in the simulator, even on the same AArch64 architecture, is not the same binary as is made for running on a real device, whether that be an iOS device or straight on the Mac. - I could be wrong about the following, but I don't even think the simulator runs in a hypervised environment. So it couldn't capture syscalls if they appear in the code of the application. It just gets calls to simulated behaviour functions embedded in the binary.
So your targets are
iOS, iOS Simulator (x86) and iOS Simulator (Aarch64) - Your dependency lacks the latter
You are right, a separate simulator build has always been required. On Intel Macs needing to build separately for the simulator vs real iOS is not really a surprise though given the CPU instruction set is completely different. I believe that you are also right that the simulator does not run in a VM which I think is a lost opportunity. I thought using an ARM64 Mac would eliminate the need for a separate simulator build. It also leads to the irony of potentially running an x64 build of an iOS app on an ARM64 Mac using Rosetta. Or just developing the iOS app on an Intel Mac instead.

I don't think its even as simple as just adding a third target if the dependency is a regular static library (on *nix operating systems a .a file). I believe the two ARM64 builds have to be packaged into an XCFramework.

However, since my desktop Mac is still Intel based I don't have to do anything right now. I will keep using the Intel Mac for iOS development and just use an M1 Mac when I want to test an iOS app running on MacOS (Catalyst and/or straight iOS).
 

casperes1996

macrumors 604
Jan 26, 2014
7,485
5,649
Horsens, Denmark
I don't think its even as simple as just adding a third target if the dependency is a regular static library (on *nix operating systems a .a file). I believe the two ARM64 builds have to be packaged into an XCFramework.

However, since my desktop Mac is still Intel based I don't have to do anything right now. I will keep using the Intel Mac for iOS development and just use an M1 Mac when I want to test an iOS app running on MacOS (Catalyst and/or straight iOS).
When I talked about targets I meant the dependency itself should be built against those targets to work, which XCFramework packaging simplifies

Your solution works. But running through Rosetta is not a bad experience either way. For me, for now, Rosetta is a necessity regardless so I'm not fuzzed about running stuff through it; I need it installed regardless. Native is ideal, but performance is rather good with Rosetta anyway. My desktop is also an Intel based Mac for now, but if I'm at university with my laptop I'll work with whatever works. Native if available, Rosetta if not, and I don't typically even think about it. It working is the most important thing in the end. And even if you have to take a performance drop from running through Rosetta, my M1 Max 16" still offers a superior experience in other aspects than a native-running Intel Mac that may outperform it in x86_64 tasks, like battery, display, speakers, fan noise, heat. So in the end, my point is, I don't think the workaround of running through Rosetta until you get an update for whatever third party dependencies you have, is that problematic necessarily. But YMMV of course
 

ADGrant

macrumors 68000
Original poster
Mar 26, 2018
1,685
1,058
When I talked about targets I meant the dependency itself should be built against those targets to work, which XCFramework packaging simplifies

Your solution works. But running through Rosetta is not a bad experience either way. For me, for now, Rosetta is a necessity regardless so I'm not fuzzed about running stuff through it; I need it installed regardless. Native is ideal, but performance is rather good with Rosetta anyway. My desktop is also an Intel based Mac for now, but if I'm at university with my laptop I'll work with whatever works. Native if available, Rosetta if not, and I don't typically even think about it. It working is the most important thing in the end. And even if you have to take a performance drop from running through Rosetta, my M1 Max 16" still offers a superior experience in other aspects than a native-running Intel Mac that may outperform it in x86_64 tasks, like battery, display, speakers, fan noise, heat. So in the end, my point is, I don't think the workaround of running through Rosetta until you get an update for whatever third party dependencies you have, is that problematic necessarily. But YMMV of course
I mostly work from my desktop and I have an i9 2020 iMac so using the Intel simulators is not a great hardship. I have no doubt that Rosetta on an M1 works well too though. I would love an XDR 27" 5k screen but otherwise I don't notice any disadvantages to using the iMac over the M1 Pro 14" MBP I could use instead.

Aside from the simulator issue, the Intel iMac does offer more virtualization choices for running Linux and Windows VMs and both the Windows and the linux (and therefore docker) ecosystem is still largely x64 based. It's also much cheaper than a Mac Studio with the Studio display so hopefully Apple continues to support Intel Mac based development for a few more years.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.