<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>CMake on kenji.blog</title><link>http://kenji.blog/fr/tags/cmake/</link><description>Recent content in CMake on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 09:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/fr/tags/cmake/index.xml" rel="self" type="application/rss+xml"/><item><title>Étapes pour configurer un environnement de compilation C++ multiplateforme avec CMake</title><link>http://kenji.blog/fr/p/cmake-cross-platform-build-environment-guide/</link><pubDate>Sat, 12 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/cmake-cross-platform-build-environment-guide/</guid><description>&lt;img src="http://kenji.blog/p/cmake-cross-platform-build-environment-guide/img/eyecatch.jpg" alt="Featured image of post Étapes pour configurer un environnement de compilation C++ multiplateforme avec CMake" />&lt;p>Dans le développement de logiciels en C++, le choix et la configuration du « système de compilation » (build system) ont longtemps été un casse-tête pour de nombreux développeurs. Comme le C++ n&amp;rsquo;a pas de gestionnaire de paquets ou de système de compilation standard officiel, il était nécessaire d&amp;rsquo;utiliser différents compilateurs et outils de compilation (MSVC, GCC, Clang, Make, Ninja, etc.) selon la plateforme (Windows, Linux, macOS).&lt;/p>
&lt;p>Cependant, aujourd&amp;rsquo;hui, &lt;strong>CMake&lt;/strong> s&amp;rsquo;est imposé comme le standard de facto de l&amp;rsquo;industrie. En utilisant correctement CMake, il est devenu possible de configurer élégamment un environnement de compilation multiplateforme à partir d&amp;rsquo;un seul &lt;code>CMakeLists.txt&lt;/code>.&lt;/p>
&lt;p>Dans cet article, nous expliquerons en détail et de manière exhaustive les étapes de configuration d&amp;rsquo;un environnement de compilation C++ multiplateforme en utilisant la version la plus récente de CMake (Modern CMake), des bases jusqu&amp;rsquo;aux techniques avancées.&lt;/p>
&lt;h2 id="1-quest-ce-que-cmake--le-concept-de-méta-système-de-compilation">1. Qu&amp;rsquo;est-ce que CMake ? (Le concept de méta-système de compilation)
&lt;/h2>&lt;p>CMake n&amp;rsquo;est pas un outil qui compile directement le code source par lui-même. CMake est un « système qui génère des systèmes de compilation », c&amp;rsquo;est-à-dire un &lt;strong>méta-système de compilation (Meta-Build System)&lt;/strong>.&lt;/p>
&lt;p>Le rôle principal de CMake est de lire un fichier de configuration abstrait, indépendant de la plateforme et du compilateur (&lt;code>CMakeLists.txt&lt;/code>), et de générer automatiquement les scripts de compilation natifs optimaux pour chaque environnement (par exemple : &lt;code>Makefile&lt;/code> pour Linux, les fichiers de projet &lt;code>.sln&lt;/code> de Visual Studio pour Windows, ou le rapide &lt;code>build.ninja&lt;/code>).&lt;/p>
&lt;p>Le schéma suivant illustre le processus de génération de CMake.&lt;/p>
&lt;div class="mermaid">graph TD
A["CMakeLists.txt (Définition de compilation abstraite)"] --> B["CMake (Configurer &amp; Générer)"]
B --> C["Unix Makefiles"]
B --> D["Fichiers Ninja Build"]
B --> E["Solutions Visual Studio"]
B --> F["Projets Xcode"]
C --> G["Outil de compilation natif (make, ninja, MSBuild, xcodebuild)"]
D --> G
E --> G
F --> G
G --> H["Exécutable / Bibliothèque partagée / Bibliothèque statique"]&lt;/div>
&lt;p>De cette façon, en interposant CMake, les développeurs peuvent gérer des projets C++ sans avoir à se soucier des légères différences de commandes entre les systèmes d&amp;rsquo;exploitation.&lt;/p>
&lt;h2 id="2-les-bases-du-modern-cmake--des-variables-aux-cibles-targets">2. Les bases du Modern CMake : Des variables aux cibles (Targets)
&lt;/h2>&lt;p>La syntaxe à partir de CMake 3.0 est appelée « Modern CMake » et a une philosophie de conception fondamentalement différente des versions antérieures (Legacy CMake). Dans Legacy CMake, l&amp;rsquo;approche dominante consistait à écraser des variables globales au niveau des répertoires (par exemple en utilisant &lt;code>include_directories()&lt;/code> et &lt;code>link_libraries()&lt;/code>), ce qui entraînait souvent des effets secondaires graves où les paramètres se propageaient involontairement à d&amp;rsquo;autres modules.&lt;/p>
&lt;p>Dans le Modern CMake, tout est traité comme des &lt;strong>Cibles (Targets)&lt;/strong> et des &lt;strong>Propriétés (Properties)&lt;/strong>. C&amp;rsquo;est similaire à la relation entre les classes et les variables membres dans la programmation orientée objet.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cible (Target)&lt;/strong> : Fichier exécutable (Executable) ou bibliothèque (Library).&lt;/li>
&lt;li>&lt;strong>Propriété (Property)&lt;/strong> : Fichiers sources nécessaires pour compiler cette cible, répertoires d&amp;rsquo;inclusion, options de compilation, autres bibliothèques à lier, etc.&lt;/li>
&lt;/ul>
&lt;p>En encapsulant (isolant) la configuration uniquement à une cible spécifique, il devient possible de créer des définitions de compilation sûres qui ne s&amp;rsquo;effondrent pas, même dans les projets à grande échelle.&lt;/p>
&lt;h3 id="un-cmakeliststxt-minimal">Un &lt;code>CMakeLists.txt&lt;/code> minimal
&lt;/h3>&lt;p>Tout d&amp;rsquo;abord, regardons le &lt;code>CMakeLists.txt&lt;/code> le plus basique.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Spécifier la version minimale requise de CMake
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Spécifier le nom du projet et les langages utilisés
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">VERSION&lt;/span> &lt;span class="s">1.0.0&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Exiger la norme C++ (C++20)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_EXTENSIONS&lt;/span> &lt;span class="s">OFF&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c"># Désactiver les extensions spécifiques au compilateur
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Définition de la cible exécutable
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En seulement ces quelques lignes, la configuration de la compilation d&amp;rsquo;un fichier exécutable portable nécessitant C++20 et désactivant les extensions du compilateur est terminée.&lt;/p>
&lt;h2 id="3-dépendances-et-portée-scope--public--private--interface">3. Dépendances et portée (Scope) : PUBLIC / PRIVATE / INTERFACE
&lt;/h2>&lt;p>Le concept le plus important et le plus difficile à maîtriser dans le Modern CMake est l&amp;rsquo;utilisation des trois modificateurs d&amp;rsquo;accès (portées) &lt;strong>&lt;code>PUBLIC&lt;/code>, &lt;code>PRIVATE&lt;/code>, &lt;code>INTERFACE&lt;/code>&lt;/strong>, utilisés dans des commandes comme &lt;code>target_include_directories&lt;/code> et &lt;code>target_link_libraries&lt;/code>.&lt;/p>
&lt;p>Ceux-ci servent à contrôler si les propriétés d&amp;rsquo;une cible (chemins d&amp;rsquo;inclusion et bibliothèques dépendantes) sont « nécessaires pour sa propre compilation ? » et si elles « doivent être propagées aux autres cibles qui en dépendent ? ».&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>PRIVATE&lt;/code>&lt;/strong> : Nécessaire uniquement pour la compilation de la cible elle-même. Ne se propage &lt;strong>pas&lt;/strong> aux cibles dépendantes.&lt;/li>
&lt;li>&lt;strong>&lt;code>INTERFACE&lt;/code>&lt;/strong> : Inutile pour la compilation de la cible elle-même, mais se propage &lt;strong>aux&lt;/strong> cibles dépendantes (utilisé pour les bibliothèques d&amp;rsquo;en-têtes seuls (header-only), par exemple).&lt;/li>
&lt;li>&lt;strong>&lt;code>PUBLIC&lt;/code>&lt;/strong> : Nécessaire pour la compilation de la cible elle-même ET se propage &lt;strong>aux&lt;/strong> cibles dépendantes (&lt;code>PRIVATE&lt;/code> + &lt;code>INTERFACE&lt;/code>).&lt;/li>
&lt;/ol>
&lt;p>Visualisons la propagation des dépendances (propagation des Exigences d&amp;rsquo;Utilisation - Usage Requirements) avec le schéma suivant.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Bibliothèques"
MathLib["MathLib (Bibliothèque statique)"]
NetworkLib["NetworkLib (Bibliothèque partagée)"]
HeaderLib["HeaderLib (En-tête seulement)"]
end
subgraph "Application"
App["Application principale"]
end
App -- "target_link_libraries(App PRIVATE MathLib)" --> MathLib
App -- "target_link_libraries(App PUBLIC NetworkLib)" --> NetworkLib
NetworkLib -- "target_link_libraries(NetworkLib INTERFACE HeaderLib)" --> HeaderLib
note1["App dépend de l'implémentation de MathLib mais ne l'expose pas à l'extérieur"]
note2["NetworkLib expose l'interface de HeaderLib"]&lt;/div>
&lt;h3 id="exemples-dutilisation-concrets-de-la-portée">Exemples d&amp;rsquo;utilisation concrets de la portée
&lt;/h3>&lt;p>Supposons qu&amp;rsquo;une bibliothèque &lt;code>MyLib&lt;/code> utilise &lt;code>nlohmann/json&lt;/code> comme implémentation interne, mais n&amp;rsquo;inclut pas &lt;code>nlohmann/json&lt;/code> dans son fichier d&amp;rsquo;en-tête public &lt;code>MyLib.hpp&lt;/code>. Dans ce cas, l&amp;rsquo;utilisateur (l&amp;rsquo;application) de &lt;code>MyLib&lt;/code> n&amp;rsquo;a pas besoin de connaître l&amp;rsquo;existence de la bibliothèque JSON.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Définition de la bibliothèque
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">src/MyLib.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Spécification du répertoire d&amp;#39;inclusion du projet lui-même
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Le répertoire include est nécessaire pour ceux qui utilisent MyLib, on utilise donc PUBLIC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Le répertoire src n&amp;#39;est utilisé que pour l&amp;#39;implémentation de MyLib, on utilise donc PRIVATE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_include_directories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PUBLIC&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">INSTALL_INTERFACE:include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">${&lt;/span>&lt;span class="nv">CMAKE_CURRENT_SOURCE_DIR&lt;/span>&lt;span class="o">}&lt;/span>&lt;span class="s">/src&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># La bibliothèque json n&amp;#39;est utilisée que dans l&amp;#39;implémentation interne, on la lie donc avec PRIVATE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">nlohmann_json::nlohmann_json&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>À l&amp;rsquo;inverse, si vous écrivez &lt;code>#include &amp;lt;nlohmann/json.hpp&amp;gt;&lt;/code> dans &lt;code>MyLib.hpp&lt;/code>, ceux qui utilisent &lt;code>MyLib&lt;/code> doivent également connaître le chemin d&amp;rsquo;en-tête de JSON, sinon une erreur de compilation se produira. Vous devez donc le lier avec &lt;code>PUBLIC&lt;/code>. En définissant ces portées de manière appropriée, vous pouvez réduire les temps de compilation et éviter la fuite de dépendances inutiles.&lt;/p>
&lt;h2 id="4-compilation-hors-source-out-of-source-build">4. Compilation hors source (Out-of-source Build)
&lt;/h2>&lt;p>La meilleure pratique à respecter impérativement lors de l&amp;rsquo;utilisation de CMake est la &lt;strong>compilation hors source&lt;/strong> (Out-of-source build).
Il s&amp;rsquo;agit d&amp;rsquo;une méthode où aucun artefact de compilation (fichiers objets ou fichiers exécutables) n&amp;rsquo;est généré dans le répertoire où se trouve le code source (l&amp;rsquo;arborescence des sources), mais ils sont isolés dans un répertoire dédié distinct (généralement &lt;code>build/&lt;/code>) pour effectuer la compilation.&lt;/p>
&lt;div class="mermaid">graph TD
Root["Racine du projet (Dépôt Git)"]
Root --> Src["src/"]
Root --> Inc["include/"]
Root --> CMake["CMakeLists.txt"]
Root -. "Créer le répertoire build" .-> Build["build/ (Hors source)"]
Build --> Obj["CMakeFiles/ (Fichiers objets, caches)"]
Build --> Bin["Binaires (MyApp.exe)"]
Build --> Gen["Makefile généré / build.ninja"]&lt;/div>
&lt;p>Avec cette configuration, si vous souhaitez réinitialiser l&amp;rsquo;environnement de compilation, il vous suffit de supprimer entièrement le répertoire &lt;code>build&lt;/code>. Comme l&amp;rsquo;arborescence des sources reste propre, la gestion avec Git est également simplifiée (il suffit d&amp;rsquo;ajouter &lt;code>build/&lt;/code> à &lt;code>.gitignore&lt;/code>).&lt;/p>
&lt;h3 id="procédure-dexécution-de-la-compilation">Procédure d&amp;rsquo;exécution de la compilation
&lt;/h3>&lt;p>Avec le Modern CMake, vous pouvez exécuter la compilation à l&amp;rsquo;aide d&amp;rsquo;une commande commune indépendante du système d&amp;rsquo;exploitation ou de l&amp;rsquo;outil de compilation.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Configuration et génération (création du répertoire de build et configuration)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake -S . -B build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Compilation réelle (compilation et liaison)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># (Optionnel) Pour compiler en multithread, utilisez l&amp;#39;option -j&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ici, &lt;code>cmake -S . -B build&lt;/code> signifie « définir le répertoire actuel (&lt;code>.&lt;/code>) comme répertoire source et &lt;code>build&lt;/code> comme répertoire de compilation ».&lt;/p>
&lt;h2 id="5-comment-introduire-des-bibliothèques-tierces">5. Comment introduire des bibliothèques tierces
&lt;/h2>&lt;p>Dans le développement C++, l&amp;rsquo;introduction de bibliothèques externes (bibliothèques tierces) a toujours été un obstacle. Cependant, aujourd&amp;rsquo;hui, les trois approches suivantes sont principalement standard.&lt;/p>
&lt;h3 id="51-find_package-recherche-de-bibliothèques-installées-sur-le-système">5.1. find_package (Recherche de bibliothèques installées sur le système)
&lt;/h3>&lt;p>C&amp;rsquo;est la méthode la plus traditionnelle pour trouver et lier des bibliothèques déjà installées sur le système (par exemple : OpenSSL ou Zlib).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">find_package&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB&lt;/span> &lt;span class="s">REQUIRED&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB_FOUND&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">ZLIB::ZLIB&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-fetchcontent-téléchargement-et-intégration-à-partir-du-code-source">5.2. FetchContent (Téléchargement et intégration à partir du code source)
&lt;/h3>&lt;p>Il s&amp;rsquo;agit d&amp;rsquo;un module introduit dans CMake 3.11 et devenu puissant à partir de la version 3.14. Il télécharge directement le code source depuis un dépôt Git externe ou une URL au moment de la compilation et le compile avec votre projet. Comme il permet de centraliser la gestion des dépendances, la reproductibilité multiplateforme est extrêmement élevée.&lt;/p>
&lt;p>Voici un exemple de l&amp;rsquo;introduction de GoogleTest à l&amp;rsquo;aide de FetchContent.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">FetchContent&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">FetchContent_Declare&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">googletest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_REPOSITORY&lt;/span> &lt;span class="s">https://github.com/google/googletest.git&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_TAG&lt;/span> &lt;span class="s">v1.14.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Intégrer la bibliothèque dans le projet
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">FetchContent_MakeAvailable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">googletest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Création et liaison de l&amp;#39;exécutable pour les tests
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">test/main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-intégration-avec-vcpkg">5.3. Intégration avec vcpkg
&lt;/h3>&lt;p>En utilisant &lt;strong>vcpkg&lt;/strong>, le gestionnaire de paquets pour C++ dirigé par Microsoft, vous pouvez facilement introduire des milliers de bibliothèques. vcpkg est conçu pour s&amp;rsquo;intégrer de manière transparente à CMake.&lt;/p>
&lt;p>Lors de l&amp;rsquo;exécution de CMake, il suffit de spécifier le fichier de toolchain de vcpkg pour que &lt;code>find_package&lt;/code> recherche automatiquement les bibliothèques dans vcpkg.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE&lt;span class="o">=&lt;/span>/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>De plus, en plaçant un fichier &lt;code>vcpkg.json&lt;/code> (mode manifeste) à la racine du projet, vous pouvez automatiser complètement la gestion des versions des bibliothèques nécessaires.&lt;/p>
&lt;h2 id="6-drapeaux-de-compilateur-compatibles-multiplateformes-compiler-flags">6. Drapeaux de compilateur compatibles multiplateformes (Compiler flags)
&lt;/h2>&lt;p>Pour que la compilation réussisse dans n&amp;rsquo;importe quel environnement, qu&amp;rsquo;il s&amp;rsquo;agisse de Windows (MSVC), Linux (GCC/Clang) ou macOS (Apple Clang), il est nécessaire de configurer de manière appropriée les drapeaux spécifiques au compilateur.&lt;/p>
&lt;p>En utilisant les &lt;strong>expressions génératrices (Generator Expressions)&lt;/strong> de CMake, vous pouvez décrire de manière déclarative des branchements conditionnels tels que « si le compilateur est MSVC, utilisez ce drapeau, sinon, utilisez celui-ci ». Les expressions génératrices utilisent la syntaxe &lt;code>$&amp;lt;...&amp;gt;&lt;/code> et sont évaluées lors de la génération du système de compilation (phase Generate).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Exemple pour activer le plus haut niveau d&amp;#39;avertissement sur toutes les plateformes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Pour MSVC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;CXX_COMPILER_ID:MSVC&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">:/W4&lt;/span> &lt;span class="s">/WX&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Pour GCC ou Clang
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;OR:$&amp;lt;CXX_COMPILER_ID:GNU&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:Clang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:AppleClang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;gt;:-Wall&lt;/span> &lt;span class="s">-Wextra&lt;/span> &lt;span class="s">-Wpedantic&lt;/span> &lt;span class="s">-Werror&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En utilisant cette méthode, on évite d&amp;rsquo;utiliser excessivement des branchements conditionnels comme &lt;code>if(MSVC)&lt;/code>, ce qui rendrait le &lt;code>CMakeLists.txt&lt;/code> difficile à lire. Cela permet également des configurations flexibles cible par cible.&lt;/p>
&lt;h2 id="7-configuration-de-lenvironnement-de-test-ctest">7. Configuration de l&amp;rsquo;environnement de test (CTest)
&lt;/h2>&lt;p>L&amp;rsquo;introduction de tests automatisés est indispensable pour l&amp;rsquo;assurance qualité dans un environnement multiplateforme. CMake est livré en standard avec un exécuteur de tests appelé &lt;strong>CTest&lt;/strong>.&lt;/p>
&lt;p>La procédure pour intégrer GoogleTest (introduit via &lt;code>FetchContent&lt;/code> précédemment) avec CTest est la suivante.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Activer la fonctionnalité de test (à écrire une seule fois dans le CMakeLists.txt racine)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">test/math_test.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span> &lt;span class="s">MyLib&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Enregistrer en tant que test dans CTest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">GoogleTest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">gtest_discover_tests&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Après la compilation, il suffit d&amp;rsquo;exécuter la commande &lt;code>ctest&lt;/code> dans le répertoire de compilation pour lancer tous les tests et obtenir un rapport des résultats.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ctest --output-on-failure -C Release
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="8-théorie-et-modèle-mathématique-des-systèmes-de-compilation">8. Théorie et modèle mathématique des systèmes de compilation
&lt;/h2>&lt;p>Changeons un peu de perspective et examinons l&amp;rsquo;efficacité des systèmes de compilation et de la compilation parallèle dans les projets à grande échelle, à l&amp;rsquo;aide d&amp;rsquo;un modèle mathématique.&lt;/p>
&lt;p>La réduction du temps de compilation est un défi éternel dans le développement C++. En divisant le code source et en compilant en parallèle, vous pouvez réduire ce temps. L&amp;rsquo;amélioration de la vitesse (Speedup) grâce à cette parallélisation est modélisée par la &lt;strong>loi d&amp;rsquo;Amdahl (Amdahl&amp;rsquo;s Law)&lt;/strong>.&lt;/p>
&lt;p>Si on définit $P$ comme la proportion de la partie du programme qui peut être parallélisée, $1-P$ comme la proportion de la partie qui doit être exécutée de manière séquentielle (non parallélisable), et $N$ comme le nombre de processeurs utilisés, l&amp;rsquo;amélioration théorique maximale de la vitesse globale $S(N)$ est exprimée par la formule suivante :&lt;/p>
$$ S(N) = \frac{1}{(1 - P) + \frac{P}{N}} $$
&lt;p>Dans le processus de compilation C++, la « compilation de chaque fichier &lt;code>.cpp&lt;/code> en fichier &lt;code>.o&lt;/code> ou &lt;code>.obj&lt;/code> » est indépendante et peut être parallélisée (la partie $P$), mais « le processus de liaison (linking) final par le linker » s&amp;rsquo;effectue fondamentalement de manière séquentielle (la partie $1-P$).&lt;/p>
&lt;p>Par conséquent, peu importe combien de cœurs de processeur vous avez à disposition ($N \to \infty$), tant qu&amp;rsquo;il y a le goulot d&amp;rsquo;étranglement du temps de liaison (linking), l&amp;rsquo;amélioration maximale de la vitesse convergera de manière asymptotique vers la formule suivante :&lt;/p>
$$ \lim_{N \to \infty} S(N) = \frac{1}{1 - P} $$
&lt;p>Ce que cette formule suggère, c&amp;rsquo;est qu&amp;rsquo;« il y a une limite à la réduction du temps de compilation par la simple augmentation du nombre de cœurs de processeur ». En utilisant correctement &lt;code>PRIVATE&lt;/code> et &lt;code>INTERFACE&lt;/code> dans le Modern CMake, et en minimisant les dépendances des fichiers d&amp;rsquo;en-tête (par exemple en utilisant des déclarations anticipées - forward declarations), on augmente la proportion de $P$. Réduire le nombre de fichiers à recompiler lors de la compilation incrémentielle constitue la stratégie la plus efficace en pratique pour accélérer la compilation.&lt;/p>
&lt;p>De plus, pour réduire le temps de liaison, il est important de passer des bibliothèques statiques (Static Library) aux bibliothèques partagées / DLL (Shared Library), ou d&amp;rsquo;adopter des linkers rapides tels que LLD ou Mold.&lt;/p>
&lt;p>Dans CMake, vous pouvez facilement spécifier le linker de la manière suivante.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Configuration pour utiliser le linker lld dans un environnement Clang/GCC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">UNIX&lt;/span> &lt;span class="s">AND&lt;/span> &lt;span class="s">NOT&lt;/span> &lt;span class="s">APPLE&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s2">&amp;#34;-fuse-ld=lld&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="9-exemple-pratique-dune-structure-de-répertoires-complexe">9. Exemple pratique d&amp;rsquo;une structure de répertoires complexe
&lt;/h2>&lt;p>Dans le développement d&amp;rsquo;applications réelles, on se retrouve avec une structure de répertoires combinant de nombreux modules. Enfin, voici une structure de répertoires idéale pour un projet de taille moyenne, et la relation parent-enfant entre les fichiers &lt;code>CMakeLists.txt&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">ProjectRoot/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── CMakeLists.txt (Racine : Définition de l&amp;#39;ensemble du projet)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── vcpkg.json (Définition des bibliothèques dépendantes)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── external/ (Modules externes)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── include/ (En-têtes publics)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── myapp/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── src/ (Code source et définitions de compilation internes)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── main.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── math/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── Vector3.hpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ └── Vector3.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── network/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── NetworkManager.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── tests/ (Code de test)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── math_test.cpp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Le fichier &lt;code>CMakeLists.txt&lt;/code> racine gère uniquement les paramètres d&amp;rsquo;environnement et la définition globale des options, tandis que les sous-répertoires sont ajoutés à l&amp;rsquo;aide de &lt;code>add_subdirectory()&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Root &lt;code>CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Paramètres globaux
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Activation des tests
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Ajout des sous-répertoires
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">src&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">tests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>&lt;code>src/CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Ajouter chaque module
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">math&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">network&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Fichier exécutable final
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Liaison des modules
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">MathLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">NetworkLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En divisant le &lt;code>CMakeLists.txt&lt;/code> pour chaque répertoire de cette manière et en définissant les dépendances entre les cibles, vous augmentez la réutilisabilité des modules et améliorez également le parallélisme de la compilation. C&amp;rsquo;est la véritable essence de « l&amp;rsquo;environnement de compilation modularisé » prôné par le Modern CMake.&lt;/p>
&lt;h2 id="10-conclusion">10. Conclusion
&lt;/h2>&lt;p>Nous avons expliqué les étapes de configuration d&amp;rsquo;un environnement de compilation C++ multiplateforme à l&amp;rsquo;aide de CMake.
Récapitulons les points clés.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Compréhension du méta-système de compilation&lt;/strong> : CMake est un outil qui génère des scripts de compilation.&lt;/li>
&lt;li>&lt;strong>Adoption du Modern CMake&lt;/strong> : N&amp;rsquo;utilisez pas de variables. Encapsulez la configuration avec une approche &lt;strong>orientée cible&lt;/strong> comme &lt;code>add_executable&lt;/code>, &lt;code>target_link_libraries&lt;/code>, &lt;code>target_include_directories&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Configuration appropriée de la portée&lt;/strong> : Utilisez correctement &lt;code>PUBLIC&lt;/code>, &lt;code>PRIVATE&lt;/code>, &lt;code>INTERFACE&lt;/code> pour contrôler la propagation des dépendances.&lt;/li>
&lt;li>&lt;strong>Respect strict de la compilation hors source&lt;/strong> : Compilez dans le répertoire &lt;code>build/&lt;/code> afin de ne pas polluer l&amp;rsquo;arborescence des sources.&lt;/li>
&lt;li>&lt;strong>Intégration de bibliothèques tierces&lt;/strong> : Tirez parti de &lt;code>FetchContent&lt;/code> et &lt;code>vcpkg&lt;/code> pour automatiser la résolution des bibliothèques dépendantes.&lt;/li>
&lt;li>&lt;strong>Utilisation des expressions génératrices&lt;/strong> : Absorbez intelligemment les différences de drapeaux entre les compilateurs.&lt;/li>
&lt;li>&lt;strong>Approche mathématique&lt;/strong> : Gardez à l&amp;rsquo;esprit la loi d&amp;rsquo;Amdahl et réduisez les dépendances pour améliorer l&amp;rsquo;efficacité de la compilation parallèle.&lt;/li>
&lt;/ol>
&lt;p>CMake peut sembler difficile à comprendre au début, mais une fois que vous avez saisi les concepts de cibles et de propriétés, vous pouvez maintenir un environnement de compilation bien organisé, quelle que soit la taille ou la complexité du projet C++. N&amp;rsquo;hésitez pas à utiliser cet article comme référence pour configurer votre environnement de développement C++ avec la syntaxe la plus récente du Modern CMake.&lt;/p></description></item></channel></rss>