Jul/090
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 target
prenne 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 !