Bon, des Makefiles, ça va faire plus de 20 ans que j'en mange. C'est plus ou moins la base des règles de compilation. Vous indiquez un nom de fichier à obtenir, puis les fichiers dont il dépend, puis les commandes à exécuter pour passer de l'un à l'autre.
Monfichier.o: Monfichier.c FichierImportant.h
compiler Monfichier.c -o Monfichier.o
Et bien sûr, vous avez le droit de rendre ça plus générique:
%.o: %.c FichierImportant.h
compiler $< -o $@
Bon, assez rapidement, ça devient plus complexe que ça, hein. Par exemple, il y a peu de chance que tout votre projet dépende de FichierImportant.h et seulement de ça. On risque plus d'avoir quelque-chose comme jeu.c qui dépend de jeu.h et sprite.h alors que sprite.c ne dépend que de sprite.h et menu.c dépend à la fois de menu.h sauvegardes.h et sprite.h, par exemple.
Si on a de la chance, le compilateur offre alors une option pour générer des fichiers de dépendances qui capturent ça (disons, jeu.dep, menu.dep et sprite.dep) et on s'en sort avec
%.o: %.c
compiler $< -o $@ $(ET_GENERER_LES_DEPENDANCES)
-include *.dep
Mais restons-en là pour l'instant. Dès que le projet grossit, qu'il commence à dépendre de bibliothèque externes (pour les formats d'images, la gestion du son, etc.), et surtout, dès qu'on commence à vouloir le compiler pour plusieurs plate-formes différentes (linux et windows?), ça devient vite un beau gros sac de noeuds ... en particulier parce que si make
est omniprésent dans le monde Linux, il est toujours boudé par Microsoft qui y va de son propre msbuild.exe
qui manipule des fichiers XML déguisés en .vcxproj ... D'où l'intérêt de programmes qui vont générer des Makefiles à partir de descriptions plus haut-niveau du projet à compiler.
C'est le cas de qmake
, notamment, qu'on va exécuter dans un répertoire vide en lui indiquant l'emplacement de nos sources et qui va créer un Makefile dédié à la compilation de nos sources dans ce répertoire-là en utilisant le fichier *.pro
distribué avec les sources.
mkdir build cd build qmake ../src
- il y définit tous les programmes utilisés (compilateur, linkeur, etc.) dans des variables pour
make
; - il donne une règle indiquant quand re-générer le Makefile (est-ce que le fichier .pro a changé?) qui réappellera
qmake
; - il ajoute les règles pour préparer une distribution du programme, nettoyer les fichiers intermédiaires, etc.
- et surtout, parce que
qmake
est lié au projet d'interface graphique Qt, il prend en charge tout ce qui concerne la génération de code pour l'interface graphique à l'aide de moc.
A travers son fichier .pro, qmake prend en charge le fait que les différents compilateurs ont des préférences différentes pour les macro-définitions (à ajouter dans DEFINES
) ou les répertoires à explorer quand il tombe sur un #include
(à ajouter dans INCLUDEPATH
). Idem avec les bibliothèques à passer au linkeur. On trouve évidemment aussi SOURCES
pour les fichiers à compiler et HEADERS
pour les déclaration de classes contenant des annotations pour le système de signal/slot propre à Qt (qui en aura besoin pour générer du code et compléter les vtables).
Une autre grande différence entre make
et qmake
est que ce dernier se veut multi-plate-formes et indépendant du shell. ça se traduit notamment par une manière franchement confortable pour les éléments conditionnels, comme
linux {
LIBS += pthread
!isEmpty(ENABLE_GL) {
SOURCES += backend/opengl.cpp
}
}
windows {
LIBS += direct3D
}
Et autres astuces du genre. Attention par contre: si il était possible de faire des Makefile qui incluent d'autre makefiles (notamment pour combiner les résultats de plusieurs répertoires), la chose qui s'en rapproche le plus avec qmake c'est le TEMPLATE = subdirs
, mais qui à l'instar de makefiles récursifs, ne partage pas les variables d'un fichier .pro à l'autre. Oui, je sais, en lisant ça, ça semble évident, mais ça l'était nettement moins en écrivant le makefile. La solution, c'est de faire venir la variable de l'extérieur soit avec
Une approche pas toujours très confortable, cela dit, en particulier à cause d'une gestion des dépendances entre variables et fichiers .o pas toujours très claire ... je comprends pourquoi mes collègues lui ont préféré
include (../projet.pri)
dans les .pro-feuilles et qui contient les DEFINES += ENABLE_GL=yes
et autre MODEL_EXPORTER_PATH=/usr/bin/export_to_gl
oh, et si, il y a des gens qui utilisent qmake pour nds
ReplyDeleteQtCreator can reveal you which qmake prompt it uses for this or that configuration. You may find sub-directories Makefile.Debug and Makefile.Release, but there will be just one Makefile in your top-level build directory, and that's the one matching the configuration you were selecting in QtCreator.
ReplyDeleteoh, and don't look for "make.exe". It's called jom.exe. Note that it still support -p ;)