22
Jul/09
0

Build des applications Erlang

Mochiweb crée un squelette applicatif en copiant les sources vers le répertoire destination. Ces sources doivent être compilés pour obtenir un byte code exécuté par le shell Erlang.

Dans le cas d’un fichier simple, la commande erlc peut être appelée directement. Dans le cadre d’une application plus évoluée (et comme pour tous les autres langages compilés), il est nécessaire d’avoir des processus de build un peu plus complexes.

Pour Mochiweb, et comme vu précédemment, un makefile est fourni. Cependant, l’outil make est assez peu intuitif à utiliser, et étant un grand utilisateur de Ruby je me dirige naturellement vers rake.

La première étape sera de recréer les commandes de makefile en Rake.

Installation de l’outil de build

Ruby et RubyGems doivent être installés sur votre système. Ces éléments sont des pré-requis et ne seront pas détaillés ici (Si vous utilisez la version 1.9 de Ruby, RubyGems sera inclus directement).

L’installation de Rake se fait simplement en installant la gem correspondante :

sudo gem install rake

Voilà, c’est tout !

Migration du makefile

Le but ici est de transformer les instructions du Makefile en tâches Rake.

Initialisation

Tout d’abord on crée un fichier Rakefile.rb à la racine du projet.

cd /d/apps/ercm
vim Rakefile.rb

On va d’abord définir l’ensemble des tâches prévues, sans les implémenter. Le fichier ressemblera alors à cela :

desc "Clean workspace"
task :clean
 
desc "Compile the sources"
task :compile
 
desc "Create documentation"
task :edoc
 
desc "Unit tests"
task :test
 
desc "Build the sources"
task :build => [ :compile, :edoc, :test ]
 
desc "Start application"
task :start
 
task :default => :build

Les tâches ont été définies, certaines sont liées (le build est le chaînage des tâches simples précédentes). La dernière ligne du fichier permet de définir la tâche par défaut. On rajoute des commentaires en début de tâche afin de les visualiser par la commande suivante :

$ rake -T
rake build    # Build the sources
rake clean    # Clean workspace
rake compile  # Compile the sources
rake edoc     # Create documentation
rake start    # Start application
rake test     # Unit tests

Les commandes suivantes sont équivalentes :

$ rake build
$ rake

Enfin, on peut chaîner les commandes :

$ rake clean build

Compilation

La compilation sera, dans un premier temps réalisée de façon très basique via la commande système :

erlc -o $root/ebin $src.erl

on demande la compilation du fichier erl dans le répertoire destination (selon OTP).

Il est donc nécessaire de référencer l’ensemble des fichiers src/erl et de créer les règles associées afin de produire un fichier .beam

On peut simplement écrire une tâche de type fichier :

file 'ebin/ercm_sup.beam' => 'src/ercm_sup.erl' do
  system "erlc -o ebin src/ercm_sup.erl"
end
 
task :compile => 'ebin/ercm_sup.beam'

Le problème est que cela n’est absolument pas utilisable en l’état. Il est donc nécessaire d’augmenter les traitements avec des expressions régulières. Il faut donc :

  • lister l’ensemble des sources
  • créer des tâches de type fichier pour chacun des sources
  • ajouter une dépendance à la tâche de compilation vers cette liste de fichiers à produire.

On peut donc écrire la compilation de cette façon :

sources = FileList["#{ROOT}/src/**/*.erl"]
 
objs = sources.map do |src|
  target = File.join EBIN_DIR, "#{File.basename(src, '.erl')}.beam"
  file target => src do
    puts "Compiling #{src}"
    system "erlc -o #{EBIN_DIR} #{src}"
  end
  target
end
 
task :compile => objs

EBIN_DIR est une constante définissant le chemin de destination des fichiers beam. Il est important que la tâche fichier targetprenne en dépendance le fichier src, ainsi la recompilation a lieu pour les fichiers qui ont été modifiés (et uniquement ceux là).

On ne prend pas en compte dans cet exemple les chemins supplémentaires, ni les fichiers d’en-tête. La création du descriptif de l’application non plus.

Nettoyage

Pour remettre le système à zéro, on peut partir sur la règle suivante :

task :clean do
  FileList["#{EBIN_DIR}/**/*.beam"].each { |f| rm f }
end

Documentation

Pour la création de la documentation à partir des sources, on agit un peu de la même manière, la seule différence est qu’il faut déplacer manuellement le fichier html généré vers le répertoire de destination.

html = sources.map do |src|
  target = File.join EDOC_DIR, "#{File.basename(src, '.erl')}.html"
  file target => src do
    puts "Creating documentation for #{src}"
    system "erl -noshell -run edoc file #{src} -run init stop"
    mv src.gsub('.erl', '.html'), EDOC_DIR
  end
  target
end

Démarrage serveur

Le démarrage serveur pourra se faire via Rake, ce qui nous permettra de supprimer les scripts de démarrage, de renforcer les automatismes en ajoutant des dépendances à la tâche, et de bénéficier à l’avenir toutes les commodités de rake.

Cette tâche correspondra pour l’instant à la recopie du script directement dans le fichier Rakfile:

task :start => :build do
  system "erl -pa #{EBIN_DIR} #{ROOT}/deps/*/ebin -boot start_sasl -s reloader -s ercm"
end

Conclusion

Cet article présente une façon de compiler les sources Erlang via un autre outil de build. Le code proposé peut être amélioré et sera sûrement retouché lors de codage plus avancé.

À vous de choisir vos armes !

Filed under: build
Comments (0) Trackbacks (0)

No comments yet.

Leave a comment

No trackbacks yet.