Developing a React Native app on an M1 Mac without Rosetta

David J Harding
9 min readJul 19, 2021

After purchasing a new MacBook Air with Apple’s new M1 processor, I ran into problems getting a working development environment for React Native apps. Although I am not new to development or React Native, each step of the way I ran into a number of issues including compilation errors and linking failures.

I searched the internet for solutions and found a lot of workarounds that ultimately resulted in setting up and running everything in Apple’s x86 compatibility mode, using Rosetta. After piecing together information I found all over, but never getting everything to work properly, I decided to figure out how to get a full development environment working for React Native with support for both iOS and Android simulators as well as Flipper while running everything natively on Apple’s new silicon, the M1 processor.

This article will step you through the process of getting your environment working. I assume a working knowledge of React Native development and the associated tools as well as comfort with the Terminal command line. Let’s get started.

Xcode and Command Line Tools

First of all, let’s get Xcode and the command line tools installed. We can install Xcode via the App Store or by downloading it from the Apple developer site. I used the App Store and installed version 12.5.1 at the time of writing this article. Once we have Xcode installed (it will take a while), we need to install the command line tools as these are needed by many of the formulae in Homebrew. There are two ways we might install the command line tools: downloading them from the Apple developer site or using the xcode-select command in the Terminal. For this article, I used the Terminal method.

Installing by Downloading from Apple

To install the command line tools by downloading them from the Apple developer site, head over to the More Downloads section of the developer site and select the matching version of command line tools.

Installing via the Terminal (Recommended)

To install the command line tools from the Terminal, launch the Terminal app. Do not use a version of Terminal opened with Rosetta. At the terminal prompt run:

Terminal showing command to install command line tools

Follow the instructional prompts from there.

Configure Xcode to use Command Line Tools

Now make sure to point Xcode to the version of the command line tools we just installed. To do this launch Xcode, open the “Preferences…” item under the Xcode menu, go to the “Locations” section and select the version of command line tools we just installed from the Command Line Tools drop down.

Locations preference screen for selecting the command line tools version

Homebrew

Next we will need to install Homebrew. If you have already installed Homebrew using Rosetta or any arch command workarounds you will have to uninstall it fully and reinstall following these instructions. For the purposes of this article, we are starting from a fresh install of MacOS without any Homebrew installed at all.

Installing Homebrew is easy. Simply follow the documented installation instructions from the Homebrew website. At the time of writing, the command to install Homebrew is:

Terminal showing command to install Homebrew

Homebrew will give us instructions on how to configure our shell environment at the end of the installation. Follow them as explained. Afterwards, it is best to close the Terminal and open a new one to ensure it has the new shell environment settings. After we complete this step, here is how our .zprofile should look:

Ruby

The version of ruby bundled with MacOS is largely there for backwards compatibility reasons. Let’s get the most recent version of ruby with support for the M1 processor using the following command:

Terminal showing command to install ruby using homebrew

Follow any instructions for setting up our shell environment that are printed out at the end of the brew install command above. As before, to be safe, close the Terminal and open a new one for future commands. Once we have completed this step, our .zshrc should look like this:

Node, Watchman, FFI, and CocoaPods

Now we need to install a few more things to get ready for React Native development. Run each of the commands below from the Terminal, following any setup instructions output at the end of each command:

Creating a React Native Project

To make all of this work on an M1-powered Mac, we will have to tweak the configuration of each of our React Native projects. Begin by creating a new React Native project:

Terminal showing command to create a new react native project

Configuring the Project for iOS

Now we need to make a couple of adjustments to our Podfile to enable Flipper and tell CocoaPods to allow more than the current architecture during builds. Modify the ios/Podfile as follows (N.B. For screen reader users — I have attempted to make this article accessible to the most people possible. However, there do not appear to be any great solutions for embedding a diff within an article. As the following diff is an image, here is a direct link to the diff on github):

Github diff of Podfile showing changes to support Flipper and allowed architectures for pods. Please follow the prior link to get the actual git diff which I hope will work better with screen readers.

Now we can install our pods by running the following command in the Terminal:

Terminal showing command to install pods

Force the Creation of a Bridging Header

In order to get our app working properly on iOS we need to force Xcode to add a bridging header to our project. Open the project’s workspace (the pod install command above will have created this workspace for us). Select the project’s folder in the left panel and right click to add a new file. Select “Swift File” and press “Next”:

First step of adding a new file to our project showing Swift File selected

In the dialog that opens, make sure you have selected the project folder name under the ios folder of the project. Give it a name such as ForceBridgingHeader.swift and press “Create.”

Second step of adding a new file to our project showing the file location and name

At this point we will be prompted by Xcode to create a bridging header. We will press “Create Bridging Header” in the dialog.

Prompt from Xcode asking to create a bridging header

Running in an iOS Simulator

To get our project to run in an iOS simulator we need to first install the simulator. Open Xcode and select “Preferences…” from the Xcode menu item. Go to the “Components” section of the preferences and choose the version of the simulator you want to use.

Xcode preferences Components section showing simulators available for installation

Before we can actually build and run our project in a simulator, we will have to tell Xcode to exclude arm64 on simulators. Open the project’s workspace and to go the “Build Settings.” Under “Excluded Architectures” for both Debug and Release, add arm64 for any iOS simulator SDK.

Xcode project build settings showing Excluded Architectures setting

Now we can finally run our app in the simulator by entering the following command in the Terminal at the top level of the project folder.

Terminal showing command to launch the react native app in the iOS simulator
Our app running successfully in the iOS simulator
Success!

Configuring the Project for Android

In order to build and run our application on Android we must first get a version of Android Studio that supports arm64-based simulator images. At the time of writing, the Arctic Fox version in beta supports this. Head over to the Android Studio preview site and download Arctic Fox. This will install next to any full release version of Android Studio that you may have already installed.

Installing an AVD

Launch the preview version of Android Studio we just installed. In the welcome screen, click on “More Actions” and then “AVD Manager.”

Welcome screen from Android Studio Preview showing “More Actions” call to action

Press the “Create Virtual Device” button. From the “Phone” section, choose a device such as a Pixel 5 and press the “Next” button.

Android Studio screen showing a new virtual device type being selected

Choose a system image from the recommended tab such as release R (API level 30). The key thing is that the ABI indicates that it is arm64. Then press “Next.”

Android Studio dialog showing the selection of an arm64-based system image for the new virtual device

In the next screen we can give our virtual device a name and press the “Finish” button.

Android Studio screen showing the new virtual device being given a name

Running in an Android Simulator

Before we can run the application in the Android simulator we will need to configure our project and shell environment. Start by going into the android/ directory within our project and creating a file named local.properties. In this file enter a single line (replacing david with your username):

Next open ~/.zshrc and add ANDROID_SDK and modify the path to include the Android SDK platform-tools as follows, keeping in mind that “david” should be replaced with your username (N.B. you can get the github diff here):

Github diff of modifications to .zshrc file to add android settings

Now open android/gradle.properties in our project folder and bump the version of flipper to 0.91.1 (N.B. you can get the github diff here):

Github diff of gradle.properties with Flipper version change

Next run ./gradlew clean within the android directory of the project.

Terminal showing command to clean the android project using gradle

At this point we should launch the Android Virtual Device that we set up earlier by opening the preview version of Android Studio, clicking on “More Actions,” then “AVD Manager,” and in the resulting dialog click on the play icon in the row next to the arm64-based simulator image we configured above.

Virtual Device screen from which the newly created virtual device is launched

Now we can build and run our application in the Android simulator using the following command from the top level directory of our project:

Terminal showing command to launch the react native project in the android simulator

Flipper

Earlier we made a few configuration changes to setup support for the Flipper debugging tool. In order to use Flipper, we need to download and install the desktop application from the Flipper site. To use it, launch Flipper while any simulator is running.

Flipper debugging tool connected to the react native project

Congratulations!

At this point we have a fully working development environment for React Native applications on an M1-powered Mac without having to use any arch or Rosetta workarounds. We are able to run our app in both the iOS as well as Android simulators and use Flipper for debugging.

I have created an example project on GitHub that follows this article. If you get stuck or lost, you can use the commit history and diffs to help find your way.

If this article has been helpful please share it with your friends and colleagues, star the repo on GitHub, leave a clap on this article, or drop me a comment. Thank you, and happy coding!

--

--

David J Harding

Brooklyn-based Entrepreneur, Product and Engineering Manager with 25 years of experience crafting successful, innovative products. Opinions my own.