Skip to content

Instantly share code, notes, and snippets.

@progrium
Last active August 20, 2024 22:33
Show Gist options
  • Save progrium/b286cd8c82ce0825b2eb3b0b3a0720a0 to your computer and use it in GitHub Desktop.
Save progrium/b286cd8c82ce0825b2eb3b0b3a0720a0 to your computer and use it in GitHub Desktop.
Setting up M1 Macs for x86 development with Homebrew

Key Points

  • In general, binaries built just for x86 architecture will automatically be run in x86 mode
  • You can force apps in Rosetta 2 / x86 mode by right-clicking app, click Get Info, check "Open using Rosetta"
  • You can force command-line apps by prefixing with arch -x86_64, for example arch -x86_64 go
  • Running a shell in this mode means you don't have to prefix commands: arch -x86_64 zsh then go or whatever
  • Don't just immediately install Homebrew as usual. It should most likely be installed in x86 mode.

Homebrew

Not all toolchains and libraries properly support M1 arm64 chips just yet. Although automatic x86 mode works pretty well, more complex build toolchains use multiple programs that should all be building for the same architecture. Since we often use Homebrew to install these toolchains, it might be best to install the x86 "version" of Homebrew, otherwise it will install arm64 versions of things.

Just be sure to run the Homebrew install command in an x86 shell

$ arch -x86_64 zsh
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

From here, as long as you're in this x86 zsh shell, you can use Homebrew as usual to install x86 packages:

$ brew install go

You'll know it's the right version because it will install into /usr/local instead of the usual /opt. This also means you can install both versions of Homebrew, and arm64 packages will live under the /opt instance. However, unless necessary I wouldn't recommend it because I can imagine accidentally using the wrong version pretty easily. If you only have one version, you can install packages without entering x86 zsh, just prefix with arch -x86_64:

$ arch -x86_64 brew install go

If you install both versions, you'll also need to specify the full path to the brew binary as one will live under /opt and one will live under /usr/local.

Tips

Terminal Trick

If you duplicate your terminal application (Terminal, iTerm, etc) and set the new one to "Open using Rosetta", then you have a quick way into a terminal and shell in either mode. Thanks for the tip @tmc

Golang Cross Compiling

Although used in the examples, if you just want to work with Go, you should be able to just use GOARCH to produce an x86_64 binary using an arm64 go binary. This probably won't work so smoothly if you're using CGO.

Checking Architecture

Remember you can always use the file command on a binary to see what architecture its built for.

@olewishg
Copy link

olewishg commented Mar 4, 2022

@Iron-Ham arch -x86_64 <command> should do the job.

@mfdmitro
Copy link

mfdmitro commented Oct 7, 2022

Beautiful. Exactly what is needed. Thank you.

@tripflex
Copy link

tripflex commented Apr 11, 2023

Configure ZSH to use brew based on arch:

# Multiple Homebrews on Apple Silicon
if [ "$(arch)" = "arm64" ]; then
    eval "$(/opt/homebrew/bin/brew shellenv)"
else
    eval "$(/usr/local/bin/brew shellenv)"
fi

Source: https://stackoverflow.com/a/68443301/378506

@felikcat
Copy link

felikcat commented Sep 1, 2023

Current way to automatically use x86 Brew (arch -x86_64 zsh only).

  • Add these contents inside /Users/${USER}/.zshrc via Vim or other means:
[[ $(arch) = "arm64" ]] &&
    eval "$(/opt/homebrew/bin/brew shellenv)" ||
    eval "$(/usr/local/Homebrew/bin/brew shellenv)"
  • Test if it's functional using by running env, then arch -x86_64 zsh with env afterwards.

@curlup
Copy link

curlup commented Feb 27, 2024

I'd add

if [ "$(arch)" = "arm64" ]; then
    ...
    # default PYENV_ROOT => $HOME/.pyenv
else
    ...
    export PYENV_ROOT="$HOME/.pyenv-x86"
fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment