Compiler des projets ADA sous linux

Surprised

1. Installation du compilateur

Le compilateur de référence de l’Ada est GNAT (GNU Ada Translator). 

Ce compilateur sous licence GPL est édité par la société Adacore qui publie également une version « pro » et payante dont nous ne parlerons pas ici.

L’installation se fat des plus facilement en installant le paquet (qui est d’ailleurs disponible dans les dépôts sous ubuntu) : 

apt-get install gnat 

2. Documentation

Tout d’abord les liens indispensables : 

GNAT user’s guide

GNAT reference manual

Ainsi qu’un site contenant un abrégé du guide d’utilisation de GNAT (en français).

3. Fichier de test

Pour chacun des exemples, nous allons utiliser un classique « hello world » : hello_world.adb

Petit rappel : Les fichiers .ads correspondent aux .h du langage C, tandis que les .adb correspondent aux .c (en une vision grossière…)

Voici donc le code source utilisé : 

with Ada.Text_IO; -- Bibliothèque
 
procedure hello_world is -- Annonce de la procédure "Hello"
begin -- Début de la procédure "Hello"
  Ada.Text_IO.Put_Line("Hello, world!"); -- Code qui imprime "Hello, world!" à l'écran
end hello_world; -- Fin de la procédure "Hello"

4. Compilation

4.1 Compilation simple

La compilation simple (cad d’un fichier seul, sans hiérarchie de projet) ne requiert rien de plus que notre fichier .adb : 

gnatmake -a hello_world.adb

Comme on peut le voir dans le guide abrégé de GNAT, l’option -a nous permet de tout compiler en effectuant totalement l’étape de link.

Nous obtenons alors (si tout vas bien) 3 fichiers dans le même répertoire : 

  • hello_world.ali (qui contient entre autre la liste des paquetages utilisés)
  • hello_world.o (fichier objet qui contient la liste des symboles)
  • hello_world (fichier exécutable ELF)

Cependant il apparaît assez vite le problème de hiérarchiser les projets ou tout simplement de séparer les fichiers générés lors de la compilation. La prochaine étape nous explique cela.

4.2 Compilation de projets

La compilation d’un projet devient vite un casse tête en ligne de commande. Le plus simple est alors de mettre en place un fichier de projet qui va contenir toutes les informations nécessaires à la compilation du projet complet. Ces fichiers de projet portent l’extension gpr (Gnat Project).

4.2.1 Fichier gpr simple

Voici un fichier .gpr simple  : 

project hello_world is

   for Languages use ("Ada");
   for Object_Dir use "obj";
   for Source_Dirs use ("src");
   for Exec_Dir use "bin";
   for Main use ("hello_world.adb");

   package Linker is
      for Default_Switches ("ada")  use (
            "-g"
      );
   end Linker;

   package Ide is
      for Debugger_Command use "gdb";
   end Ide;

end hello_world;

Ce qu’il faut retenir :

  • Les premières lignes permettent de définir les répertoires de destination des fichiers générés par la compilation.
  • La seconde partie permet de donner les options de compilation ainsi que les options de link. Nous verrons cela plus loin.

Ici nous avons donc regroupé les fichiers sources dans le répertoire src, les fichiers objets dans le répertoire obj… Les langages acceptés sont Ada et assembleur (s) et le fichier contenant le main est hello_world.adb

4.2.2 Inclusion de sous projets

Il est parfois utile de développer des sous-projets séparément afin de les tester plus facilement. Il est alors possible d’inclure le fichier gpr de ces sous-projets directement dans le projet principal pour tout compiler en une seule fois.

Il suffit d’ajouter la ligne suivante en entête du fichier gpr principal : 

-- include the framework project 
with "framework/framework.gpr";
-- include here your others subprojects

4.2.3 Directives de compilation et de link

C’est ici que notre fichier gpr devient particulièrement intréressant. En effet, nous allons maintenant donner toutes les directives de compilation et de link de notre projet (les sous projets inclus peuvent donc être compilés ou linkés avec des options différentes). Par exemple : 

package Linker is
      for Default_Switches ("ada")  use (
            "-g",                     --debug option
            "-T/[…]/framework/lib/linker_script.ld",     --extern linkerscript include
            "--section-start .zconf=0x40040000",        --ld option
            "-Lframework/lib",                 --extern library dir include
            "-lposix"                     --extern library
      );
end Linker;

Dans notre exemple il n’y a qu’une seule librairie externe incluse, mais il est très aisé d’ajouter d’autres répertoires ou d’autres librairies. On peut facilement imaginer la longueur de la ligne de commande si nous n’avions pas utilisé de fichier de projet…ça fait peur ! Surprised

4.2.4 Compilation du projet

La compilation de notre projet se résume maintenant à une simple commande :

gnatmake -P hello_world.gpr

Attention, il ne faut pas oublier l’option -P qui signale au compilateur qu’il doit travailler avec un projet.

Après exécution de cette commande, nous obtenons bien nos fichier .ali et .o proprement rangés dans le répertoire obj, ainsi que l’exécutable dans le fichier bin. Il ne reste plus qu’à tester notre programme :

./hello_world 

qui nous donne

Hello, world!  

Et pour terminer en beauté, un makefile qui nous facilite encore plus le travail : 

clean :
    @echo suppression des fichiers obj et bin
    gnatclean -P hello_world.gpr

all :
    @echo compilation du projet
    gnatmake -P hello_world.gpr

La commande gnatclean associée au fichier gpr permet de supprimer tous les fichiers générés lors de la compilation du projet. Ainsi il n’est pas nécessaire de faire plusieurs rm dans le makefile. Là encore il ne faut pas oublier l’option -P qui précise à gnat qu’il traite un projet.

Cet article est terminé, j’espère qu’il vous aura évité bien des compilations fastidieuses ! Wink

{jcomments on} 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *