Introduction à CMake
Table des matières
- 1. Introduction
- 2. Qu'est-ce que CMake ?
- 3. TP montrant l'utilisation de CMake
- 3.1. Sous Linux, CMake en mode commande (utilisation de l'outil de construction make)
- 3.2. Sous Linux, CMake avec CLion (utilisation de l'outil de construction Ninja)
- 3.3. Sous Windows, CMake en mode commande (utilisation de l'outil de construction MSBuild)
- 3.4. Sous Windows, CMake avec VisualStudio (utilisation de l'outil de construction Ninja)
- 4. Configuration de CMake : les fichiers
CMakeLists.txt
- 4.1.
CMakeLists.txt
global- 4.1.1.
cmake_minimum_required(VERSION 3.15)
- 4.1.2.
cmake_policy(VERSION 3.15)
- 4.1.3.
include(FetchContent)
- 4.1.4.
project(JIN4_SampleSFML VERSION 1.0.0 LANGUAGES CXX)
- 4.1.5.
IF(WIN32)
,else()
etendif()
- 4.1.6.
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
- 4.1.7.
set (BUILD_SHARED_LIBS FALSE)
- 4.1.8.
find_package
- 4.1.9.
include_directories
- 4.1.10.
FetchContent_Declare
- 4.1.11.
FetchContent_MakeAvailable
- 4.1.12.
set(CMAKE_CXX_STANDARD 17)
- 4.1.13.
add_subdirectory(sample)
- 4.1.14.
enable_testing()
- 4.1.1.
- 4.2.
CMakeLists.txt
par entité logicielle
- 4.1.
- 5. Exemples de projets avec CMake
- 6. Quelques trucs et astuces
1 Introduction
Ce cours a pour vocation d'introduire à l'outil CMake en s'appuyant sur l'expérience acquise par Michel Simatic dans l'utilisation de CMake pour le cours CSC4526 de Télécom SudParis. Ce cours n'est donc qu'une introduction forcément partielle, mais qui permet quand même un bon survol des possibilités de CMake.
2 Qu'est-ce que CMake ?
- CMake est un méta-"système de construction" destiné à générer, pour la plupart des systèmes d'exploitation existants (Windows, Linux, MacOS, etc.), des fichiers de configuration pour des "systèmes de construction" de logiciel: make, MSBuild, Ninja
- Il facilite la vie des développeurs·ses en :
- limitant les besoins d'installation de bibliothèques avant de pouvoir compiler le logiciel
- leur évitant de se préoccuper des soucis de configuration d'outil
de construction de logiciel, compilateur et éditeur de liens.
- en particulier, facilitant le développement d'une version debug ou production.
- permettant de déclencher, sur un simple commit Git, la compilation du logiciel avec différents compilateurs (MSVC, gcc, clang) avec, par exemple, Microsoft Azure Pipelines.
3 TP montrant l'utilisation de CMake
Décompressez l'archive SampleSFML.zip dans le répertoire de votre choix (par exemple, dans C:\users\votre_login\CSC4526
).
3.1 Sous Linux, CMake en mode commande (utilisation de l'outil de construction make)
- Sous Linux, ouvrez un terminal et tapez les commandes :
cd cheminVersLeRepertoireSampleSFML mkdir buildUnix cd buildUnix cmake .. make sample/sample # Sous Linux (bin/sample sous MacOS)
- Observez que :
- Le répertoire
_deps
contient le résultat du ~ git clone~ de SFML. - Tout le travail de construction du logiciel a été fait dans ce
répertoire
buildUnix
. Il suffit d'effacer ce répertoire pour s'en débarrasser.
- Le répertoire
3.2 Sous Linux, CMake avec CLion (utilisation de l'outil de construction Ninja)
- Sous Linux, exploitez le canevas de projet obtenu selon la procédure
cmake
de ce document. - Observez que :
- Le travail de Clion n'est pas dérangé par la présence du répertoire buildUnix.
- Tout le travail de construction du logiciel a été réalisé dans le
répertoire
cmake-build-debug
. - CLion a également créé un répertoire
.idea
qui contient les données de travail de CLion sur ce projet (par exemple, l'indexation des fichiers). - Si besoin de "réinitialiser" l'environnement, il suffit d'effacer
ces deux répertoires
cmake-build-debug
et.idea
.
3.3 Sous Windows, CMake en mode commande (utilisation de l'outil de construction MSBuild)
- Sous Windows, lancez VisualStudio et "Outils > Ligne de commande > Powershell développpeur".
- Dans ce terminal, tapez les commandes :
cd cheminVersLeRepertoireSampleSFML mkdir buildWindows cd buildWindows # Si on a lancé la fenêtre de commande en dehors de Visual Studio, il faut exécuter # la commande suivante pour correctement initialiser la variable d'environnement Path (pour voir # le contenu de cette variable, tapez la commande : echo $env:path ) et donc accéder à tous les # outils VisualStudio) : # C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat cmake .. MSBuild.exe .\JIN4_SampleSFML.sln .\sample\Debug\sample.exe
- Observez que :
- Le répertoire
_deps
contient le résultat du ~ git clone~ de SFML. - Tout le travail de construction du logiciel a été fait dans ce
répertoire
buildWindows
. Il suffit d'effacer ce répertoire pour s'en débarrasser.
- Le répertoire
3.4 Sous Windows, CMake avec VisualStudio (utilisation de l'outil de construction Ninja)
- Sous Windows, exploitez le canevas de projet obtenu selon la procédure
cmake
de ce document. - Observez que :
- Le travail de VisualStudio n'est pas dérangé par la présence du répertoire buildUnix.
- Tout le travail de construction du logiciel a été réalisé dans le
répertoire
.out
. - VisualStudio a également créé un répertoire
.vs
qui contient les données de travail de CLion sur ce projet (par exemple, l'indexation des fichiers). - Si besoin de "réinitialiser" l'environnement, il suffit d'effacer
ces deux répertoires
out
et.vs
.
4 Configuration de CMake : les fichiers CMakeLists.txt
- Pour un projet logiciel donné, on aura au moins 2 fichiers
CMakeLists.txt
à écrire. Nous les détaillons ci-après.
4.1 CMakeLists.txt
global
- Ce fichier (présent dans le répertoire racine du projet) contient les informations communes à toutes les entités logicielles (exécutable ou bibliothèque) de votre projet.
- Affichez
SampleSFML/CMakeLists.txt
4.1.1 cmake_minimum_required(VERSION 3.15)
Spécifie que vous avez au moins besoin de CMake 3.15 pour votre
projet. NB : Dans CSC4526, on a besoin d'avoir au moins la version
3.15 de CMake pour disposer du module CMake FetchContent
.
4.1.2 cmake_policy(VERSION 3.15)
Désormais inutile, car, à partir de CMake version 2.4, "The cmake_minimum_required(VERSION) command implicitly invokes the cmake_policy(VERSION) command" (cf. https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html)
4.1.3 include(FetchContent)
Spécifie qu'on utilise le module CMake FetchContent
.
4.1.4 project(JIN4_SampleSFML VERSION 1.0.0 LANGUAGES CXX)
Spécifie le nom de votre projet dans l'outil de construction (cf. JIN4_SampleSFML.sln), sa version et les langages informatiques utilisés pour votre projet.
4.1.5 IF(WIN32)
, else()
et endif()
Permettent une génération conditionnelle
4.1.6 set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
Permet de positionner un flag de génération CMake dont SonarLint a besoin, sous Windows, pour travailler correctement après.
4.1.7 set (BUILD_SHARED_LIBS FALSE)
Indique à CMake de générer des bibliothèques statiques (et non dynamiques). Ainsi, même si les exécutables résultant sont plus gros, il n'y a rien à configurer au niveau du système d'exploitation des développeurs·ses pour que l'exécution puisse se faire correctement.
4.1.8 find_package
Demande à CMake de vérifier que ces bibliothéques sont bien installées sur la machine.
4.1.9 include_directories
Pour les futures compilation, configure le compilateur pour qu'il référence les répertoires en paramètre en tant que répertoires d'include.
4.1.10 FetchContent_Declare
Spécifie comment récupérer une bibliothèque externe (son repository GIT, la branche, le tag de version à utiliser).
4.1.11 FetchContent_MakeAvailable
Va effectivement récupérer une bibliothèque externe.
4.1.12 set(CMAKE_CXX_STANDARD 17)
Spécifie que CMake doit dire au compilateur d'autoriser les spécificités du C++17 (ce qui inclut C++11, C++14, mais pas C++20).
4.1.13 add_subdirectory(sample)
Ajoute le sous-répertoire sample
à la construction.
4.1.14 enable_testing()
Permet de spécifier qu'il y aura des fichiers pour les tests dans le
répertoire courant et ses sous-répertoires. NB : Cette instruction
doit absolument apparaître dans le CMakeLists.txt
de plus haut
niveau pour permettre à l'explorateur de tests de Visual Studio de
trouver les tests unitaires.
4.2 CMakeLists.txt
par entité logicielle
- Ce fichier (présent dans le répertoire contenant les sources de votre entité logicielle) contient les informations permettant de dire comment construire votre entité logicielle.
- Affichez
SampleSFML/sample/CMakeLists.txt
4.2.1 file(GLOB SOURCES CONFIGURE_DEPENDS *.h *.cpp)
Spécifie une variable CMake qui contient la liste de tous les
fichiers .h
et .cpp
de votre répertoire courant.
4.2.2 add_executable
Spécifie que votre entité logiciell générée est un exécutable du nom
de sample
construit avec tous les fichiers issus de la liste de
fichiers dans la variable CMake SOURCES
.
4.2.3 target_link_libraries(sample PUBLIC sfml-graphics)
Spécifie que, pour construire votre entité logicielle sample
, vous
aurez besoin de faire l'édition de liens avec la bibliothèque
sfml-graphics
(et donc, implicitement, que vous aurez besoin des
include SFML pour la compilation de vos .cpp
5 Exemples de projets avec CMake
- SampleGoogleTest.zip est un exemple de projet contenant la
génération d'une bibliothèque et de 2 exécutables s'appuyant sur
cette bibliothèque.
- NB : L'exécutable des tests unitaires n'est pas généré dans un répertoire dédié aux tests unitaires, à cause d'une limitation de l'explorateur de tests Visual Studio (qui ne voit pas les tests unitaires s'ils sont dans un sous-répertoire).
- ProgrammationConcurrente.zip est un exemple de projet contenant la génération de 26 exécutables.
6 Quelques trucs et astuces
- Certaines entités logicielles (par exemple, sqlite) sont écrites complètement en C. Dans ce cas, il faut expressément dire à CMake qu'il doit utiliser l'éditeur de lien C++ et pas l'éditeur de lien C :
add_library(sqlite sqlite3.c) set_target_properties(sqlite PROPERTIES LINKER_LANGUAGE CXX)
- Parfois, il y a besoin d'ajouter une option pour le linker (par
exemple, l'option
-pthread
pour obtenir un exécutable Unix multithreadé):
add_executable(02_CounterMultithread Source_02.cpp ) if (UNIX) target_link_options(02_CounterMultithread PUBLIC -pthread) endif()
- Pour mettre le niveau maximum de warnings à la compilation:
if (MSVC) # warning level 4 (see https://docs.microsoft.com/fr-fr/cpp/build/reference/compiler-option-warning-level?view=vs-2019) # We do not put /WX to consider all warnings as errors add_compile_options(/W4) else() # lots of warnings # We do not put -Werror to consider all warnings as errors add_compile_options(-g -Wall -Wextra) endif()
- Recopie d'un dossier Media pour qu'il soit vu par l'exécutable généré:
add_custom_target(copy-Media ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Media) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Media DEPENDS ${CMAKE_SOURCE_DIR}/Media COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Media ${CMAKE_CURRENT_BINARY_DIR}/Media ) add_dependencies(my_executable copy-Media)
- S'appuyer sur des bibliothèques installées manuellement sur la machine
set (PHOTON_DIR "C:/Software/Photon-Windows-Sdk_v4-1-16-3") if(MSVC) find_library(PHOTON_COMMON Common-cpp_vc16_debug_windows_md_x64.lib PATHS ${PHOTON_DIR}/Common-cpp/lib REQUIRED) find_library(PHOTON_PHOTON Photon-cpp_vc16_debug_windows_md_x64.lib PATHS ${PHOTON_DIR}/Photon-cpp/lib REQUIRED) find_library(PHOTON_LOADBALANCING LoadBalancing-cpp_vc16_debug_windows_md_x64.lib PATHS ${PHOTON_DIR}/LoadBalancing- cpp/lib REQUIRED) elseif(APPLE) find_library(PHOTON_COMMON libCommon-cpp_debug_macosx.a PATHS ${PHOTON_DIR}/Common-cpp/lib REQUIRED) find_library(PHOTON_PHOTON libPhoton-cpp_debug_macosx.a PATHS ${PHOTON_DIR}/Photon-cpp/lib REQUIRED) find_library(PHOTON_LOADBALANCING libLoadBalancing-cpp_debug_macosx.a PATHS ${PHOTON_DIR}/LoadBalancing-cpp/lib REQU IRED) else() # Linux find_library(PHOTON_COMMON libCommonDebug64.a PATHS ${PHOTON_DIR}/Common-cpp REQUIRED) find_library(PHOTON_PHOTON libPhotonDebug64.a PATHS ${PHOTON_DIR}/Photon-cpp REQUIRED) find_library(PHOTON_LOADBALANCING libLoadBalancingDebug64.a PATHS ${PHOTON_DIR}/LoadBalancing-cpp REQUIRED) endif() target_link_libraries(Multi_Photon_V0 PUBLIC sfml-graphics ${PHOTON_LOADBALANCING} ${PHOTON_PHOTON} ${PHOTON_COMMON} )