1°/ Préambule

Il existe principalement deux bibliothèques sous Linux pour créer des interfaces graphiques (IG) en C/C++ :

  • Qt,
  • Gtk
L'avantage de la première est d'être réellement écrite en C++ et qu'elle existe aussi bien sous Linux que sous Windows. D'autre part, la gestion des "callbacks" (les fonctions qui sont appelées lorsque l'utilisateur interagit avec l'IG) est beaucoup plus simple. Enfin, Qt propose de nombreuses classe outils permettant entre autre de manipuler facilement des collections, des threads, des sockets, des fichiers XML, des bases SQL, etc.

Dans les outils proposés par Qt après installation, on trouve qmake, qui sert à créer un Makefile automatiquement. Le problème est que cet outil est très limité. Par exemple, il ne supporte pas le fait d'avoir des sources réparties dans différents répertoire, de pouvoir créer plusieurs exécutables, et de faire de la cross-compilation, c'est-à-dire créer un exécutable pour un OS donné avec des outils installés sous un autre OS.
En conclusion, si l'on veut faire des choses un peu complexe, il faut écrire soi-même un Makefile adapté. Quoique ...

2°/ Les outils passe-partout

Généralement, les projets que l'on veut compiler soi-même ont à la racine un script configure qui permet de générer automatiquement un Makefile à partir d'un squelette (généralement nomé Makefile.in), souvent grâce à automake. Cependant, cet outil est un peu opaque dès lors que l'on veut faire des choses un peu complexes telles que la cross-compilation. Il vaut donc mieux écrire soi-même ce script de configure. Ce n'est pas très compliqué : à part traiter correctement les options possibles, il suffit de faire des chercher:remplacer dans le squelette, par exemple avec sed. On peut également générer automatiquement des blocs cible : dependance pour le Makefile, afin de prendre en compte les relations entre .c et .h. C'est le cas avec le script fourni dans cet article.

La chose la plus complexe est de créer le squelette Makefile.in. Celui qui est fournit utilise plein d'astuces pour faciliter la vie à configure. En effet, configure ne va modifier que quelques lignes qui se trouvent au début. Ensuite, tout le reste se fait grâce à la "magie" des variables make. Mais avant de l'utiliser, il faut installer tout ce qu'il faut pour créer les exécutables.

2.1°/ installation de la chaîne de compilation

Pour que tout fonctionne, il faut au préalable installer les outils permettant de faire de la cross-compilation. Dans le cas présent, on suppose que l'on développe sous Linux mais que l'on veut pouvoir créer des exécutables Linux ET Windows. Il faut donc un compilateur et un éditeur de lien pour Windows, fonctionnant sous Linux. Par défaut Makefile.in fait appel aux outils de MinGW, en se basant sur leur emplacement et nom dans une distribution de type Debian.

2.1.1°/ Etape 1 : installation des outlis linux

Le compilateur gcc est celui utilisé par défaut. Pour Qt, il suffit d'installer la version 4 ou 5 (de préférence la 5) sans oublier les paquets nécessaires au développement Qt. Voici une liste sommaire de paquets debian à installer pour avoir l'essentiel :
  • libqt5core5a
  • libqt5widgets5
  • libqt5gui5
  • libqt5network5
  • qtbase5-dev
  • qtbase5-dev-tools
  • qttools5-dev-tools
  • qtcreator

Il est également possible d'installer des bibliothèques pour des fonctionnalités moins classiques :

  • libqt5xml5
  • libqt5xmlpatterns5
  • libqt5xmlpatterns5-dev
  • libqt5printsupport5
  • libqt5opengl5
  • libqt5opengl5-dev
  • libqt5sql5

2.1.2°/ Etape 2 : installation des outills Windows

NB : cette étape n'est utile que si vous projetez de créer des exécutables pour windows à partir d'un environnement linux. Sinon, vous pouez la sauter.

A l'heure actuelle, en utilisant mingw des paquets debian, il n'est possible de faire de la cross-compilation que pour produire des executable 32 bits pour Windows. Cela dit, ils fonctionnent très bien sur des windows 64bits. On peut espérer qu'à l'avenir, on puisse générer des exécutable 64 bits.
Le problème de mingw est de trouver les bons paquets à installer. En effet, il existe de très nombreux paquets dont les noms se ressemblent fortement. Pour faire simple, on peut directement lancer la commande suivante :
apt-get install mingw-w64 mingw-w64-dev mingw-w64-tools binutils-mingw-w64

ATTENTION : cela installe aussi bien le compilateur pour 32bits que celui pour 64bits. Cela ne veut as pour autant dire que le résultat d'une compilation 64 bits fonctionnera effectivement sous windows.

Ensuite, il faut diposer des bilbliothèques Qt pour windows et de les installer dans le système de fichier. Pour cela, vous pouvez télécharger la version windows, l'installer sous widnows, copier le répertoire d'installation sur une clé puis recopier le tout sous linux. Ou alors vous pouvez télécharger l'archive de cette installation [ ici ]. ATTENTION, le fichier fait 1.3Go et contient la version 5.3.2 de Qt. Ensuite, en tant que root, décompactez l'archive dans /usr/local/.

2.2°/ le supermake

L'archive contenant les fichiers est disponible [ ici ]. Elle contient 4 fichiers :
  • configure : le script de configuration qui va créer le vrai Makefile.
  • Makefile.in : le canevas qui va etre utilisé comme modèle par configure.
  • install.sh.in : c'est un canevas de script d'installation des binaires pour Linux. Il va servir de base à configure pour produire install.sh, le vrai script d'installation. A noter que pour windows, il n'y a pas de script d'installation, juste une archive zip à dézipper, par exemple dans c:\Program Files\
  • object-files.txt : ce fichier contient la liste des fichiers objet nécessaire lors de l'édition de lien. ATTENTION : celui qui est fournit donne une idée de la structuration avec des lignes du type $(BUILDPATH)/nom_fich.o \ (sauf la dernière sans \). De plus, il faut que chaque ligne après la 1ère commence par une tabulation. Ce fichier va être inclu dans le Makefile lors de son évaluation.
Remarque pure Qt : quand on crée une classe qui va utiliser le principe des slot/signaux (c.a.d. une classe dans laquelle on ajoute la macro Q_OBJECT), il faut obligatoirement créer un fichier .cpp à partir du .h de cette classe et ensuite compiler ce .cpp. Celui-ci est produit grâce à un outil Qt appelé moc. Dans l'archive fournie ci-dessous, si on suppose que monfichier2.cpp contienne le code d'une classe dans ce cas, alors il faudrait utiliser moc sur monfichier2.h. Il est d'usage d'appeler le résultat avec comme préfixe moc_, donc moc_monfichier2.cpp. Pour simplifier la tâche du développeur et lui éviter d'appeler lui-même moc, on peut mettre dans object-files.txt un nom de fichier du type moc_fichier.o.  Dans ce cas, le Makefile va chercher fichier.h, appeler moc dessus pour produire moc_fichier.cpp et le compiler pour obtenir moc_fichier.o. Dans l'exemple fournit, on voit effectivement une ligne moc_monfichier2.o

3°/ Principes d'utilisation
  • Créer un répertoire pour le projet et un sous répertoire avec le numéro de version courante. Par exemple : mkdir -p monprojet/v0.1
  • Aller dans ce répertoire : cd monprojet/v0.1
  • Utilisez qtcreator pour créer votre projet Qt, en utilisant "Nouveau projet" -> "Importer un projet" -> "Importer un projet existant". ATTENTION ! contrairement à ce que cet item laisse penser, pas besoin d'avoir un projet. Vous allez juste donner un nom au projet (par exemple monprojet) puis cliquer plusieurs fois sur OK. Au final, vous aurez dans le répertoire 5 fichiers : monprojet.config, monprojet.creator, monprojet.creator.user, monprojet.files et monprojet.includes
  • Editez le fichier monprojet.includes en ajoutant les lignes suivantes (pour une distribution debian 64bits) :
.
/usr/include/x86_64-linux-gnu/qt5/QtCore
/usr/include/x86_64-linux-gnu/qt5/QtGui
/usr/include/x86_64-linux-gnu/qt5/QtXml
/usr/include/x86_64-linux-gnu/qt5/QtNetwork
  • Ces modifications permettent à qtcreator d'aller analyser les fichiers .h présent dans ces répertoires et faire de la complétion automatique.
  • Copiez l'archive superqtmake.tgz dans le répertoire et décompactez : tar ztvf superqtmake.tgz.
  • Créez votre application en ajoutant des classes (donc des .h et .cpp).
  • A chaque fois que vous ajoutez un couple .h/.cpp, modifiez object-files.txt pour que le .cpp soit compilé. Par exemple si vous créez toto.h et toto.cpp, alors vous ajoutez $(BUILDPATH)/toto.o  (et éventuellement $(BUILDPATH)/moc_toto.o si la classe utilise Q_OBJECT).

Une fois que votre pojet est dans un état "stable" (c.a.d. pas de nouveau fichier créé), lancez le script configure pour qu'il génère un Makefile tenant compte de tous les fichiers sources disponibles. Par exemple :

  • configure -d lin -v 0.1 monprojet permet de créer un Makefile pour construire l'exécutable linux, avec comme nom monprojet.
  • configure -d win -v 0.1 monprojet permet de créer un Makefile pour construire l'exécutable windows, avec comme nom monprojet.exe.
Dans les exemples ci-dessus, -d permet d'utiliser les réglages par défaut. Pour rester cohérent, la numéro de version doit correspondre au nom du répertoire courant. Cela dit, aucun vérification n'est faite donc le répertoire courant peut très bien être nommé différemment. Le numéro de version sera notamment utilisé lors de la création de l'archive des sources ou du paquet installable.
  • Quand vous voulez créer l'exécutable, il suffit de taper : make.
  • Pour créer une archive d'installation des binaires, tapez : make dist.
  • Pour créer une archive des source, tapez : make src-dist
Remarques :
  • pour construire l'exécutable windows, il faut 2 fichiers de plus que sous Linux :  un fichier .ico qui est l'icône de l'application et un fichier .rc qui permet de référencer cet icône. Il faut obligatoirement que ces fichiers aient le même suffixe que le nom donné au projet lors de l'appel à configure.
  • pour lancer les exécutables windows sans avoir besoin d'installer Qt, les bibliothèques basique sont inclues dans l'archive des binaires pour windows. (NB : ces bibliothèques sont dans lib/win32)
  • si vous fouillez dans le Makefile, vous trouverez des defines de compilation -DNOMDUPROJET_LIN et -DNOMDUPROJET_WIN. Vous pouvez vous servir de ces define dans votre code pour définir des sections qui seront compilées uniquement pour la version Linux ou Windows. Cela est notamment nécessaire lorsque l'on veut faire appel aux socket Windows, ce qui nécessite d'inclure des .h qui existent uniquement sous Windows.
4°/ Exemple complet
  • Pour voire comment tout s'articule, voici un petit exemple d'application Qt tiré des tutoriaux mais "packagée" pour être construire avec les outils donnés ci-dessus.
  • L'archive se trouve [ ici ].
  • Pour tester, décompactez l'archive et allez dans testgroupbox/v0.1. 
  • Tapez configure -d lin testgroupbox pour générer le Makefile linux, puis make pour créer l'exécutable, et enfin make dist pour créer l'archive des binaires.
  • Tapez configure -d win testgroupbox pour générer le Makefile windows, puis make pour créer l'exécutable, et enfin make dist pour créer l'archive des binaires.