Un aperçu de la technologie GPR

GPR diagram

La mise en œuvre des différents éléments constitutifs d’un projet logiciel peut s’avérer être une tâche fastidieuse. C’est pour cela que, depuis de nombreuses années, un ensemble d’outils ont été développés afin de faciliter, de sécuriser et de systématiser celle-ci.

Cet article est une introduction à l’une des solutions existantes qu’est la technologie GNAT GPR (Gnat PRoject).

Cet outil permet de gérer simplement et efficacement des projets multi-langages de tailles et de natures extrêmement variables. Même si cette technologie a été introduite dans le cadre de la mise en œuvre de projets Ada, elle n’est pas dévolue à ce langage.

Généralités

La technologie GPR permet de construire et de gérer simplement et efficacement des projets multi-langages.

Les fichiers GPR peuvent dépendre d’autres fichiers GPR de façon modulaire.

Cette modularité simplifie l’intégration de systèmes complexes tout en permettant la réutilisation de projets existants.

La technologie s’appuie entre autres sur l’outil GPRbuild.

Celui-ci interprète un fichier GPR (.gpr) contenant une description du projet.

Il y a plusieurs types de GPR et donc de projets :

  • les projets « normaux »,

  • les projets agrégeant d’autres projets « agregate »,

  • les projets étendant d’autres projets « extended »,

  • les projets librairie « library »,

  • les projets abstraits « abstract ».

À ces types viennent se greffer des notions de « limited » et de projets enfants. Les projets limités permettent de gérer des dépendances circulaires entre projets. Les projets enfants reprenant un peu la notion d’unité enfant Ada transposée à la notion de projet.

Un fichier GPR décrit entre autres :

  • les fichiers sources contenant les points d’entrée,

  • des définitions de types et de variables propres au projet,

  • le ou les langages utilisés,

  • les répertoires contenant les fichiers sources,

  • le répertoire dans lequel les produits de compilations doivent être placés (*.ali, .o, etc.),

  • le répertoire contenant les binaires ou les librairies générés,

  • les paramètres à appliquer aux outils utilisés (compilateur, binder, éditeur de lien, dévermineur, etc.),

Cette description se fait au travers d’une syntaxe proche de l’Ada.

 with "../configuration.gpr";

 library project Convol is

   for Object_Dir   use "_obj";
   for Library_Name use "convol";
   for Library_Dir  use "_lib";
   for Source_Dir   use (".");

   for Language use ("C");

   package Builder  renames Configuration.Builder;
   package Compiler renames Configuration.Compiler;

end Convol;

Dans le cadre de projets plus ou moins complexes, l’articulation des GPR reflète l’architecture de ou des applications et éventuellement celle du système.

Note

En conséquence, une articulation compliquée et peu claire des GPR est probablement le reflet d’un problème bien plus profond à savoir une mauvaise architecture/découpe dans son ensemble de l’application ou du système.

Un browser intégré à l’environnement de développement GPS (GNAT Programming Studio) permet de visualiser clairement les dépendances entre GPR. Ci-dessous un projet type mis en œuvre par Systerel qui est complexe mais qui reflète aussi une bonne structuration.

Dépendances pour un projet complexe

Dépendances pour un projet complexe

Exemple

Cet exemple très simple va présenter les GPR de types :

  • projet « normal »,

  • projet librairie « library »,

  • projet abstrait « abstract ».

Ainsi que la mise en œuvre :

  • des préprocesseurs Ada du GNAT et C,

  • d’un projet multi-langages.

Dans cet exemple on décrit au travers des GPR :

  • le fichier source contenant le point d’entrée,

  • la définition d’un type de build et d’une variable de ce même type,

  • les langages utilisés,

  • le répertoire dans lequel les produits de compilations doivent être Placés,

  • le répertoire contenant le binaire et la librairie générés,

  • les paramètres à appliquer aux compilateurs.

L’application générée réalise la convolution d’une image. L’ossature est en Ada 2012 et le code implémentant le produit de convolution est en C. On veut pouvoir avoir un build DEBUG et un build RELEASE de l’application. Ces deux types de build sont différents aussi bien sur les paramètres de génération que sur le comportement du programme qu’ils produisent.

L’arborescence projet est la suivante :

Arborescence projet

Arborescence projet

Avec :

  • config.gpr : GPR « abstrait » permettant de mettre en commun un certain nombre de définitions,

  • test_convol.gpr : GPR « normal » générant l’exécutable « test_convol.exe »,

  • convol.gpr : GPR « librairie » générant la librairie statique « libconvol.a »,

  • test_convol.adb : point d’entrée Ada de l’application,

  • image.ad[sb] : paquetage définissant une image et implémentant ses services,

  • convol.c : implémentation du produit de convolution.

Note

Pour ce qui suit et dans des cas simples le pragma Debug peut aussi satisfaire au même besoin en ce qui concerne le comportement du programme suivant le type de build2.

Il est assez courant de définir un build DEBUG et RELEASE ainsi qu’une target NATIVE et CROSS.

Les codes mis en œuvre sont succinctement :

source de test_convol.adb

test_convol.adb

source de image.ads

image.ads

source de image.adb

image.adb

source de convol.c

convol.c

config.gpr

Par le biais de ce GPR « abstrait », on va à la fois définir le type de build et les définitions partagées entre GPR.

Plus précisément, on va définir ce qu’est un build DEBUG et un build RELEASE ainsi que les options de compilation associées.

Pour le build DEBUG, on positionne les macros __DEBUG__ et Build_Kind qui seront pris en compte lors de la phase de preprocessing des sources.

Pour le build RELEASE, on considère les warnings des compilateurs comme des erreurs.

Au final le fichier config.gpr sera :

source de config.gpr

config.gpr

convol.gpr

Par le biais de ce GPR « librairie », on va fournir les informations requises pour la construction de la librairie statique libconvol.a. On note aussi que la configuration du compilateur est celle définie par le GPR config.

source de convol.gpr

convol.gpr

test_convol.gpr

Par le biais de ce GPR « normal », on va expliciter le point d’entrée Ada de notre programme. Tout comme le précédent GPR, il s’appuie sur la configuration du compilateur définie par le GPR config.

source de test_convol.gpr

test_convol.gpr

Pour générer l’application on peut soit utiliser l’IDE GPS et sélectionner le build souhaité dans la vue scenario.

Copie d'écran de l'IDE GPS pour le build

Copie d’écran de la sélection du type de build.

Soit appeler directement l’outil GPRbuild en ligne de commande en spécifiant le build souhaité.

Copie d'écran de la ligne de commande pur le build

Copie d’écran de la construction en ligne de commande.

Dans les deux cas, les produits de compilation seront les mêmes :

Produits de compilation

Produits de compilation

Conclusion

La technologie GNAT GPR apporte une solution efficace et évolutive à la mise en place de projets pouvant être à la fois volumineux et complexes. Cette technologie s’intègre très aisément au sein d’un environnement de développement.

Commentaires