Des questions se posent rapidement lorsque on déploie un logiciel chez des clients:

  • Est-ce que chaque client a la même version du logiciel ?
  • Comment connaître la version installée ?
  • Comment connaître les personnalisations apportées pour la version spécifique du client ?
  • Comment retrouver le code et le débugger ?

Nous proposons ici quelques pistes pour répondre à ces questions et mettre en pratique un versionnement efficace de ses applications.

On fait l’hypothèse dans la suite qu’on utilise Git comme outil de gestion des sources.

Méthode de travail

La première étape pour versionner correctement son logiciel consiste à suivre une méthodologie de développement pour pourvoir dire à un moment “ça y est, mon application marche, je peux faire une livraison”.

Une méthodologie éprouvée consiste à suivre ce modèle. Mis à jour récemment, il suggère cependant que des méthodologies plus simples sont parfois mieux adaptés, notamment celle proposée par Github

Comment donner un numéro de version

Manuellement

Il y a la numérotation standard MAJOR.MINOR.

À chaque changement du numéro MAJOR il y a généralement une rupture, de compatibilité, d’interface… Le MINOR indique une sous version du major qui indique souvent des corrections de bugs ou de nouvelles fonctionnalités mineures.

Cependant il manque plusieurs informations, et on peut ajouter le nom du client ou d’un variante -VARIANTE, et le numéro du commit git -7dfea849 pour être certains d’avoir une référence unique.

Conseil : à minima, enregistrez le numéro du commit git. C’est l’élément le plus sûr pour retrouver le code utilisé pour créer l’exécutable.

Note : Sous git, la version est généralement indiquée par un tag. On peut alors automatiser la tâche de création de binaire et de version dans les outils d’intégration continue.

Automatiquement

La plupart des outils de gestion de paquets gèrent les différences de versions et peuvent proposer des règles de numérotation.

Une méthode très simple pour trouver un numéro de version consiste à utiliser une variante de la commande git describe, qui est souvent utilisé comme base par les outils générant des numéros de version.

Par exemple:

  • Les projets python générés avec pyscafhold créent automatiquement un numéro de version à partir du tag git lors de la création d’un package
  • Les paquets Fédora répondent à un format précis de ce genre: 6.0.0-3.fc34. Ils proposent des guides pour versioner
  • Il exite des modules CMake qui génèrent un numéro de version en utilisant git
  • La plupart des IDES permettent d’executer des scripts avant / après la compilation. On peut donc intégrer un script qui génère un fichier version.txt, ou version.h contenant le résultat de la commande git évoquée précédemment.

Un exemple de script :

#! /bin/bash
r=`git describe`
r_code=$?
echo $r_code
version=""
if [ $r_code = 128 ] ; then
# case where no tag is available
    version=`git describe --all --long --dirty`
else
    version=`git describe --long --dirty`
fi

echo $version > VERSION.txt

Comment gérer les versions des librairies utilisées

Comment faire pour ne pas avoir à se poser la question « Est-ce que mon logiciel est compatible avec cette version de la bibliothèque » ?

Librairies externes

C’est à dire dont on est pas les développeurs principaux.

Avec un package manager

Si on dispose d’un package manager, la gestion des dépendances est généralement bien faite et il suffit d’indiquer dans un fichier le numéro de version de la librairie qu’on souhaite utiliser. Il faut pouvoir gérer les conflits éventuels (deux librairies veulent utiliser deux versions différentes de la même sous-librairie) mais en python, ruby et même rust, on isole chaque projet avec un environnement virtuel pour limiter ceux-ci.

Sans package manager

Intégrer les sources au projet

La solution la plus simple d’un point de vu du développeur est de phagociter (comprendre copier-coller) les sources de la bibliothèque dans son projet. Il faut pour cela que la licence le permette et intégrer à la compilation les sources ce qui peut devenir compliqué si les bibliothèques n’utilisent pas le même logiciel de compilation. Il y aura également une veille à faire sur les différents bugs et corrections critiques, pour savoir si l’on doit les intégrer ou non.

Deuxième solution, utiliser un submodule. La démarche est la même, la gestion de la version est différente. Elle offre un plus de rigeur car il n’y a pas de copier-coller possible, donc pas de modifications ultérieures. On garantit l’intégrité du code utilisé. Les changements sont facilement intégrés, il suffit d’une commande git. Il n’y a pas besoin de refaire un copier-coller à chaque fois qu’on veut faire une modification. Le seul point négatif est que lorsqu’on développe en parallèle une librairie et un logiciel, on doit quasiment faire un commit dans le logiciel pour un commit dans la librairie.

Avantages :

  • Pas problèmes de versionnement. La version de la bibliothèque sera la même est intrinsèquement lié à la version du logiciel.
  • La compilation est simplifiée. Elle se déroulent exactement de la même manière sur tous les ordinateurs.

Inconvénients:

  • Il faut gérer les mises à jour de la bibliothèque.
  • Certaines bibliothèques sont difficiles à compiler.
  • Du fait de leurs licences certaines bibliothèques ne peuvent pas être intégrées.
Utilisation des librairies binaires

Soit on est dépendent de la version de la librairie installée sur l’OS cible et il faut la vérifier au démarrage ou croiser les doigts, soit on livre le logiciel avec toutes ses dépendances (assez lourd, mais possible: de nombreux logiciels embarquent tout un navigateur web !).

Librairies internes / développées en parallèle

Se pose également la question pour les bibliothèques internes, dont on suppose qu’on est les principaux développeurs. La problématique est la même en réalité que pour une bibliothèque externe dont on a accès aux sources.

Un exemple concret

Cura ? Gtk ? Qt

Conclusion

  • Utiliser Git et un workflow documenté
  • Utiliser des subrepositories autant que possible