Migrate brew formulas from Intel to ARM on M1
I pre-ordered the Macbook Pro M1 in November 2020, so you can imagine everything was running under Rosetta2. It wasn’t even a question back then 😅
Now ARM is more supported. I naturally wanted to switch and get the maximum binaries and applications running into native ones.
It is not a trivial situation, and when it comes to solving it, everyone has their way to dot it, and I guess it depends on your needs.
I recommend reading https://github.com/Homebrew/discussions/discussions/417 and http://tenderlovemaking.com/2022/01/07/homebrew-rosetta-and-ruby.html.
I was struggling with the fact to support two versions of Homebrew on my machine, and I feel I’m not alone on that!
But If you have to support any old version of a binary, you are very likely to be forced to maintain two versions of Homebrew.
When it comes to supporting a particular set of dependencies, the best way would be using containers. Still, if it’s (really, unfortunately) your daily project, you might want the comfort of running it on the host.
Configuration
I needed two terminals to make that happen, my main one, Iterm, and whatever other you want to pick. I picked up Alacritty because it wasn’t supporting ARM back then, but now it does. However, you always can force it to run as x86_64.
Once on a terminal running natively, you can install the second version of Howbrew running the installer https://brew.sh. You will get the install under `/opt/homebrew` instead of `/usr/local`, but the previous will stay.
On my Zsh, Bash and Fish, I set the prefix depending on ARCH get by the terminal and promoted it on the PATH.
ARM_HOMEBREW_PREFIX="/opt/homebrew"
INTEL_HOMEBREW_PREFIX="/usr/local"case "$(uname -m)" in
"arm64")
HOMEBREW_PREFIX=${ARM_HOMEBREW_PREFIX}
echo "Start Home Brew as ARM64 M1 Sillicon ✅"
;;
"i386"|"x86_64")
HOMEBREW_PREFIX=${INTEL_HOMEBREW_PREFIX}
echo "Start Home Brew under Rosetta 2 Intel Emulation x86_64 🤔"
;;
*)
echo "Which Processor Architecture is that? [$(uname -m)]"
;;
esacexport PATH=${HOMEBREW_PREFIX}/bin:${PATH}
Fish version:
set -l ARM_HOMEBREW_PREFIX "/opt/homebrew"
set -l INTEL_HOMEBREW_PREFIX "/usr/local"switch (uname -m)
case arm64
set -g HOMEBREW_PREFIX $ARM_HOMEBREW_PREFIX
echo "Start Home Brew as ARM64 M1 Sillicon ✅"
case i386 x86_64
set -g HOMEBREW_PREFIX $INTEL_HOMEBREW_PREFIX
echo "Start Home Brew under Rosetta 2 Intel Emulation x86_64 🤔" case '*'
echo "Which Processor Architecture is that? [(uname -m)]"endfish_add_path -m --path $HOMEBREW_PREFIX/bin
So far so good. I added a bit of logic to be warned if I install a formula already present under x86_64, mainly to remove it if not legit anymore. Generally speaking, I’m not a fan of having two versions of the same formula installed but you may need to. Let’s take, for instance, running new and old versions of ImageMagick.
/usr/local/Homebrew/bin/brew list | grep imagemagick
=> imagemagick@6/opt/Homebrew/bin/brew list | grep imagemagick
=> imagemagick
If you have to compile something depending on OpenSSL, like Ruby, for instance, it might be a good idea to manage that as well:
# Begin Section: Open SSL
if [[ -d ${HOMEBREW_PREFIX}/opt/openssl@1.1 ]]
then
printf "Set ${BLUE}RUBY_CONFIGURE_OPTS with OPEN SSL${NC}\n"
export RUBY_CONFIGURE_OPTS=--with-openssl-dir="${HOMEBREW_PREFIX}/opt/openssl@1.1"
else
printf "${RED}********************************************${NC}\n"
printf "${YELLOW}The OPEN SSL files cannot be found!${NC}\n"
printf "${RED}********************************************${NC}\n"
fi
# End Section: Open SSL
I had to compile an earlier version of Ruby under Rosetta due to mysql2 dependency.
gem install mysql2 -v '0.5.3' -- --with-ldflags=-L/usr/local/opt/openssl@1.1/lib --with-cppflags=-I/usr/local/opt/openssl@1.1/include"
or
bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl@1.1/lib --with-cppflags=-I/usr/local/opt/openssl@1.1/include"
Conclusion
It is not the best situation to be in, but on the other hand, with a bit of discipline is manageable 😅
In case those notes can help someone.