With Elixir 1.1.0-beta I made the switch from whatever version of Elixir was available in Homebrew, to bleeding edge compiled from source. It was surprisingly easy!

Get the Latest Source

Following the installation instructions:

$ git clone https://github.com/elixir-lang/elixir.git
$ cd elixir

In this case I want to clone directly from the elixir-lang repo, not from my fork. This is what I’ll use to execute most of my Elixir programs locally, so unless I’m specifically testing a change I’m making, I don’t want to use my own fork, where I may be swapping branches back and forth.

Change the Version Number

The convention seems to be to leave the version number alone after a release is tagged, which means that if there have been any commits since the release, and you simply build from the source on the master branch, you will build something different than already exists for that name. This can complicate bug reporting if you say you were using “1.1.0-beta” and yours isn’t the same as someone else’s.

Since I know the latest tagged release was 1.1.0-beta, let’s see where that appears in the source:

$ git grep 1.1.0-beta
CHANGELOG.md:## v1.1.0-beta (2015-09-05)
VERSION:1.1.0-beta
src/elixir.app.src: {vsn, "1.1.0-beta"},

Based on this I need to change the version number in two places, the VERSION file and the src/elixir.app.src file:

It’s not a good idea to make changes directly on master of someone else’s repository, so I’m going to make a branch. I often use the date for the branch name if I’m not working on something specific.

$ git checkout -b 20150907
# edit src/elixir.app.src and VERSION to: 1.1.0-20150907

Now review the changes. In particular MAKE SURE that your editor does not add a newline to the VERSION file, or you may see failing tests in IEx.

If you are a vim user you can avoid this by editing the file in binary mode: vim -b VERSION.

$ git diff
diff --git a/VERSION b/VERSION
index 2ff3577..ec10cd1 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.0-beta
\ No newline at end of file
+1.1.0-20150907
\ No newline at end of file
diff --git a/src/elixir.app.src b/src/elixir.app.src
index 3c099d4..e63cf7e 100644
--- a/src/elixir.app.src
+++ b/src/elixir.app.src
@@ -1,6 +1,6 @@
 {application, elixir,
 [{description, "elixir"},
- {vsn, "1.1.0-beta"},
+ {vsn, "1.1.0-20150907"},
  {modules, [
  elixir
   ]},

Build From Source

And then build and test it:

$ make clean test

If all the dots are green, carry on!

If that didn’t work… you may need to install Xcode so that the make command will be available. See https://developer.apple.com/xcode/download/.

Modify Environment

Next I modified my ~/.bash_profile so that the newly built elixir and iex scripts would be first on my path:

export ELIXIR_HOME=/Users/wsmoak/projects/elixir/bin
export PATH=$ELIXIR_HOME:$PATH

It’s important to make sure that $ELIXIR_HOME appears in the PATH before /usr/local/bin where Homebrew puts the things it is managing.

I used to always start a new terminal session to get bash profile changes to take effect, but eventually I learned about:

$ source ~/.bash_profile

And now

$ elixir -v
Elixir 1.1.0-20150907

$ iex -v
Erlang/OTP 18 [erts-7.0.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Elixir 1.1.0-20150907

$ which elixir
/Users/wsmoak/projects/elixir/bin/elixir

Updating and Re-Building

When you come back for your next Elixir programming session, here’s how to update to the lastest code on master.

NOTE: It’s probably a good idea to shut down anything that is using elixir or iex. In my brief test, when the elixir/bin directory was yanked out from under a running process, a Phoenix app started throwing errors, while iex seemed to survive.

$ cd /path/to/elixir
$ git checkout master
$ git pull
$ git checkout -b YYYYMMDD
# edit VERSION and src/elixir.app.src
$ make clean test

It’s up to you whether to commit the version number change on the branch, or just revert it:

$ git checkout VERSION src/elixir.app.src
ingenii:elixir wsmoak$ git status
On branch YYYYMMDD
nothing to commit, working directory clean

Either way, the branch is there to remind me what revision I was working with on a given day, in case things start going wrong.

If I needed to update again the same day, I would just add the time to the branch name so it is unique.

Switch back to Homebrew’ed Elixir

If something goes wrong, simply revert your changes to ~/.bash_profile, making sure that /usr/local/bin is on your PATH.

Start a new terminal session and check which elixir and elixir -v to see what is in use.

Uninstall Homebrew’ed Elixir

I uninstalled the Homebrew version of Elixir I had been using because I’d rather be in control of all the bits. :)

$ brew uninstall elixir
# it complained that there was still another version installed
$ brew uninstall --force elixir

Build From Source Distribution

If something goes wrong using the latest compiled version from master we may want to drop back to the most recent release to compare behavior.

Since I uninstalled Elixir 1.0.5 from homebrew, how do I get it back?

There are precompiled and source archives listed on the release page:

https://github.com/elixir-lang/elixir/releases/tag/v1.0.5

I’m going to download elixir-1.0.5.tar.gz into ~/Downloads folder and then expand and build it in my /Applications directory because that’s where I keep software that I use as-is.

$ cd /Applications
$ tar -xzvf ~/Downloads/elixir-1.0.5.tar.gz
$ cd elixir-1.0.5
$ make

Now I’ll add a line to ~/.bash_profile so that I can easily switch versions by un-commenting one or the other:

export ELIXIR_HOME=/Applications/elixir-1.0.5/bin

Recall that earlier we also added ELIXIR_HOME to the PATH:

export PATH=$ELIXIR_HOME:$PATH

Note: This also works with the 1.1.0-beta source distribution, which you can download from https://github.com/elixir-lang/elixir/releases/tag/v1.1.0-beta

DIY Source Archive

If for some reason there isn’t a source distribution available for a given tag, you can make one with git archive. Here’s an example using the v1.0.5 tag:

Make sure you’re in the same directory as the clone of elixir-lang/elixir from above:

$ cd /path/to/elixir
$ git archive --prefix=elixir-1.0.5/ -o elixir-1.0.5.tar v1.0.5

This will create an uncompressed tar with the contents of the v1.0.5 tag, with a top-level directory of elixir-1.0.5.

Clone the v1.0.5 Tag

Alternately, here’s how to clone the v1.0.5 tag directly from the repository. This will take up more space on disk because it has all the git metadata included, but is preferable if you ever need to make changes, so that git diff will work.

$ git clone --branch v1.0.5 https://github.com/elixir-lang/elixir.git  elixir-1.0.5
Cloning into 'elixir-1.0.5'...
remote: Counting objects: 81849, done.
remote: Compressing objects: 100% (60/60), done.
remote: Total 81849 (delta 17), reused 0 (delta 0), pack-reused 81787
Receiving objects: 100% (81849/81849), 29.59 MiB | 1010.00 KiB/s, done.
Resolving deltas: 100% (45201/45201), done.
Checking connectivity... done.
Note: checking out '3eb938a0ba7db5c6cc13d390e6242f66fdc9ef00'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

$

Since I’m not going to make changes, being in a ‘detached HEAD’ state is fine.

Now build it. Remember to check the README file of the branch/tag you are working with. In this case the instructions are the same.

$ cd elixir-1.0.5
$ make clean test

In this case it’s not necessary to change the version number, because this is the official tagged source for the 1.0.5 version.

Now I can edit ~/.bash_profile to switch the location of ELIXIR_HOME and control which version is used.

Remember to start a new terminal session or execute source ~/.bash_profile to reload changes.

Wrap Up

We’ve seen how to build multiple versions of Elixir from source and how to switch between them. This will allow us to

  • test out beta versions,
  • reproduce bugs that people report on specific versions, and
  • check whether bug are still there on master.

Copyright 2015 Wendy Smoak - This post first appeared on http://wsmoak.github.io and is CC BY-NC licensed.

References