Sur cette page

Premiers pas avec CMake

CMake est un ensemble d'outils permettant de compiler, de tester et de packager des applications. Tout comme Qt, il est disponible sur toutes les principales plateformes de développement. Il est également pris en charge par divers IDE, notamment Qt Creator et Visual Studio Code.

Dans cette section, nous allons vous présenter la manière la plus simple d’utiliser Qt dans un projet CMake. Nous commencerons par créer une application console basique. Ensuite, nous étendrons le projet pour en faire une application avec interface graphique utilisant Qt Widgets.

Si vous souhaitez savoir comment compiler un projet CMake existant avec Qt, consultez la documentation expliquant comment compiler des projets avec CMake en ligne de commande.

Pour découvrir les bases de CMake, suivez le cours « Building with CMake : Getting Started with CMake and Qt » (Compiler avec CMake : premiers pas avec CMake et Qt ) sur Qt Academy.

Compilation d'une application console C++

Un projet CMake est défini par des fichiers écrits en langage CMake. Le fichier principal s'appelle « CMakeLists.txt » et se trouve généralement dans le même répertoire que les sources du programme proprement dit.

Voici un exemple de fichier « CMakeLists.txt » typique pour une application console écrite en C++ à l'aide de Qt :

cmake_minimum_required(VERSION 3.16)

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Core)

qt_standard_project_setup()

qt_add_executable(helloworld
    main.cpp
)

target_link_libraries(helloworld PRIVATE Qt6::Core)

Passons en revue son contenu.

cmake_minimum_required(VERSION 3.16)

cmake_minimum_required() spécifie la version minimale de CMake requise pour configurer correctement le projet. Consultez la section « Versions de CMake prises en charge » pour connaître la version minimale requise par Qt.

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

project() définit le nom du projet et la version par défaut de celui-ci. L'argument LANGUAGES indique à CMake que le programme est écrit en C++.

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

Qt 6 nécessite un compilateur prenant en charge la version 17 ou une version plus récente du C++. En imposant cette contrainte via les variables CMAKE_CXX_STANDARD et CMAKE_CXX_STANDARD_REQUIRED, CMake affichera un message d’erreur si le compilateur est trop ancien.

find_package(Qt6 REQUIRED COMPONENTS Core)

Cela indique à CMake de rechercher Qt 6 et de rendre le module Core disponible. Il est inutile de poursuivre si CMake ne parvient pas à localiser le module ; c’est pourquoi nous définissons l’indicateur REQUIRED afin que CMake interrompe le processus dans ce cas. Pour plus d’informations, consultez la section « Rendre Qt disponible dans les projets CMake ».

En cas de succès, le module définira certaines variables CMake documentées dans la section « Variables du module ». Il importe en outre la cible « Qt6::Core » que nous utilisons ci-dessous.

qt_standard_project_setup()

La commande ` qt_standard_project_setup()` définit les valeurs par défaut à l'échelle du projet pour une application Qt classique.

Entre autres, cette commande définit la variable « CMAKE_AUTOMOC » sur « ON », ce qui indique à CMake de configurer automatiquement des règles afin que le générateur de code de Qt (Meta-Object Compiler, moc) soit appelé de manière transparente, lorsque cela est nécessaire.

Pour plus de détails, consultez la documentation de la fonction qt_standard_project_setup().

qt_add_executable(helloworld
    main.cpp
)

qt_add_executable() indique à CMake que nous souhaitons compiler un exécutable (et non une bibliothèque) nommé helloworld en tant que cible. Il s'agit d'un wrapper autour de la commande intégrée ` add_executable() `, qui fournit une logique supplémentaire pour gérer automatiquement des aspects tels que la liaison des plugins Qt dans les builds Qt statiques, la personnalisation des noms de bibliothèques en fonction de la plateforme, etc.

La cible doit être compilée à partir du fichier source C++ main.cpp.

En règle générale, vous ne devez pas lister les fichiers d’en-tête ici. Cela diffère de qmake, où les fichiers d’en-tête doivent être explicitement listés pour être traités par le générateur de code (Meta-Object Compiler, moc).

Pour créer des bibliothèques, voir qt_add_library().

target_link_libraries(helloworld PRIVATE Qt6::Core)

Enfin, la commande « target_link_libraries » indique à CMake que l’exécutable « helloworld » utilise Qt Core en faisant référence à la cible ` Qt6::Core ` importée par l’appel ` find_package() ` ci-dessus. Cela permettra non seulement d’ajouter les bons arguments à l’éditeur de liens, mais aussi de s’assurer que les répertoires d’inclusion et les définitions de compilateur appropriés sont transmis au compilateur C++. Le mot-clé « PRIVATE » n’est pas strictement nécessaire pour une cible exécutable, mais il est recommandé de le spécifier. Si « helloworld » était une bibliothèque plutôt qu’un exécutable, il faudrait alors spécifier soit « PRIVATE », soit « PUBLIC » («PUBLIC » si la bibliothèque fait référence à un élément de « Qt6::Core » dans ses en-têtes, « PRIVATE » dans le cas contraire).

Compilation d’une application C++ avec interface graphique

Dans la section précédente, nous avons présenté le fichier CMakeLists.txt d’une application console simple. Nous allons maintenant créer une application avec interface graphique qui utilise le Qt Widgets module.

Voici le fichier de projet complet :

cmake_minimum_required(VERSION 3.16)

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Widgets)

qt_standard_project_setup()

qt_add_executable(helloworld
    mainwindow.ui
    mainwindow.cpp
    main.cpp
)

target_link_libraries(helloworld PRIVATE Qt6::Widgets)

set_target_properties(helloworld PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

Passons en revue les modifications que nous avons apportées.

find_package(Qt6 REQUIRED COMPONENTS Widgets)

Dans l’appel ` find_package `, nous remplaçons ` Core ` par ` Widgets`. Cela permettra de localiser le module ` Qt6Widgets ` et de fournir les cibles ` Qt6::Widgets ` auxquelles nous effectuerons ensuite la liaison.

qt_standard_project_setup()

En plus de CMAKE_AUTOMOC, qt_standard_project_setup() définit la variable CMAKE_AUTOUIC sur ON. Cela créera automatiquement des règles pour invoquer l’User Interface Compiler (uic) de Qt sur les fichiers source .ui.

qt_add_executable(helloworld
    mainwindow.ui
    mainwindow.cpp
    main.cpp
)

Nous ajoutons un fichier DesignerQt Widgets (mainwindow.ui) et son fichier source C++ correspondant (mainwindow.cpp) aux sources de la cible d’application.

Remarque : uneautre façon d’ajouter des fichiers « .ui » à votre projet consiste à utiliser la commande `qt_add_ui()` à la place de ` AUTOUIC`.

target_link_libraries(helloworld PRIVATE Qt6::Widgets)

Dans la commande ` target_link_libraries `, nous effectuons la liaison avec ` Qt6::Widgets ` au lieu de ` Qt6::Core`. Notez que l’application continuera à effectuer la liaison avec ` Qt6::Core`, car ` Qt6::Widgets ` en dépend.

set_target_properties(helloworld PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

Enfin, nous définissons des propriétés sur notre cible d'application, ce qui a les effets suivants :

  • Empêcher la création d’une fenêtre de console sous Windows.
  • Créer un bundle d'application sur macOS.

Consultez la documentation CMake pour plus d'informations sur ces propriétés de cible.

Structuration des projets

Les projets comportant plusieurs cibles gagneront à bénéficier d’une structure de fichiers claire. Nous utiliserons la fonctionnalité de sous-répertoires de CMake.

Comme nous prévoyons d'étendre le projet avec davantage de cibles, nous déplaçons les fichiers source de l'application dans un sous-répertoire et y créons un nouveau fichier « CMakeLists.txt ».

<project root>
├── CMakeLists.txt
└── src
    └── app
        ├── CMakeLists.txt
        ├── main.cpp
        ├── mainwindow.cpp
        ├── mainwindow.h
        └── mainwindow.ui

L'CMakeLists.txt de niveau supérieur contient la configuration globale du projet, ainsi que les appels ` find_package ` et ` add_subdirectory ` :

cmake_minimum_required(VERSION 3.16)

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Widgets)
qt_standard_project_setup()

add_subdirectory(src/app)

Les variables définies dans ce fichier sont visibles dans les fichiers des sous-répertoires du projet.

Le fichier de projet de l'application, src/app/CMakeLists.txt, contient la cible exécutable :

qt_add_executable(helloworld
    mainwindow.ui
    mainwindow.cpp
    main.cpp
)

target_link_libraries(helloworld PRIVATE Qt6::Widgets)

set_target_properties(helloworld PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

Une telle structure facilitera l'ajout de nouvelles cibles au projet, telles que des bibliothèques ou des tests unitaires.

Remarque : ajoutez le répertoire de compilation de votre projet à la liste des répertoires exclus de tout logiciel antivirus fonctionnant sur votre système.

Compilation des bibliothèques

À mesure que le projet prend de l'ampleur, vous souhaiterez peut-être transformer certaines parties du code de votre application en une bibliothèque utilisée par l'application et, éventuellement, par les tests unitaires. Cette section explique comment créer une telle bibliothèque.

Notre application contient actuellement de la logique métier directement dans le fichier ` main.cpp`. Nous extrayons ce code dans une nouvelle bibliothèque statique nommée ` businesslogic `, située dans le sous-répertoire ` "src/businesslogic" `, comme expliqué dans la section précédente.

Par souci de simplicité, la bibliothèque se compose uniquement d’un fichier source C++ et de son fichier d’en-tête correspondant, qui est inclus par le fichier ` main.cpp` de l’application :

<project root>
├── CMakeLists.txt
└── src
    ├── app
    │   ├── ...
    │   └── main.cpp
    └── businesslogic
        ├── CMakeLists.txt
        ├── businesslogic.cpp
        └── businesslogic.h

Jetons un œil au fichier de projet de la bibliothèque (src/businesslogic/CMakeLists.txt).

qt_add_library(businesslogic STATIC
    businesslogic.cpp
)
target_link_libraries(businesslogic PRIVATE Qt6::Core)
target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

Passons en revue son contenu.

qt_add_library(businesslogic STATIC
    businesslogic.cpp
)

La commande `add_library ` crée la bibliothèque businesslogic. Plus tard, nous ferons en sorte que l'application se lie à cette cible.

Le mot-clé ` STATIC ` désigne une bibliothèque statique. Si nous souhaitions créer une bibliothèque partagée ou dynamique, nous utiliserions le mot-clé ` SHARED `.

target_link_libraries(businesslogic PRIVATE Qt6::Core)

Nous disposons d’une bibliothèque statique et n’avons en réalité pas besoin de lier d’autres bibliothèques. Cependant, comme notre bibliothèque utilise des classes issues de QtCore, nous ajoutons une dépendance de liaison à Qt6::Core. Cela permet d’intégrer les chemins d’inclusion QtCore et les définitions de préprocesseur nécessaires.

target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

L'API de la bibliothèque est définie dans le fichier d'en-tête businesslogic/businesslogic.h. En appelant la fonction `target_include_directories`, nous nous assurons que le chemin absolu vers le répertoire businesslogic est automatiquement ajouté comme chemin d'inclusion à toutes les cibles utilisant notre bibliothèque.

Cela nous évite, dans ` main.cpp `, d’utiliser des chemins relatifs pour localiser ` businesslogic.h`. À la place, nous pouvons simplement écrire

#include <businesslogic.h>

Enfin, nous devons ajouter le sous-répertoire de la bibliothèque au fichier de projet de niveau supérieur :

add_subdirectory(src/app)
add_subdirectory(src/businesslogic)

Utilisation des bibliothèques

Pour utiliser la bibliothèque que nous avons créée dans la section précédente, nous demandons à CMake de la lier :

target_link_libraries(helloworld PRIVATE
    businesslogic
    Qt6::Widgets
)

Cela garantit que le fichier « businesslogic.h » sera trouvé lors de la compilation de « main.cpp ». De plus, la bibliothèque statique « businesslogic » fera partie intégrante de l'exécutable « helloworld ».

En termes de CMake, la bibliothèque businesslogic spécifie des exigences d’utilisation (le chemin d’inclusion) que tout utilisateur de notre bibliothèque (l’application) doit respecter. La commande target_link_libraries s’en charge.

Ajout de ressources

Nous souhaitons afficher des images dans notre application ; nous les ajoutons donc à l'aide du système de ressources Qt.

qt_add_resources(helloworld imageresources
    PREFIX "/images"
    FILES logo.png splashscreen.png
)

La commande `qt_add_resources() ` crée automatiquement une ressource Qt contenant les images référencées. À partir du code source C++, vous pouvez accéder aux images en leur ajoutant le préfixe de ressource spécifié :

logoLabel->setPixmap(QPixmap(":/images/logo.png"));

La commande ` qt_add_resources()` prend comme premier argument soit un nom de variable, soit un nom de cible. Nous vous recommandons d'utiliser la variante de cette commande basée sur la cible, comme indiqué dans l'exemple ci-dessus.

Ajout de traductions

Les traductions des chaînes de caractères d’un projet Qt sont encodées dans des fichiers « .ts ». Ces fichiers « .ts » sont compilés en fichiers binaires « .qm », qui sont ensuite chargés par l’application Qt au moment de l’exécution. Pour plus de détails, consultez la section Internationalisation avec Qt.

Cette section décrit comment ajouter une traduction en allemand et en français à l'application helloworld.

Spécifiez les deux langues à l’aide de la fonction qt_standard_project_setup():

qt_standard_project_setup(I18N_TRANSLATED_LANGUAGES de fr)

Appelez ensuite la fonction qt_add_translations() sur la cible qui doit charger les fichiers .qm:

qt_add_translations(helloworld)

Lors de la première configuration, cette commande crée les fichiers helloworld_de.ts et helloworld_fr.ts dans le répertoire source du projet. Ces fichiers contiendront les chaînes traduites et doivent être placés sous contrôle de version.

La commande crée également des règles du système de compilation permettant de générer automatiquement les fichiers ` .qm ` à partir des fichiers ` .ts `. Par défaut, les fichiers ` .qm ` sont intégrés dans une ressource et sont accessibles sous le préfixe de ressource ` "/i18n" `.

Pour mettre à jour les entrées du fichier ` .ts `, compilez la cible ` update_translations ` :

$ cmake --build . --target update_translations

Pour déclencher manuellement la génération des fichiers .qm, compilez la cible release_translations:

$ cmake --build . --target release_translations

Pour plus d’informations sur la manière d’influencer le traitement des fichiers « .ts » et leur intégration dans une ressource, consultez la documentation relative à qt_add_translations.

La commande qt_add_translations() est une enveloppe de commodité. Pour un contrôle plus fin de la gestion des fichiers d’ .ts s et des fichiers .qm, utilisez les commandes sous-jacentes qt_add_lupdate() et qt_add_lrelease().

Pour en savoir plus

La documentation officielle de CMake constitue une ressource inestimable pour travailler avec CMake.

Le tutoriel officiel de CMake aborde les tâches courantes liées au système de compilation.

L'ouvrage « Professional CMake : A Practical Guide » offre une excellente introduction aux fonctionnalités les plus pertinentes de CMake.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.