Wednesday, November 2, 2011

Tutorial: Getting Started with Erlang and Rebar

Introduction

I have been investigating the Erlang language and a logical place to start was with using its standard tools for building an Erlang application. Apparently Rebar is the default Erlang release management tool. Starting there, this tutorial illustrates how to use the tool to get a simple application project started. Once you complete this tutorial, you will be able to deploy a completely self-contained application that has a full copy of Erlang embedded in it, and automatically compiled executables. The application will be SMP-capable.

Tutorial

As a prerequisite, follow these instructions on how to build rebar. You will require it for later steps.

We then start with creating your application directory:
mkdir exemplar
cd exemplar/
Next, copy your build of rebar into your application directory:
cp ../../rebar .
Next, invoke rebar to have it generate your skeleton application:
./rebar create-app appid=exemplar
You should see this output:
==> exemplar (create-app)
Writing src/exemplar.app.src
Writing src/exemplar_app.erl
Writing src/exemplar_sup.erl
Next, lets prepare the build environment to automatically generate a release:
mkdir rel
cd rel
../rebar create-node nodeid=exemplar
You should see this output:
==> rel (create-node)
Writing reltool.config
Writing files/erl
Writing files/nodetool
Writing files/exemplar
Writing files/sys.config
Writing files/vm.args
Writing files/exemplar.cmd
Writing files/start_erl.cmd
Next, lets go back to our root application directory:
cd ..
Next, configure rebar to automatically generate the release by introducing this line to your rebar configuration file:
echo "{sub_dirs, ["rel"]}." >>rebar.config
cat rebar.config
You should see this output:
{sub_dirs, ["rel"]}.
Next, compile the application:
./rebar compile
You should see this output:
==> rel (compile)
==> exemplar (compile)
Compiled src/exemplar_sup.erl
Compiled src/exemplar_app.erl
Next, generate the release:
./rebar generate
You should see this output:
==> rel (generate)
Next, lets start the application:
rel/exemplar/bin/exemplar start
Oops, you will see this if it was already running:
Node is already running!
So lets stop the application that was running previously:
rel/exemplar/bin/exemplar stop
You should see this output:
ok
Next, lets start the application, opening an interactive console to it:
rel/exemplar/bin/exemplar console
You should see this output:
Exec: /home/rbuck/dev/tools/erlang/tests/exemplar/rel/exemplar/erts-5.8.5/bin/erlexec -boot /home/rbuck/dev/tools/erlang/tests/exemplar/rel/exemplar/releases/1/exemplar -mode embedded -config /home/rbuck/dev/tools/erlang/tests/exemplar/rel/exemplar/releases/1/sys.config -args_file /home/rbuck/dev/tools/erlang/tests/exemplar/rel/exemplar/releases/1/vm.args -- console
Root: /home/rbuck/dev/tools/erlang/tests/exemplar/rel/exemplar
Erlang R14B04 (erts-5.8.5) [source] [smp:4:4] [rq:4] [async-threads:5] [hipe] [kernel-poll:true]

Eshell V5.8.5 (abort with ^G)
(exemplar@127.0.0.1)1>
Congratulations, the application runs. Lets stop the application:
(exemplar@127.0.0.1)1> q().
You should see this output:
ok
Let's be good citizens and hook in Git as our source control system of choice:
git init
Let's create a Makefile to simplify life; why remember all those commands when you already know make. Add the following Makefile to your application root:
REPO       ?= exemplar
TAG = $(shell git describe --tags)
REVISION ?= $(shell echo $(TAG) | sed -e 's/^$(REPO)-//')
VERSION ?= $(shell echo $(REVISION) | tr - .)

.PHONY: rel deps

REBAR=./rebar

all: deps compile

deps:
@$(REBAR) get-deps

compile:
@$(REBAR) compile

rel: deps compile
@$(REBAR) generate

clean:
@$(REBAR) clean

relclean:
rm -fr rel/exemplar

distclean: clean relclean
@$(REBAR) delete-deps

docs:
@$(REBAR) skip_deps=true doc

test:
@rm -rf .eunit
@mkdir -p .eunit
@$(REBAR) skip_deps=true eunit
Next, add a git-ignore list so that generated artifacts are not inadvertently added to git:
echo "ebin/" >> .gitignore
echo "rel/exemplar/" >> .gitignore
Next, lets check everything into git (be sure that you initially run `make distclean` to prevent build artifacts from being checked in):
git add .
git commit -m "initial commit"
Next Steps

Next steps for me will be to:
  • add unit test capabilities
  • transform this into a simple hello-world server that responds to console requests
  • add mochiweb support, changing the application into a library
  • add webmachine support
  • lastly, test the hello-world web server using Node.js and nodeload

5 comments:

  1. excellent tutorial.

    two comments :
    - can you appid and nodeid to use different names?
    - more than 2 apps under the same nodeid.

    ReplyDelete
  2. I follow until

    ./rebar generate

    at which point I get the error "exemplar: : Missing application directory."

    ReplyDelete
  3. Inaimathi,

    I was getting the same error for a long time. I solved it by editing rel/reltool.config and changing: {app, examplar, [{mod_cond, app}, {incl_cond, include}]}

    to: {app, examplar, [{mod_cond, app}, {incl_cond, include},{lib_dir, ".."}]}

    but then ./rebar generate did not work either, saying it could not create spec file. I solved that by cd'ing into the rel directory then running ../rebar generate. Then it finally worked.

    ReplyDelete
  4. edit rel/reltool.config like this:-

    {sys, [
    {lib_dirs, ["../.."]},

    ReplyDelete