M1 stacks

Abstract

Bitrise offers the Apple silicon M1 stacks for all credit-based accounts. We recommend using the latest version of our Steps on the M1 stacks.

Apple announced the Apple silicon M1 chip, in 2020. This represents a fundamental change in hardware architecture and it means that in the future, all iOS and macOS development will take place on Macs with Apple silicon. As such, Bitrise is offering a virtualized M1 environment for CI/CD purposes.

Credit-based accounts only

The M1 stack isn't available to legacy, concurrency-based accounts.

Selecting an M1-based stack for your build

You have two options for selecting an M1-based stack, just like with any other stack:

  • Selecting it in the Workflow Editor.

  • Adding it as a meta property in the bitrise.yml file.

Setting an M1 stack in the Workflow Editor

  1. Open your app on Bitrise.

  2. Go to the Workflow tab.

  3. Find the relevant stack selector menu:

    • If you want to set the default stack for all Workflows, find the Default stacks section.

    • If you want to set Workflow-specific stacks, find the Workflow Specific Stacks section and choose a Workflow.

  4. In the dropdown menu, select an Xcode stack with Xcode version 13 or higher.

  5. In the Machine type for the default stack section, select the M1 machine.

    infrastructure-m1-stack-machine-type-selector.png
  6. Click Save in the top right corner.

Setting an M1 stack in the bitrise.yml file

We'll go through how to set an M1 stack as the default stack for your app.

  1. Open your app's bitrise.yml file.

  2. Add a meta entry that will specify the stack ID and the machine type.

    You can find the stack IDs on the system reports page: the filenames without the .log extension are the stack IDs. To use an M1-based stack, you must select one of the stacks with Xcode version 13 or higher. The machine id is g2-m1.8core.

    You can set a default stack or Workflow-specific stacks:

    • For the default stack, add the meta property at the top level of the structure. It should be on the same level as, for example, format_version. We recommend putting it at the end of the file:

      meta:  
        bitrise.io:       
          stack: osx-xcode-13.4.x    
          machine_type_id: g2-m1.8core
      
    • If you want to set a Workflow-specific stack, you need to add the meta entry under the Workflow itself:

      workflows:
        deploy:  
          meta:      
            bitrise.io:       
              stack: osx-xcode-13.4.x
              machine_type_id: g2-m1.8core

      In this example, we're setting a Workflow-specific stack for the deploy Workflow.

Transitioning to M1 from Intel-based stacks

Switching your development environment from Intel-based architecture to Apple silicon is a major change and it affects CI/CD as well. At Bitrise, we've tried to make sure the transition is as seamless as possible: we've updated our Steps and we've installed M1-compatible versions of the most important tools on the M1 stacks.

This means that for the most part, if you use the official Bitrise Steps, your builds should work as they always did. Still, we strongly recommend testing everything locally, on your own M1 machines. You can use the Bitrise CLI to do so.

Bitrise Step versions

Always use the latest version of any Bitrise Step in your Workflow on the M1 stacks! They are designed to be backwards compatible with the Intel-based stacks, too.

There are also some limitations, and some changes to be aware of when it comes to transitioning from Intel-based stacks to M1. We'll go through the most important ones.

Using Rosetta

Rosetta is an emulator/translator designed by Apple to bridge the compatibilities between Intel and Apple silicon processors. It translates Intel-targeting executables so that they can run on M1-equipped machines.

Rosetta has been installed and enabled on our stacks. To use it, add the arch -x86_64 prefix in front of each command you run in your scripts. This tells the system to use x86_64 instructions.

Rosetta limitations

Rosetta can't translate:

  • Kernel extensions.

  • Virtual Machine apps that virtualize x86_64 computer platforms.

Xcode and MacOS version requirement

The most important requirement is that you need to use Xcode 13.0 or above. It is highly recommended to transition to Xcode 13.0 or higher anyway, as Apple no longer accepts apps submitted to the App Store if they were built with older Xcode versions.

As for the operating system, M1 requires MacOS Monterey. Big Sur isn't compatible with Apple silicon. As such, our M1 stacks run on Monterey.

Android SDK version requirement

All Xcode stacks include the Android SDK, too, as part of our support for cross-platform apps.

On M1 stacks, Android 32 is installed, as Google hasn't introduced M1 compatibility to earlier versions.

Changes to Homebrew's default path

Homebrew is the most popular package manager for macOS and it is of course available on Bitrise, on both Intel-based and M1 stacks.

There is one important difference: the default path for packages has changed:

  • On Intel-based Macs, the default path for packages is /usr/local/.

  • On M1-based Macs, the default paths for packages are /usr/local/bin/, /usr/local/share/, and /usr/local/lib/.

This is only important if your build uses hard-coded paths to access Homebrew packages. In that case you need to change the path to the M1 version.

Caching

Caching on Bitrise works on the basis of branches: running the same Workflow on a different branch of a repository creates a different cache archive.

The Cache:Pull Step makes sure that the downloadable cache was generated on the same stack and CPU architecture as the currently running build. If, for example, you are trying to run a build on an Intel-based stack and the Step only finds a cache archive that was generated on an M1-based stack, it won't download the cache. This is in order to avoid stability problems that comes from using cache that was generated on the other CPU architecture.

This means, in practice, that there is only ever one active cache on a given branch: it's either an M1-based or an Intel-based cache but never both. If you run the Cache:Push Step on a Workflow that has a cache archive from a different architecture, the Step will overwrite that cache archive.

Caching Step version requirements

The logic of differentiating between cache archives based on the CPU architecture doesn't work on older versions of the caching Steps:

  • The Cache:Pull Step must be version 2.6.0 or higher. Older versions will download any cache archive they find, regardless of CPU architecture.

  • The Cache:Push Step must be version 2.7.0 or higher. Older versions won't add metadata related to the CPU architecture.

Other known issues and limitations

M1 has some other limitations and known issues. We're working hard at making sure we have a working solution for most use cases.

Android emulation is unavailable

The M1 stacks don't support using an Android emulator in your builds. This is because Bitrise runs your builds on virtual machines and the Apple silicon architecture doesn't allow nested virtualization.

You can, however, still use Firebase Test Lab to run Android device tests on Bitrise: Device testing for Android.

Hanging builds issue

There is a bug in Apple's hypervisor framework that can cause issues in virtualized environments like ours. The issue can occur whenever a simulator is launched: for example, our Xcode Test for iOS Step uses an iOS simulator to run tests. Once the simulator starts, your build can hang indefinitely.

For more information on this issue, please check out this discuss post. The issue has been reported to Apple.