Configuring my new (new) Mac I: Homebrew
Introduction
In this series of posts I'd like to walk through the process of configuring my new Mac to
- help out anyone else configuring their Mac
- interrogate and reflect on the decisions I make during configuration
- provide a stable reference to conveniently come back to if needed
Package managers
Like mobile app stores, package managers provide a single place to manage installing, updating, and removing programs. Package managers, however, tend to have more of a open-source, power user connotation. Coming from Arch Linux, I like and prefer to use a package manager.
Before I tell you about installing my package manager, however, let's talk about arm and x86.
arm and x86
At the lowest level, computers run “instructions,” e.g. load, store, and add. To run a program on a computer, you must compile or interpret the program as lines of these instructions. An instruction set architecture (ISA) specifies the types of instructions a computer can run and how those instructions should behave.1
You will generally encounter 2 ISAs with everyday computers: smartphones mostly run arm (yes, stylized all lowercase); laptops and desktops mostly run x86. Until the most recent generation, Macs have run x86. However, the newest Macs run arm, with support for x86 programs via Rosetta 2, an emulator that translates from x86 to arm.
Because historically laptops and desktops have mostly run x86, many developer-oriented programs, libraries, even programming languages, lack support for arm. With that in mind, I want the following from my package manager:
- Availability of packages I want/need
- Ease of package installation, update, and removal
- Support for arm where available with x86 as backup
- Commitment to support arm going forward
Step 1: fail
In my first attempt, I dipped my toes into the Nix package manager. However, using Nix to install yabai, a tiling window manager, ended up so messy that I felt the need to purge my Mac. To clean the slate, I tried to re-install macOS, bricked the laptop, and had to return it. I write to you from a second Mac.
Step 2: choose a different package manager
Since I got burned by Nix,2 I'll use the go-to package manager for Mac: Homebrew, which fulfills the 4 requirements from before. The next steps come from this tutorial by Sam Soffes, with some additional steps and explanation where I feel appropriate.
Step 3: install Rosetta 2
For x86 compatibility, we install Rosetta 2. In terminal:3
$ softwareupdate --install-rosetta
Step 4: install x86 Homebrew
Next in terminal:
$ arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
Only run commands you understand and trust. This command means:
- arch -x86_64: With Rosetta 2 to emulate x86,
- /bin/bash -c: use the bash shell to run
- “$(curl …)": the install script from Homebrew
This will set up Homebrew for x86 packages in /usr/local
.
Step 5: install arm Homebrew
Homebrew expects to install arm packages in /opt/homebrew
, so let's create that directory:
$ sudo mkdir -p /opt/homebrew
Since /opt/homebrew
lives on the system level rather than the user level, we request special permission to create the directory by prefixing the command with sudo
, meaning “superuser do.”
We set ourselves as the owner of that directory:4
$ sudo chown -R $(whoami):staff /opt/homebrew
Finally, we go into /opt
and install our arm Homebrew in /opt/homebrew
:
$ cd /opt && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
Step 6: Set PATH
(Almost) all commands you run in terminal actually come from files in your computer. The PATH
environment variable specifies where to look for files for commands.
Recall we installed our arm Homebrew in /opt/homebrew
and our x86 Homebrew in /usr/local
. Also recall I would prefer arm first and x86 as backup. Therefore, we put our arm Homebrew directory before our x86 Homebrew directory in our PATH
.
Where should we modify the value of PATH
? Newer macOS versions have moved from bash to zsh for terminal. This post describes the configuration files for zsh in detail. Short answer: let's set PATH
in the file ~/.zshrc
:5
$ touch ~/.zshrc && echo 'export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"' >> ~/.zshrc
touch
creates the file and echo
puts the export statement into that file.
We need to run our x86 Homebrew through Rosetta 2. For convenience, we can create an alias ibrew
to properly run our x86 Homebrew. Add
alias ibrew='arch -x86_64 /usr/local/bin/brew'
to a relevant zsh configuration file. For example, to add it to our ~/.zshrc
we can use echo
again:
$ echo "alias ibrew='arch -x86_64 /usr/local/bin/brew'" >> ~/.zshrc
Conclusion
To install an arm package, we can run brew install <package>
. In case Homebrew can't find an arm version, we can run ibrew install <package>
to install the x86 version.
Going forward, Homebrew will provide greater support for arm, since Apple has decided to use arm for future Macs. These instructions may soon become out-of-date.
An ISA also specifies data types, registers, etc. outside the scope of this post. ↩︎
Yes, you could argue I misunderstood or misused Nix. Regardless, I have a bad association. Nix also requires a lot of manual configuration, much more than other package managers. ↩︎
You might see
$
notation when people talk about executing commands in terminal. The dollar sign stands for the shell prompt, where you type commands to execute. In the default terminal, your prompt might have%
instead of$
. ↩︎staff
refers to the default group of all users in Mac, so technically we change the owner to the default group of all users. ↩︎~
stands for the user's home directory. ↩︎