At Coletiv we have a lot of Elixir projects, and some of them more recent, others started years ago. Those older projects will, most certainly, use older versions of Elixir & Erlang and, as another thing to take into account, not all elixir versions support all Erlang versions and vice-versa.
Table of compatibility between Elixir and Erlang versions
💡 At the time of writing the article, these were the only versions that existed. Please consult Elixir Documentation on Compatibility and Deprecation to check the newer versions (and if you have some spare time add them here 😋).
If you're constantly jumping from one project to another, it's not doable to uninstall and install the correct Elixir & Erlang versions every time you need to switch. That's where asdf
comes to the rescue. asdf
is a Runtime Version manager and that means that you can literally install any version of Elixir and Erlang on your machine (among others, check them here) and enable them with just a single command. 🤯
Without losing much more time, here's how you can do it!
💡 This article was not possible without the excellent documentation provided by asdf
and the respective Elixir and Erlang asdf
Plugins. Make sure to check them out.
We will split the how-to into three segments
- Installing and configuring
asdf
- Installing Erlang Plugin and Erlang versions
- Installing Elixir Plugin and Elixir versions
Make sure to follow the steps in order, especially the 2. and 3. since sometimes installing the Elixir plugin and versions first can give some problems with the Erlang plugin.
Installing and configuring asdf
We will only cover the macOS with Homebrew on this tutorial step, so we recommend if you're on other OS to follow ASDF Install Doc. Firstly, make sure to clone the latest branch of asdf
. We recommend you to check the latest version on the releases tab of asdf
. In our case, it's v0.8.1
.
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.8.1
Now, if you're using Zsh add this to your ~/.zshrc
. This is needed so that we can call the asdf
commands without having to write the full path of where asdf
is installed. The auto-completion will allow you to receive the list of commands by pressing "Tab" when writing asdf
commands.
. $HOME/.asdf/asdf.sh
# append completions to fpath
fpath=(${ASDF_DIR}/completions $fpath)
# initialise completions with ZSH's compinit
autoload -Uz compinit
compinit
If the shell you're using is Bash, add the following to your ~/.bash_profile
. $HOME/.asdf/asdf.sh
# asdf completions
. $HOME/.asdf/completions/asdf.bash
After this, restart the terminal and you're ready to go with asdf 🥳
If you're one of those guys that aren't sure if it is really installed, on that terminal window you have just restarted type asdf --version
and it should return you the version of asdf
you previously installed.
If for any reason it doesn't return the version, it means that asdf
was not installed properly or you didn't change the correct shell file that locates the asdf
installation.
With asdf
installed, we now need to add plugins to it. Let's start with Erlang!
Installing Erlang Plugin and Erlang versions
Plugins are how asdf
knows how to handle different tools like Elixir, Erlang, Node.js, Ruby, etc.
Before installing the plugin we need to check if we have installed all the dependencies that we need for asdf
to install/run Erlang successfully. Again, in this article we will cover the macOS version, so we recommend you to jump on the asdf-erlang GitHub and follow the instructions given on the section Before asdf install
.
The dependencies asdf
needs for macOS are Autoconf and (if you want to run Erlang observer or debugger) wxWidgets.
For this, you should run the two following commands (bear in mind that Autoconf might take a bit of time to install).
brew install autoconf
brew install wxmac
After these dependencies are installed we can install Erlang plugin via
asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git
If for any reason you get an SSL error installing the Erlang plugin try the following command and then repeat the previous command.
export KERL_CONFIGURE_OPTIONS="--disable-debug --without-javac"
Installing Erlang versions
Now we need to decide what versions we want to install from Erlang. If you do the command asdf list all erlang
, it will prompt you the list of erlang versions that asdf can provide you.
The output of command asdf list all erlang
Now it's the time you look to the table at the beginning of the article and decide what versions you need. In our case 24.0.3
. This way we can install the most recent release that covers the most recent bug fixes & security patches.
So from my list, I will install 24.0.3
and 23.3.4.4
. To install the versions run the commands (change for your versions of course 😜)
asdf install erlang 24.0.3
asdf install erlang 23.3.4.4
and you're good to go! The installation might take a bit of time and some warnings can appear (not having dependency for docs per example is a warning that appears to me).
Installing Elixir Plugin and Elixir versions
For elixir, the process is similar to erlang's, but in this case, we don't have any dependencies to install before we install the plugin. We can jump right away to the command.
asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git
If, once again, you need to consult anything about the elixir plugin you can access their Github repository.
Once you've successfully installed the plugin we can do asdf list all elixir
and choose what option works best for our needs.
The output of command asdf list all elixir
In my case, I will need versions 1.12
and 1.11
. If you check some versions on the list are 1.12.2-otp-24
and others are 1.12.2
. The difference between the first and the second is that in the first we tell this version to be compiled in Erlang OTP 24. On one project we have to work on the 1.12
version and, as I want to take full advantage of working with Erlang OTP 24 I will install the version 1.12.2-otp-24
. On the second project, we use Erlang OTP 23 with Elixir 1.11 so I will install version 1.11.4-otp-23
.
To install the versions is, like in Erlang
asdf install elixir 1.12.2-otp-24
asdf install elixir 1.11.4-otp-23
So now we have the versions installed and we can check if they're installed via the commands asdf list erlang
and asdf list elixir
.
Activating different versions for different cases
Note that now, when you do elixir -v
(and if you don't have any elixir installed rather than the one we installed here) it will not recognise the command.
Why? Simple. We need to enable globally, or locally (by project), the versions we want to use for Erlang and Elixir.
The behavior I want to reach in my system is the following:
- When I'm inside the project directory that uses Elixir 1.11 / Erlang OTP 23 I want to use Elixir 1.11 / Erlang OTP 23 (captain obvious 😅)
- When I'm any other place rather than the project in the first behavior, I want to use Elixir 1.12 / Erlang OTP 24
In order to comply with these two requirements, we will take advantage of the global and local definitions of versions provided by asdf
.
Defining global versions
By defining global versions, we are telling our system "Ok, you will always use the versions defined on this global file, BUT, if you find any local versioning file, use those instead." Basically, it will create a .tool-versions
file on your home folder that is overridden by the .tool-versions
files nested on the directory tree (we will talk about these files in the next section).
To define global versions (for our case will be Elixir 1.12 / Erlang OTP 24) we simply type
asdf global erlang 24.0.3
asdf global elixir 1.12.2-otp-24
And voilá! All your system now has Elixir 1.12 compiled with OTP 24 enabled and working by default. Congratulations 🥳
But, wait a second. If I access the directory of the project I use Elixir 1.11 / Erlang OTP 23 and type elixir -v
it prompts me that I'm using elixir version 1.12! And I don't want this version! For this, we define local versions 😊
Defining local versions
Local versions are defined always inside the directory of where you want that version to work. This type of version defines a file called .tool-versions
inside your directory that will keep the versions you want to use there. To enable local versions type
asdf local erlang 23.3.4.4
asdf local elixir 1.11.4-otp-23
This will create the .tool-version
file and if you check the file content it will have the versions of erlang and elixir defined on the commands above.
And now if you try the command elixir -v
on the directory you defined local version, it will prompt you those versions. In my case, it prompted me that I'm using elixir version 1.11 compiled with OTP 23! Yay 🤩
And we're done! We successfully understood:
- Why do we need a runtime version manager,
- How to install one (
asdf
),
- How to install different versions of Erlang and Elixir,
- Difference between defining a version globally and locally.
Thank you for taking the time to follow me until here, and as always, if you have any questions please write them on our Twitter, and someone from our team (possibly me 😜) will be more than pleased to help you!