Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode 12, building for iOS Simulator, but linking in an object file built for iOS, for architecture 'arm64'

I am trying to get a large (and working on Xcode 11!) project building in Xcode 12 (beta 5) to prepare for iOS 14. The codebase was previously in Objective-C, but now it contains both Objective-C and Swift, and uses pods that are Objective-C and/or Swift as well.

I have pulled the new beta of CocoaPods with Xcode 12 support (currently 1.10.0.beta 2).

Pod install is successful. When I do a build, I get the following error on a pod framework:

building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

and possibly also the error:

Unable to load standard library for target 'arm64-apple-ios11.0'

When I go run lipo -info on the framework, it has: armv7s armv7 i386 x86_64 arm64.

Previously, the project had Valid Architectures set to: armv7, armv7s and arm64.

In Xcode 12, that setting goes away, as per Apple's documentation. Architectures is set to $(ARCHS_STANDARD). I have nothing set in excluded architectures.

What may be going on here? I have not been able to reproduce this with a simpler project yet.

like image 983
btxios Avatar asked Aug 26 '20 23:08

btxios


People also ask

Is iOS simulator arm64?

Both ios-arm64-simulator and ios-x86_64-simulator represent two equivalent library definitions. Seeing these when trying to create an xcframework for Apple Silicon that supports Mac Catalyst and the iOS Simulator: Both ios-arm64-simulator and ios-x86_64-simulator represent two equivalent library definitions.

How do I add excluded architectures in Xcode?

Go to Targets section, select each target and do the following: Set Build Active Architecture Only to YES. Add Excluded Architectures and set its value to arm64 (See attached) Set Active scheme (on toolbar next to project name) to any iOS Simulator.

Do I need Xcode for iOS simulator?

The Simulator app requires several other large directories from the Xcode distribution in order to work at all. The only official way to install all of those properly is to install the entire SDK from the dmg.

Does xcodebuild support x86_64?

And that means xcodebuild will try to build all architectural variants of your libs/apps for the selected run destination for release builds. And for the Simulator run destination, it will includes both x86_64 and arm64 now on, since arm64 in Xcode 12+ is also a supported architecture for simulators to support Apple silicon.

Does Xcode build support ARM64 simulators?

xcodebuild, in the Xcode 12+ build system considers arm64 as a valid architecture for simulator to support Apple silicon. So when a simulator is chosen as the run destination, it can potentially try to compile/link your libs/apps against arm64 based simulators, as well.

Is there a framework for building iOS simulators?

Building for iOS Simulator, but the linked and embedded framework 'My.framework' was built for iOS + iOS Simulator. The framework is built for both devices and simulators (as the error actually says) and merged using lipo, so it should be able to run everywhere without issues.

How to add x86_64 to the iOS simulator SDK?

To do that, navigate to Build Settings of your project -> Excluded Architectures -> Select the configuration (Debug/Release/Etc...) -> Tap + -> Any iOS Simulator SDK -> Add arm64, arm64e, armv7 Similarly, add x86_64, i386 to Any iOS SDK.


4 Answers

Basically, you have to exclude arm64 for the simulator architecture, both from your project and the Pod project.

  • To do that, navigate to Build Settings of your project and add Any iOS Simulator SDK with value arm64 inside Excluded Architecture.

    Enter image description here

OR

  • If you are using custom XCConfig files, you can simply add this line for excluding simulator architecture.

    EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64
    

    Then

    You have to do the same for the Pod project until all the Cocoa pod vendors are done adding following in their Podspec.

    s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
    s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
    

    You can manually add the Excluded Architecture in your Pod project's Build Settings, but it will be overwritten when you use pod install.

    In place of this, you can add this snippet in your Podfile. It will write the necessary Build Settings every time you run pod install.

    post_install do |installer|
      installer.pods_project.build_configurations.each do |config|
        config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
      end
    end
    
like image 169
Amit Samant Avatar answered Oct 22 '22 09:10

Amit Samant


TL;DR;

Set "Build Active Architecture Only (ONLY_ACTIVE_ARCH)" to Yes for your libraries/apps, even for release mode.


While trying to identify the root cause of the issue I realized some fun facts about Xcode 12.

  1. Xcode 12 is actually the stepping stone for Apple silicon which unfortunately is not yet available (when the answer was written). But with that platform we are going to get an arm64-based macOS where simulators will also run on the arm64 architecture unlike the present Intel-based x86_64 architecture.

  2. Xcode usually depends on the "Run Destination" to build its libraries/applications. So when a simulator is chosen as the "Run Destination", it builds the app for available simulator architectures and when a device is chosen as the "Run Destination" it builds for the architecture that the device supports (arm*).

  3. xcodebuild, in the Xcode 12+ build system considers arm64 as a valid architecture for simulator to support Apple silicon. So when a simulator is chosen as the run destination, it can potentially try to compile/link your libs/apps against arm64 based simulators, as well. So it sends clang(++) some -target flag like arm64-apple-ios13.0-simulator in <architecture>-<os>-<sdk>-<destination> format and clang tries to build/link against an arm64-based simulator that eventually fails on an Intel based Mac.

  4. But xcodebuild tries this only for Release builds. Why? Because, "Build Active Architecture Only (ONLY_ACTIVE_ARCH)" build settings is usually set to "No" for the "Release" configuration only. And that means xcodebuild will try to build all architectural variants of your libs/apps for the selected run destination for release builds. And for the Simulator run destination, it will includes both x86_64 and arm64 now on, since arm64 in Xcode 12+ is also a supported architecture for simulators to support Apple silicon.

Simply putting, Xcode will fail to build your application anytime it tries the command line, xcodebuild, (which defaults to release build, see the general tab of your project setting) or otherwise and tries to build all architectural variants supported by the run destination. So a simple workaround to this issue is to set "Build Active Architecture Only (ONLY_ACTIVE_ARCH)" to Yes in your libraries/apps, even for release mode.

Enter image description here

Enter image description here

If the libraries are included as Pods and you have access to .podspec you can simply set:

spec.pod_target_xcconfig = { 'ONLY_ACTIVE_ARCH' => 'YES' }

spec.user_target_xcconfig = { 'ONLY_ACTIVE_ARCH' => 'YES' } # not recommended

I personally don't like the second line since pods shouldn't pollute the target project and it could be overridden in the target settings, itself. So it should be the responsibility of the consumer project to override the setting by some means. However, this could be necessary for successful linting of podspecs.

However, if you don't have access to the .podspec, you can always update the settings during installation of the pods:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings["ONLY_ACTIVE_ARCH"] = "YES"
    end
  end
end

One thing I was concerned about that what will be the impact of this when we actually archive the libraries and applications. During archiving applications usually take the "Release" configuration and since this will be creating a release build considering only the active architecture of the current run destination, with this approach, we may lose the slices for armv7, armv7s, etc. from the target build. However, I noticed the documentation says (highlighted in the attached picture) that this setting will be ignored when we choose "Generic iOS Device/Any Device" as the run destination, since it doesn't define any specific architecture. So I guess we should be good if we archive our app choosing that as a run destination.

like image 266
Ayan Sengupta Avatar answered Oct 22 '22 11:10

Ayan Sengupta


I found a solution! SwiftUI Previews not working with Firebase

If you set excluded architectures for the simulator to arm64 it will compile.

Excluding architectures for the simulator

like image 132
SlashDevSlashGnoll Avatar answered Oct 22 '22 10:10

SlashDevSlashGnoll


The proposed answers are outdated/incorrect.

You should initially try to update both CocoaPods and the dependencies for your library/app, and then, if that doesn't work, contact the vendors of any dependencies you are using to see if they have an update in progress to add support for arm64 Simulator slices on M1 Macs.

There are a lot of answers on here marked as correct suggesting that you should exclude arm64 from the list of supported architectures. This is at best a very temporary workaround, and at worst it will spread this issue to other consumers of your libraries. If you exclude the arm64 Simulator slice, there will be performance impacts on apps that you're developing in the Simulator (which in turn can lead to reduced battery time for your shiny new M1 kit while you're developing your amazing ideas).

like image 97
Tony Arnold Avatar answered Oct 22 '22 10:10

Tony Arnold