Retour d'expérience sur un portage de windows vers linux
Quel est le contexte? Thales transportation systems travaille notamment dans deux domaines différents : parking et transport. Ces deux activités, jusqu'alors complètement indépendantes, vont, petit à petit, être amenées à se regrouper au sein d'une même borne qui distribuerait des tickets de parking et de transport. Chacune des deux applications tourne sous un OS diffèrent. La problématique est donc de faire fonctionner une application Visual C++ Windows sous un Linux standard.Open Wide est intervenu sur cette partie en tant qu'expert dans le monde Linux présentant des compétences reconnues dans le portage d'application. Le portage représente environ 80000 lignes de code réparties dans 20 modules pour une moyenne de 7 fichiers par module. Le code utilise largement l'API Visual C++ de Windows; le principal choix technique fut de développer une couche d'abstraction : la libwinapi, une librairie d'interface entre l'API Windows et l'API Linux. Pour les fonctionnalitées additionnelles (les COTS) telles que le client FTP, la communication CORBA et la base de Données, nous n'avons eut qu'à chercher dans le monde du libre pour trouver les équivalents Linux des DLL Windows, et réécrire les interfaces entre l'application principale et les librairies Open Source.
La libwinapi
Ce choix technique présente énormément d'avantages tant du point de vue technique, que gestion du projet. En effet, 135 fonctions de l'API Windows portées sont facilement testées unitairement et assurent ainsi un risque minimum lors de l'étape suivante qui est l'exécution des tests fonctionnels. Par la suite, l'intégration de modifications dans le code Windows original ou l'ajout de nouveaux modules représente un travail moindre : seules les quelques nouvelles fonctions spécifiques Windows devront être portées.
Ainsi, la libwinapi permet actuellement d'utiliser les timers, les threads, les sockets, les sémaphores, les mutexes, les sections critiques, les pipes, les événements, une base de registre (en lecture seule), et toutes les fonctions standards de manipulation de fichiers, de dossiers, de fichiers de configuration (.ini), de chaînes de caractères, de temps, les constantes et les types. Du point de vue technique, la libwinapi n'est pas intrusive, elle est complètement indépendante du code de l'application principale. Cela permet de ne pas surcharger le code de directives préprocesseur qui perturbe la lisibilité du code et d'assurer au maximum la compatibilité Linux et Windows.
Il reste tout de même quelques modifications nécessaires au niveau du code du client. Tous les fichiers utilisant l'API Windows (contenant #include windows.h) doivent maintenant inclure la libwinapi (avec #include linux.h). Un simple #ifdef sur une variable WIN32 / LINUX définit pour le préprocesseur va assurer le bon fonctionnement du code quel que soit le système d'exploitation utilisé.
Portages annexes : les COTS
Il n'est pas rare qu'une application fasse appel à des DLL pour réutiliser des fonctionnalitées complexes telles que, dans notre cas, un client FTP, Base de données, bus CORBA. Il existe sous Linux, les équivalents de beaucoup des DLL Windows. Dans le cas présent, nous pouvons citer libCURL pour le FTP, SQLITE pour la base de données, et omniORB pour la communication CORBA. Ces librairies présentent des interfaces différentes de celles utilisées par Windows, il faut donc : soit enrichir la libwinapi, soit écrire du code parallèle, le préprocesseur choisira alors le morceau de code en fonction de flags de compilation WIN32 ou LINUX. Lorsque l'application gère déjà une couche d'interface avec ces DLL, ce deuxième choix est pertinent afin d'éviter de cumuler les couches d'abstraction et donc de compliquer/ralentir l'application finale.