Développement Ada sous Unix


Aide Ada

Vous disposez d'une introduction à Ada en suivant
ce lien . Vous pouvez vous y reporter en cas de besoin.

Vous pouvez accéder aux transparents du cours en suivant ce lien.


Environnement de développement

Avant de modifier le logiciel SDC, vous devez vous familiariser avec un des environnements de développement Ada sous Unix.

Éditeur

Nous vous conseillons d'utiliser Emacs ou XEmacs, puisqu'ils possèdent un mode sensitif à la syntaxe Ada.

Lors du chargement d'un fichier Ada (ie se terminant par ".ads" ou ".adb"), Emacs ou XEmacs passe en mode "Ada" et les mots clés ainsi que les commentaires doivent apparaître en couleurs ou fontes différentes.

Dans le cas contraire, vous pouvez sélectionner le mode Ada manuellement en tapant "ESC", puis "x", puis "ada-mode" et terminant par un retour de chariot.

Compilateur

Nous utilisons pour les TPs le compilateur GNAT (GCC/Ada). Dans ce but, tapez dans la fenêtre où vous travaillez:
    PATH=/usr/local/packages/gnat/bin:$PATH
A titre de vérification, exécutez la commande:
        gnatls -v
vous devez voir apparaître
        GNATLS x.xx ..... etc
X.XX est supérieur ou égal à 3.12. Dans le cas contraire, connectez vous à une autre machine.

Pour compiler à partir d'Emacs ou de XEmacs, n'oubliez pas de positionner la variable PATH comme indiqué ci-dessus avant de lancer l'éditeur.

Vous pouvez installer GNAT librement sur votre PC (sous windows 95/NT ou sous Linux) en le téléchargeant à partir de ftp://ftp.lip6.fr/pub/gnat.

Débogueur

L'utilisation d'un débogueur n'est pas indispensable pour les TPs de ce cours. Cependant, si vous le souhaitez, vous pouvez utiliser gdb.

Assurez vous que votre machine dispose de la bonne version de gdb en tapant gdb. Vous devez voir apparaître :

        [...] lignes effacées
        GDB is free software ....
        [...]
        GDB XXX.gnat.XXX [...]
        [...]
        (gdb) 
Si la version XXX importe peu, le mot gnat doit apparaître. Dans le cas contraire, connectez vous à une autre machine, car vous aurez du mal à déboguer vos programmes Ada.
Tapez quit dans la fenêtre où le message s'est affiché pour sortir de gdb.


Vos premiers pas en Ada

Vous allez maintenant créer, compiler et exécuter l'inévitable "Hello World" en Ada. Pour cela, recopiez le programme suivant dans le fichier hello.adb. Utilisez le copier-coller entre votre navigateur et votre éditeur.
with Ada.Text_IO;
--  Commentaire: Ada.Text_IO est un paquetage predefini en Ada
--               contenant des sous-programmes d'entree/sortie.

procedure Hello is
begin
   Ada.Text_IO.Put_Line ("Hello World.");
end Hello;
Unix est sensible à la casse et différencie hello et Hello. A l'inverse, Ada ne les différencie pas. Par convention, nous devez impérativement enregistrer le code ci-dessus dans le fichier hello.adb. En Ada, toute procédure ne prenant pas de paramètres peut être le point d'entrée de votre programme (il n'y a pas de convention comme en C où le point d'entrée doit s'appeler main).
Pour compiler la procédure Hello et toutes les unités dont elle dépend (dans le cas d'Hello la seule unité dont elle dépend, Ada.Text_IO fait partie de l'environnement Ada et a déjà été compilée) tapez la commande suivante:
        gnatmake -g hello
Le drapeau -g signale à gnatmake que hello.adb doit être compilé avec les informations de déboguage. Si tout se passe bien, la série de commandes exécutées par gnatmake est :
        gcc -c -g hello.adb     --> compile le fichier hello.adb
        gnatbind -x hello.ali   --> verifie que tout est coherent
        gnatlink -g hello.ali   --> edition de liens
L'exécution du fichier exécutable hello devrait afficher à l'écran l'inexorable "Hello World.".

Dans les commandes effectués par gnatmake, la commande gcc effectue la compilation à proprement parler. D'ailleurs si vous aviez voulu seulement compiler hello.adb sans créer un exécutable, vous auriez tapé directement la ligne de commande:

        gcc -c -g hello.adb
La compilation d'un fichier Ada produit un fichier objet (dans ce cas hello.o) ainsi qu'un fichier .ali (ici hello.ali) pour pouvoir vérifier la cohérence de vos sources lors de l'étape suivante (gnatbind).

La commande gnatbind vérifie la cohérence entres les sources Ada qui composent le programme final et produit un fichier qui sert à démarrer le programme Ada. Ici, on génère un fichier Ada appelé dans le cas de votre exemple b~hello.adb.

La commande gnatlink effectue l'édition de liens entre les différents modules objets et le module de démarrage.

Développer rapidement avec GNAT

Les Makefiles que vous trouverez dans les répertoires struct, struct-sol et object sont propres à ces TP et ils visent à vous aider dans votre travail (voir Réaliser et évaluer rapidement votre TP). Cependant, avec gnat, et Ada en général, vous n'avez pas besoin de Makefile. L'outil gnatmake se charge de compiler ou re-compiler les fichiers nécessaires au bon fonctionnement de votre programme. Par exemple, supposons que vous décidiez d'appeler la procédure Hello à partir d'une procédure appelée Autre:
--  Mettez ce code dans un fichier autre.adb

with Hello;
--  En Ada il faut toujours préciser avec des clauses "with ...;"
--  les unités extérieures utilisées dans votre module.

procedure Autre is
begin
   Hello;
end Autre;
Pour créer un autre programme où la procédure Autre est le point d'entrée, il suffit de taper (de préférence dans Emacs/XEmacs):
        gnatmake -g autre
Remarquez que gnatmake ne recompile que le fichier autre.adb, hello.adb étant déjà compilé.

Compiler sous Emacs/XEmacs

Vous pouvez effectuer directement vos compilations sous Emacs/XEmacs. Dans le menu Ada de Emacs sélectionnez Compile. Pour XEmacs, cliquez sur le button Compile. Ceci affiche dans la dernière ligne, ou dans une fenêtre la commande
        gcc -c      OU      make -k
Remplacez cette commande par votre commande de compilation (gnatmake -g hello) et appuyez sur la touche d'entrée. Si votre compilation a des erreurs, vous pouvez passer en revue chaque erreur et voir l'endroit exact de chaque problème en sélectionnant next error dans le menu Ada de Emacs.
Essayez cette fonctionalité en introduisant une erreur dans votre programme hello. Vous pouvez, par exemple, enlever un point virgule.

Déboguer votre programme Ada

Si vous souhaitez utiliser le débogueur gdb, tapez :
        gdb hello
Vous pouvez alors utiliser gdb comme vous en avez l'habitude en posant des points d'arrêt :
        b hello


Problèmes de langage

A quoi servent X'First et X'Last

En Ada, le premier élément d'un tableau X ne se trouve pas toujours à l'indice 0. X'First correspond au premier indice du tableau X et X'Last au dernier. Par exemple, T est un tableau d'entiers dont le premier indice T'First vaut 2 et T'Last vaut 4. S est une chaîne de caractères considérés en Ada comme un tableau. S'First vaut 10 et S'Last vaut 13.
   T : array (2 .. 4) of Integer;
   S : String (10 .. 13) := "STOP";

A quoi sert T'Image (X)

T'Image (X), où T est un type scalaire (entier, énumération, etc), convertit la valeur scalaire X en une chaîne de caractères. Si X vaut 4, Integer'Image (X) retourne "4".

A quoi servent with et use?

"with U;" permet d'importer une unité U et rend donc visible ses déclarations. Par la suite, pour utiliser un sous-programme S visible dans la spécification de U, vous devez qualifier complètement S c'est à dire écrire "U.S" et non pas uniquement "S". Pour éviter de tout qualifier systématiquement, vous pouvez ajouter après la clause "with U;", la clause "use U;". Dans ce cas, lorsque vous écrivez "S", si le compilateur ne trouve pas de "S" local, il va essayer toutes les unités V pour lesquelles une clause "use" a été demandée pour essayer de trouver un "V.S".

Comment convertir une donnée V dans un type T [[ T (V) ]]?

Cette opération se fait par l'opération T (V) où T représente un type d'arrivée et V une variable d'un type compatible avec V.

Comment construire une donnée V de type T [[ T'(X => A, Y => B) ]]

T'(X => A, Y => B) permet de créer un objet de T en imposant que ses attributs X et Y valent respectivement A et B. Il en va de même pour la notation :
return new T'(X => A, Y => B);
Cela permet de réserver de la place mémoire dans le tas avec l'allocateur new et en plus d'initialiser ce nouvel objet en imposant des valeurs aux attributs X et Y.

Quelle est la différence entre T'(...) et T (...)

Comme indiqué dans les deux précédentes questions, T'(...) permet de construire un enregistrement de type T alors que T (...) permet de faire une conversion vers le type T.

A quoi correspond T'Class ?

T'Class permet de représenter tout type qui se trouve dans la hiérarchie du type T. Il faut bien noter la différence avec T. Lors d'une conversion dans le type T'Class, une donnée d'un type dérivé de T ne perd pas la visibilité sur ses méthodes et attributs dérivés alors qu'une conversion dans le type T les lui ferait perdre.

Comment tester si une donnée appartient à un type dérivé ?

Le test conditionnel V in T permet de savoir si V appartient au sous-type T. En général, ce test s'accompagne d'une conversion T'Class (V) ou T (V) selon que l'on souhaite ou non conserver les méthodes et attributs de V.

Pourquoi le programme principal ne s'appelle pas main()

Ada permet d'utiliser n'importe quelle procédure sans paramètre comme programme principal équivalent d'un main. Il n'y a donc pas de convention comme en C où ce programme principal doit avoir un nom bien défini.

Quelle est la différence entre and et and then ?

L'opération booléenne F1(X) and then F2(X) évalue F1(X). Si le résultat est faux, F2(X) n'est pas évalué. L'opération booléenne F1(X) and F2(X) évalue F1(X) ET F2(X).


Problèmes de compilation

Vous n'arrivez pas à compiler.

Vérifiez que vous utilisez la bonne version de GNAT en tapant :
   which gnatmake
qui doit retourner
   /usr/local/packages/gnat/bin/gnatmake
Notez que dès l'instant que vous travaillez sur SDC, vous pouvez utiliser la commande make pour construire SDC sans vous préoccuper de ces problèmes de chemin traités par le fichier Makefile.

Vous n'arrivez pas à compiler à partir d'Emacs/XEmacs.

Vérifiez que vous avez bien dans l'ordre : Notez que dès l'instant que vous travaillez sur SDC, vous pouvez utiliser la commande make pour construire SDC sans vous préoccuper de ces problèmes de chemin traités par le fichier Makefile.

Vous avez des problèmes avec les fichiers ALI.

Vous avez probablement utilisé à un moment donné une mauvaise version du compilateur. Pour reconstruire un programme hello par exemple, positionnez correctement le PATH, puis tapez :
   gnatmake -f -g hello
Le drapeau -f force la reconstruction complète de votre programme. Notez que dès l'instant que vous travaillez sur SDC, vous pouvez utiliser la commande make pour construire SDC sans vous préoccuper de ces problèmes de chemin traités par le fichier Makefile.

Vous n'arrivez pas faire l'édition de liens.

Vous avez épuisé votre place disque sur votre compte. Vous pouvez vérifier ce qu'il vous reste en tapant :
   quota -v
Il ne vous reste plus qu'à faire de la place sur votre compte.

Votre programme s'interrompt violemment.

Votre programme a probablement été mal construit en raison d'un manque de place disque sur votre compte. Reportez vous à la section propre aux problèmes d'édition de liens.

gnatmake ne trouve pas un fichier qui existe pourtant

Vous avez un problème de nommage ou de casse (majuscule/minuscule). Vérifiez que : Par convention de nommage, l'implémentation ou corps d'une unité (procédure, fonction ou paquetage) doit être stockée dans un fichier du même nom (en minuscule) que l'unité suivi du suffixe ".adb" (Ada Body). S'il s'agit de la spec ou spécification d'une unité (procédure, fonction ou paquetage), il faut utiliser le suffixe ".ads" (Ada Specification). Par exemple, la spec du paquetage Values doit être stockée dans le fichier values.ads alors que son corps doit être stocké dans le fichier values.adb.