Skip to content
Writing

React Native on M1: What Actually Fixed the Build

The M1 Mac broke every React Native build tool in 2022. Here's what actually worked.

3 min read
  • react-native
  • ios
  • mobile

My company handed me an M1 MacBook Pro in early 2022. Within an hour of cloning the repo, I had a build error I’d never seen before. Within a day, I had twelve.

React Native on Apple Silicon was a minefield in early 2022. Most of the advice online at the time was either outdated by a week or written for a different RN version. This is what actually worked for me on our React Native 0.67 project. No theory, just the specific problems and the commands that fixed them.

CocoaPods won’t install

The first error you’ll hit. CocoaPods depends on the ffi gem, and at the time it shipped an x86-only binary:

LoadError - dlopen(.../ffi-1.14.2/lib/ffi_c.bundle, 0x0009):
  missing compatible arch in .../ffi_c.bundle

What worked:

arch -x86_64 pod install

This forces CocoaPods to run under Rosetta. It’s ugly but it works. The alternative is installing Ruby via rbenv under arm64 and then reinstalling the ffi gem natively. More correct, but not worth the yak shave when you just need a build.

After pods install, Xcode throws this:

building for iOS Simulator, but linking in object file
built for iOS, file '...libcrypto.a' for architecture arm64

The problem: Xcode 12+ added arm64 simulator support, but pre-built pod binaries only had one arm64 slice, compiled for the device. Xcode couldn’t tell the device and simulator slices apart, so it choked.

What worked: Add this to your Podfile post_install:

post_install do |installer|
  installer.pods_project.build_configurations.each do |config|
    config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
  end
end

This tells Xcode to skip arm64 when building for the simulator, forcing Rosetta simulation. You lose native simulator speed, but you gain a build that actually compiles.

Flipper

Flipper was included by default in the React Native template and it broke constantly on M1. The errors changed with every Flipper release. Flipper-Folly 2.6.9 was a particularly memorable one. I spent an afternoon pinning Flipper versions before realizing I’d never once used it to debug anything.

# In your Podfile, comment out:
# use_flipper!()

React Native’s built-in dev menu and Chrome DevTools still work. Flipper caused more build failures than it ever saved in debugging time, at least on our project.

The kitchen sink Podfile fix

By mid-2022, most RN projects on M1 had converged on some version of this post_install block:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
    end
  end
end

Not elegant. Got us through six months until we could upgrade.

It got better

React Native 0.66 had already shipped __apply_Xcode_12_5_M1_post_install_workaround(installer) as a template helper by the time I wrote this. If your project was on a recent version, that helper did most of the heavy lifting. For the rest of us on older codebases, the manual Podfile hacks were the only path forward.

By 0.70+, most of the upstream CocoaPods and Flipper issues were resolved. If you’re reading this later and still hitting these problems, upgrade your RN version before trying any of the workarounds above.

The M1 transition was genuinely painful for mobile developers. It’s easy to forget now that everything just works, but there was a solid year where “I got a new Mac” meant “I can’t build the project for two days.”

Back to all writing