Composition des solutions

Les solutions de CiviKey sont des solutions dites « composées » : chaque solution tire parti d’une ou plusieurs solutions pour ne faire qu’ajouter des fonctionnalités, sans devoir recopier des projets essentiels. La solution Core est la solution de base, elle regroupe les projets du noyau permettant par exemple de lire et sauvegarder les données de CiviKey. Ensuite la solution Certified apporte un host d’exécution du Core, ainsi que des plugins essentiels, elle est donc composée du résultat de la solution Core. Enfin Contrib est une solution « bac à sable » où tout le monde peut venir tester son plugin. Elle est composée par la solution Certified et contient donc tous ses plugins, et en y ajoutant les plugins développés par les développeurs de la communauté Open Source ou par les étudiants d’In’Tech INFO.

Création d’un « Runtime »

Pour que ces solutions puissent être composées par d’autres il a fallu réfléchir à un système assez souple pour ne lier trop fortement deux solutions entre elles. Il faut par exemple que le développement de Core puisse continuer en parallèle sans impacter Certified.

Pour cela nous avons ajouté un dossier « Runtime » à chaque solution (sauf Core car c’est la solution élémentaire) contenant les résultats de la (ou des) Solutions qui la compose : Certified/Runtime contient donc les binaires de Core. Les projets de la Solution composée n’ont qu’à faire référence aux binaires du dossier Runtime pour les utiliser et les développeurs de la Solution composée gèrent leur répertoire Runtime : ce sont eux qui choisissent de prendre en compte on non les nouvelles versions des composants sur lesquels ils s’appuient.

Ce dossier Runtime peut être mis sous contrôle de SubVersion (ou autre gestionnaire de code source), c’est d’ailleurs ce que nous faisons à Invenietis. De cette façon, les Solutions sont autonomes et il est aisé de « remonter dans le temps » du projet : les sources sont en phase avec les versions exactes des composants sur lesquels la Solution est fondée.

Les « Saveurs »

Lorsqu’on compile une solution dans Visual Studio il est possible de choisir dans quel mode se déroulera la compilation. En mode Debug, pour que les « #If Debug », « Debug.* », etc. soient pris en compte, cela permet de résoudre les bugs plus facilement (via des outils de diagnostic). En mode Release, pour que les performances soient optimales.

Mais il n’y a pas que Debug et Release : si ces « modes de compilation » sont les plus courants, il peut s’avérer nécessaire de gérer d’autres « saveurs » : processeur, optimisations plus ou moins agressive, versions gratuites vs. payantes, signé ou non, etc. La notion de « Saveur » généralise le « mode de compilation » : un même composant logiciel est disponible pour le développeur en plusieurs « saveurs » et celui-ci doit pouvoir les choisir.

Le Runtime de chaque Solution contient un sous dossier par « saveur », typiquement Debug et Release, qui contiennent les résultats des compilations correspondantes. Il est donc possible de choisir quelle « saveur » utiliser simplement en changeant les chemins des références.

Notons qu’il est même possible d’intégrer la version dans la « saveur » : rien n’empêche de travailler en même temps sur des composants « ReleaseOld » et « ReleaseNew » (afin de vérifier que le plugin que l’on écrit marche aussi bien avec deux versions différentes du même composant.

Malheureusement, changer toutes les références à chaque changement de configuration est très fastidieux (une solution comme Certified possède, à date, 14 projets, chaque projet possède au moins 3 références au Core, il faut donc changer 42 chemins à chaque fois que l’on veut passer en Debug/Release).

Pour éviter cette opération, le dossier Runtime contient un répertoire Current. Ce dossier est une copie exacte d’une des saveurs disponible dans Runtime. La solution n’a plus qu’à faire référence systématiquement aux binaires de Current : pour changer de configuration, il suffit de remplacer ces binaires par les binaires de la saveur que vous voulez utiliser. Il est ainsi très facile par exemple d’utiliser le Core en Release dans la solution Certified en mode Debug (ou le contraire).

Pour le moment ce dossier Current est à gérer manuellement, il faut le créer, le mettre en « ignore list » dans SubVersion, et faire un export des binaires de Debug / Release dedans afin de pouvoir les utiliser. Nous spécifions actuellement un petit utilitaire pour automatiser et sécuriser cette opération, il devrait permettre aussi de faire un update automatique des « saveurs » disponibles.

Finissons sur une remarque générale : nous proposons ici un moyen simple de gérer un très classique problème du développement logiciel. Dans le bon vieux temps des compilateurs C, des fichiers make permettaient de se lier à des librairies différentes en fonction de valeur de macro (la « saveur » à produire). Visual Studio n’intègre pas cette possibilité (subordonner ses références au « mode de compilation ») car elle a souvent été mal utilisée et source de problème.

Pour notre part, nous estimons avoir besoin de ce petit jeu : compiler facilement ma Solution avec tous les checks intégrés dans la saveur « Debug » du Core pour faciliter la traque des bugs… alors que ma Solution, elle-même, est compilée en « Release ».

Ou le contraire : j’ai confiance dans le Core, je travaille en Debug et utilise le Core en Release. Bref, les différentes combinaisons sont possibles… Mais nous imposons néanmoins UNE contrainte forte : les « saveurs » doivent être interchangeables au sens où elles doivent toutes contenir les mêmes composants.

Exemple pratique : Faire fonctionner Contrib après un checkout

Voici toutes les étapes pour mettre en œuvre la solution Contrib directement après un checkout. Pour information le dépôt de Contrib est à l’adresse suivante : https://civikey.svn.codeplex.com/svn/trunk/Contrib Voici la marche à suivre :

  1. 1 - Aller dans Runtime/, créer le dossier Current/ et l’ajouter en « ignore list » dans votre client SubVersion.
  2. 2 - Exporter les dll d’un des deux dossiers de Runtime/ vers Current/.
  3. 3 - Lancer la solution Contrib.VS2008.sln.
  4. 4 - Compiler une première fois la solution.
  5. 5 - Dans les propriétés du projet Artefact aller dans la section « Déboguer » puis choisir « Output/Debug (ou Release selon votre mode de compilation)/CiviKey.exe » comme programme de démarrage. Attention cette configuration s’enregistre dans un fichier .user, qui ne doit pas être commit car cette configuration est liée à chaque poste.

Une fois cette configuration faite vous n’aurez plus qu’à changer le mode de compilation de Contrib ou de changer les dll de Runtime/Current/ pour compiler avec les saveurs qu’il vous faut.