Wednesday, September 26, 2007

Building Erlang with Rake

I've recently started using Erlang on a project. This is my first foray into Erlang and I'm using Joe Armstong's new book Programming Erlang as introductory material. It is a great introduction to the language, although I wish it covered more of the OTP. I suppose there is the OTP Design Principles guide but sometimes a good paper book written in conversational style is better when you are learning.

In the book Joe describes building an Erlang project using make and most of the downloadable bits of Erlang code use make too; this makes sense, make is virtually ubiquitous. However the other components of this project are Ruby on Rails applications and make heavy use of Rake, so I figure why subject myself to Make when I can use the beautiful Rake.

Here is my Rakefile for building an Erlang project.

require 'rake/clean'

INCLUDE = "include"
ERLC_FLAGS = "-I#{INCLUDE} +warn_unused_vars +warn_unused_import"

SRC = FileList['src/*.erl']
OBJ = SRC.pathmap("%{src,ebin}X.beam")

directory 'ebin'

rule ".beam" => ["%{ebin,src}X.erl"] do |t|
sh "erlc -pa ebin -W #{ERLC_FLAGS} -o ebin #{t.source}"

task :compile => ['ebin'] + OBJ
task :default => :compile

This gives you rake compile which builds all the .erl files in the src subdirectory into the .beam files in the ebin directory. Files will only be built if they have changes since the last build. You also get rake clean which deletes all the .beam files from the ebin directory.

I much prefer this over the equivalent Makefile and it is much easier to extend since you have the full power of Ruby at your disposal.


Update: Fixed bug when compile many files from after clean.


Jean-Baptiste Quenot said...

Sorry, but:

** Invoke compile (first_time)
** Invoke ebin (first_time, not_needed)
rake aborted!
Don't know how to build task 'ebin/shop1.beam ebin/shop.beam ebin/geom.beam'

Sean Geoghegan said...

Thanks for that. There was a bug in the compile dependencies that caused problems when builing many files after a clean. It should work now.

I fixed this a while ago but forgot to update my blog post so thanks for reminding me.

Anonymous said...

I have also used Rake with erlang.
Here is what I came up with when I need to rebuild eunit.
require 'rake/clean'
CLOBBER.include 'ebin'
SRC_TO_BIN = [/src(\/.*\.)erl/,'ebin\1beam']
BIN_TO_SRC = [/ebin(\/.*\.)beam/,'src\1erl']

beams = ['ebin'] +'src/*.erl').gsub(*SRC_TO_BIN)
task :default => beams
directory 'ebin'

rule(%r{^ebin/.*\.beam$} => lambda { |fn| fn.gsub(*BIN_TO_SRC) }) do |t|
`erlc -pa ebin -Iinclude +warn_unused_vars +nowarn_shadow_vars +warn_unused_import -oebin #{t.source}`
-- Mike Berrow

CresceNet said...
This comment has been removed by a blog administrator.
Benjamin Nortier said...

Thanks for the Makefile!

Just a note (and for future readers), it works fine with rake 0.7.3, but didn't work for me with rake 0.7.1...