Setting up M1 Mac for Clojure development

By Mitesh (@oxalorg)

I recently bought an M1 Macbook Air with 16 GB RAM. Below is a log of how and what I downloaded on my machine for a full stack Clojure development experience.

The M1 is an ARM chip and thus the software which runs on it must be compatible with the ARM instruction set instead of the x86 instruction set.

Fortunately I’ve had no problems moving from Linux/WSL to the M1 full time. There were a few minor hurdles, but nothing has been a deal breaker yet.

The first thing I did was setup my Apple ID. Then I wanted to download my most used apps which I did (without brew):

  • Slack
  • Discord
  • OBS
  • Dropbox
  • Firefox developer edition
  • Docker for Mac
  • HomeBrew - https://brew.sh

HomeBrew (or simply “brew”) is a package manager for macOS. I haven’t had a great experience dealing with some of the brewisms, but it has a huge repertoire and it just works.

So let’s start brewing

# mpv the best media player
brew install —cask mpv
brew install --cask keepassxc # save your ℀
brew install --cask flux # save your 👀
brew install --cask maccy # clipboard manager
brew install youtube-dl
brew install jq wget coreutils shellcheck tree cloc

What is --cask here? Cask is a way to install GUI application using homebrew.

Compatibility note

In the earlier days I think it was necessary to install x86 binaries in a specially rosseta2 terminal, but I’ve never had to do that.

For example you must have seen people asking you to do this before running brew install on specific software:

/usr/bin/arch -x86_64 zsh

But I’ve never had to do this. I think the newer versions of MacOS automagically detect x86 binaries and run them under rosseta2 without having to do anything at all.

I’ve never once worried about this incomaptibility except for not being able to run certain Docker containers (which is also quite rare).

Java & Clojure

It’s really simple to install JDK, Clojure CLI tools, and leiningen using homebrew.

# java/jdk, we need this for clojure
brew install openjdk
brew install leiningen
brew install maven
brew install clojure/tools/clojure

I chose to not install brew install openjdk@17 explicitly, because leiningen and maven depend on the latest openjdk so that gets installed anyways. If you want a specific version like say JDK v11, then you can also do something like brew install openjdk@11.

Then put the path of openjdk@11 first in your $PATH var in shell so clojure picks that up.

If the above does not work for you, try running this with sudo perms and see if that works as a fix:

sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk

Babashka

Babashka has become such a huge part of my everyday workflow nowadays. So let’s install that ASAP

brew install borkdude/brew/babashka

Node & NPM

I mainly work on Clojurescript with shadow-cljs which only needs node and npm installed.

brew install node@14

Fonts

I use Iosevka as my choice of font, which is easy to install using brew.

Unfortunately there’s a rendering performance issue with Iosevka on Emacs + MacOS. It was a hard bug to find, but switching to fira-code fixes those performance issues.

brew tap homebrew/cask-fonts
brew install —cask font-iosevka
brew install —cask font-fira-code

Emacs on mac m1

There are a lot of ways to install emacs on the m1, but I found emacsmacport to be the best in the sense that it works out of the box and as expected 🙂

brew tap railwaycat/emacsmacport
brew install --cask emacs-mac
ln -s ~/projects/dotfiles/emacs.d ~/.emacs.d

Then I changed the CAPSLOCK to CTRL to avoid the emacs pinky and also because who uses caps lock 😂

Go to System Preferences → Keyboard → Caps and select it as “control modifier”

Corgi Emacs

My choice of emacs configuration layer is Corgi Emacs, it’s a lightweight version of spacemacs/doom aimed at Clojure users. So do give it a try!

Terminal

A lot of Mac users prefer to use iTerm2, and it has lots of benefits. But this time around I didn’t really find a need for it, so I’m just using the built-in terminal.app

macOS now ships with zsh as the default shell. So the first thing I did was install oh-my-zsh and link my .zshrc dotfiles

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
ln -s ~/projects/dotfiles/shell/zshrc ~/.zshrc

Now my zsh config started complaining that it didn’t find tmux. Any terminal I open launches a tmux instance automatically. This way I almost completely live in tmux and the terminal.app works just fine for that! So let’s install tmux and some other terminal helper/utilities

brew install tmux
brew install tmuxp
brew install ripgrep
brew install fzf
brew install fd
brew install direnv

Then I generate an ssh key. Folks remember to use ed25519 algorithm as RSA is now being deprecated.

ssh-keygen -t ed25519

Docker

Docker for Mac was installed using their website and it runs as expected. I haven’t had any issues uptil now as most of the images I run are well supported for ARM.

Terraform

A lot of terraform plugins had to be updated to newer versions which support Darwin ARM builds.

brew install hashicorp/tap/terraform

Conclusion

All in all I am extremely happy with this machine. The battery life is amazing, there is no FAN noise, it never heats up, and software runs and builds much faster than my ~9 year old custom built PC.

One thing I hate is that it only has 2 ports and can only drive a single external monitor. Both of these are minor annoyances for me, but not enough to give up on this laptop.

Ref: my dotfiles repo. Thanks

Mitesh Shah

@oxalorg