Clojure and Doom Emacs on a brand new M1 computer
I've recently landed my first Clojure position and received an m1-powered MacBook. Two months before that, I had also bought myself an m1 MacBook air and had to set up Clojure to use it in my projects. Since I had no experience using macOS whatsoever I had to do some googling and managed to get a pretty simple setup running.
There are lots of tutorials out there on how to set up m1 laptops for Clojure usage, but there are a few quirks that aren't yet documented, such as how to get clj-kondo
and parinfer
to work in it. I'll try to cover these steps in this post, while also showing how to set up doom emacs and some other stuff I ended up using myself.
Let's get to it:
Table of contents:
Installing Java and Clojure
This post will describe two ways of installing Java and Clojure: one will use homebrew and the other will install things manually.
Using homebrew:
We'll go the easy route here: we will use Homebrew to install Zulu (an m1 native version of the JVM), Clojure, Java, and Leiningen. To do so, we'll start by adding homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
After installing, homebrew will ask us to add it to our PATH. We'll do so and move on to installing Java, Clojure, and Leiningen:
arch -arm64 brew install zulu clojure/tools/clojure leiningen
With the above done, we'll now simply add our JAVA_HOME
to our PATH:
export JAVA_HOME="/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home"
To verify our setup, we can simply run clojure
and open up a REPL.
Manual installation:
We will start by downloading Azul's Zulu m1 build from their downloads page. With the download done, we'll open the zip
file and copy the zulu-17.jdk
folder to /Library/Java/JavaVirtualMachines/
. We'll also set the JAVA_HOME
variable:
export JAVA_HOME="/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home"
With JAVA_HOME
set up, it is time to install Leiningen, which will also install Clojure. To do so, we'll simply follow Leiningen's instructions.
With the above done, we can now verify our setup by running clojure
.
Doom Emacs
My editor of choice is Doom Emacs. To use it, we'll need to first download emacs. This will be done using homebrew:
brew tap railwaycat/emacsmacport
brew install --cask emacs-mac
With the step above done, we'll now move into getting Doom Emacs:
git clone --depth 1 https://github.com/hlissner/doom-emacs ~/.emacs.d
~/.emacs.d/bin/doom install
Lets now configure it so we can use tools such as CIDER and clojure-lsp. This can be done by changing the .doom.d/init.el
file. We'll start by uncommenting lsp
, and clojure
(under :lang
). We will also want to add +lsp
to that clojure
expression, making it (clojure +lsp)
. Having done that, we'll run ~/.emacs.d/bin/doom sync
and our pretty basic Clojure environment will be set up.
Clj-kondo
Adding +lsp
to clojure
in init.el
made doom add clojure-lsp
to our emacs configuration. Clojure-LSP comes with clj-kondo
, but, for some reason I do not know, flycheck
won't recognize it, so we'll probably also want to install kondo as a separate executable. To do so, we'll need to install GraalVM.
Setting up GraalVM on an m1 device currently requires using a snapshot, so we'll simply use it. Follow this comment to get it up and running. (The file you should download is graalvm-ce-java17-darwin-aarch64-dev.tar.gz
). After setting up, also add the GRAALVM_HOME
variable to PATH
-it should match the value for the JAVA_HOME
for Graal.
We can now compile and install clj-kondo on an m1 device:
git clone https://github.com/clj-kondo/clj-kondo.git
cd clj-kondo
script/compile
Now simply add it to your PATH and you'll be able to use clj-kondo
in flycheck
.
Parinfer-rust
There is currently no releases of parinfer-rust
for m1 devices. This means we need to compile it ourselves. We'll need to install rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
We'll then move into compiling parinfer-rust:
git clone https://github.com/eraserhd/parinfer-rust.git
cd parinfer-rust
cargo build --release --features emacs
After compiling it, we'll move it to emacs:
mkdir ~/.emacs.d/.local/etc/parinfer-rust
mv target/release/libparinfer_rust.dylib ~/.emacs.d/.local/etc/parinfer-rust/parinfer-rust-darwin.so
We'll activate parinfer on our doom config by uncommenting parinfer
in ~/.doom.d/init.el
and adding (use-package! parinfer-rust-mode)
to our ~/.doom.d/packages.el
file and run ~/.emacs.d/bin/doom sync
And that's pretty much it for a basic setup :) Hope someone finds this useful