Compiling Erlang/OTP and Elixir from sources
It’s risky to be on the edge, but it’s also breathtaking to test out latest features of your
beloved programming language/environment. Despite being rolling release Archlinux still doesn’t
provide you with the latest Erlang/OTP and Elixir versions in it’s default repositories. Besides,
Erlang/OTP in Archlinux is compiled without documentation, which give you no chance to use awesome
new Elixir feature in iex, when you can read docs on Erlang functions with h/1 helper. So why
won’t we compile our own Erlang/OTP and Elixir;)
Installing dependencies
First of all, we need to install some dependencies:
$ pacman -S fop libxslt openssl jdk-openjdk flex wxgtk2
Explanation of dependencies:
libxslsandfopare required to compile documentationopensslis needed by crypto applicationjdk-openjdkis needed to compile jinterface, which is
The Jinterface package provides a set of tools for communication with Erlang processes
flexis needed by megaco application, which is
- and
wxgtk2needed to compile wx application, which is used, for example, byobserver
Installing latest Erlang/OTP from github
NOTE: I’ll be downloading everything we need into ~/src directory.
Now, let’s clone Erlang/OTP repository and setup some environment variables:
~/src $ git clone 'git@github.com:erlang/otp.git'
~/src $ cd otp
~/src/otp $ export ERL_TOP=`pwd`
~/src/otp $ ./configure --prefix=${XDG_DATA_HOME:-$HOME/.local/share}/erlang
~/src/otp $ export PATH=$ERL_TOP/bin:$PATH
~/src/otp $ export FOP_HOME=/usr/bin
~/src/otp $ export MAKEFLAGS=-j8
ERL_TOP is used in compilation time, and in our case should be set to current working directory,
which is repo’s root. Passing --prefix option to the ./configure script, we tell compiler,
where do we want to install Erlang/OTP, once it compiled. In my case, the path is set to
$HOME/.local/share/erlang. I suggest you to do the same, to ease the way you can
remove Erlang from your system by simply deleting this directory.
Updating PATH variable is needed for documentation to compile
successfully.
Setting up FOP_HOME is for docs compilation too. MAKEFLAGS will be passed to the make
commands, -j8 means I want to compile in parallel using 8 cores. You can adjust it as you want,
by changing number after -j.
Next, we are compiling and installing Erlang/OTP and documentation:
~/src/otp $ make
~/src/otp $ make docs DOC_TARGETS=chunks
~/src/otp $ make install
~/src/otp $ make DOC_TARGETS=chunks install-docs
DOC_TARGETS is need to be set to one of the following type:
- chunks
- man
- html
I’ve set it to chunks, so it won’t compile docs in all available formats, to save time and space.
And finally, update your PATH environment variable, so we would use newly installed Erlang while
building Elixir from sources:
~/src/otp $ export PATH=${XDG_DATA_HOME:-$HOME/.local/share}/erlang/bin:$PATH
Installing latest Elixir from github
NOTE: run this steps in the same shell session with updated PATH environment variable.
Let’s clone Elixir repo, and compile it with tests afterwards, to be sure everything works properly:
~/src/otp $ cd ..
~/src $ git clone 'git@github.com:elixir-lang/elixir.git'
~/src $ cd elixir
~/src/elixir $ make clean test
The case when you got some errors in the last step above is beyond the scope of this post, sorry:).
So, finally let’s install our freshly compiled elixir into $HOME/.local/share/elixir for the
same reason we did it within Erlang/OPT installation:
$ PREFIX=${XDG_DATA_HOME:-$HOME/.local/share}/elixir make install
Final steps
Don’t forget to update your PATH environment variable by adding this lines into .bash_profile
(if you using bash):
PATH=${XDG_DATA_HOME:-$HOME/.local/share}/erlang/bin:$PATH
export PATH=${XDG_DATA_HOME:-$HOME/.local/share}/elixir/bin:$PATH
Wrap up
You can test your installation by running iex:
$ iex
Erlang/OTP 25 [RELEASE CANDIDATE 3] [erts-12.3.2] [source-71b0d4e7cf] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.14.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> h :lists.reverse
reverse/1
@spec reverse(list1) :: list2 when list1: [t], list2: [t], t: term()
Returns a list with the elements in List1 in reverse order.
reverse/2
@spec reverse(list1, tail) :: list2
when list1: [t], tail: term(), list2: [t], t: term()
Returns a list with the elements in List1 in reverse order, with tail Tail
appended.
Example:
> lists:reverse([1, 2, 3, 4], [a, b, c]).
[4,3,2,1,a,b,c]
iex(2)>
Here you go, in my desktop it took approximately 10 minutes to set all up and running.
Have a nice and productive day!