🔝 Retour au Sommaire
Chapitre 2 · Section 2.3 · Accélération de compilation · Niveau Débutant
Dans la section précédente, nous avons vu comment invoquer ccache manuellement (ccache g++ -c main.cpp). En pratique, personne ne tape les commandes de compilation à la main sur un projet réel — c'est le build system (CMake + Ninja, CMake + Make, ou un Makefile écrit à la main) qui orchestre les appels au compilateur. L'enjeu est donc de faire en sorte que chaque appel au compilateur passe par ccache de manière transparente, sans modifier le code ni les fichiers source du projet.
Trois approches existent, chacune adaptée à un contexte différent. Nous les présentons de la plus recommandée à la plus globale.
Depuis CMake 3.4, la variable CMAKE_<LANG>_COMPILER_LAUNCHER permet de spécifier un programme qui sera inséré devant chaque invocation du compilateur. Quand on configure cette variable avec ccache, CMake génère des règles de build qui ressemblent à :
ccache /usr/bin/g++-15 -std=c++23 -O2 -c main.cpp -o main.o
Le build system (Ninja ou Make) ne voit rien de particulier — il exécute cette commande comme n'importe quelle autre. ccache intercepte l'appel, vérifie le cache, et retourne le résultat caché ou délègue au compilateur réel.
La manière la plus directe :
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccacheCes deux variables couvrent respectivement les compilations C (gcc) et C++ (g++). Spécifiez les deux pour être certain que tous les fichiers sources passent par ccache.
Après la configuration, vous pouvez vérifier que ccache est bien intégré en lançant un build avec l'option verbose :
cmake --build build --verbose 2>&1 | head -20Vous devriez voir ccache apparaître devant chaque appel au compilateur dans la sortie :
[1/4] ccache /usr/bin/g++-15 -std=c++23 -O2 ... -c main.cpp -o CMakeFiles/programme.dir/main.cpp.o
[2/4] ccache /usr/bin/g++-15 -std=c++23 -O2 ... -c utils.cpp -o CMakeFiles/programme.dir/utils.cpp.o
...
Si ccache n'apparaît pas, vérifiez que le binaire est bien dans votre PATH (which ccache) et que les variables ont été correctement passées lors de la configuration (cmake -B build ... -DCMAKE_CXX_COMPILER_LAUNCHER=ccache).
⚠️ Les variablesCMAKE_<LANG>_COMPILER_LAUNCHERsont des variables de cache CMake : elles sont fixées lors de la première configuration (cmake -B build ...) et persistent dans le répertoire de build. Si vous avez déjà configuré le projet sans ccache, deux options s'offrent à vous : supprimer le répertoire de build et reconfigurer, ou modifier la variable dans le cache existant :# Option A : reconfigurer de zéro rm -rf build cmake -B build -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache # Option B : modifier le cache existant cmake -B build -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
Certaines équipes préfèrent inscrire le support ccache directement dans le CMakeLists.txt du projet, de manière à ce qu'il soit automatiquement activé si ccache est présent sur la machine, et silencieusement ignoré sinon :
cmake_minimum_required(VERSION 3.25)
project(MonProjet LANGUAGES CXX)
# Activer ccache automatiquement s'il est disponible
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
message(STATUS "ccache trouvé : ${CCACHE_PROGRAM} — activation automatique")
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
else()
message(STATUS "ccache non trouvé — compilation sans cache")
endif()
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(mon_programme main.cpp utils.cpp)Cette approche a l'avantage d'être auto-adaptative : sur une machine de développement où ccache est installé, la compilation est accélérée ; sur un serveur de production ou dans un conteneur minimal sans ccache, le build fonctionne normalement. Le message(STATUS ...) informe le développeur de l'état lors de la configuration.
Pour les projets d'équipe, il peut être utile d'offrir un contrôle explicite :
option(USE_CCACHE "Utiliser ccache pour accélérer la compilation" ON)
if(USE_CCACHE)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
message(STATUS "ccache activé : ${CCACHE_PROGRAM}")
else()
message(WARNING "USE_CCACHE est ON mais ccache n'est pas trouvé dans le PATH")
endif()
endif()Un développeur qui souhaite désactiver ccache peut alors passer -DUSE_CCACHE=OFF lors de la configuration.
Les CMake Presets (fichier CMakePresets.json versionné avec le projet) sont la manière la plus propre de standardiser la configuration de build au sein d'une équipe. Voici un exemple intégrant ccache :
{
"version": 6,
"cmakeMinimumRequired": {
"major": 3,
"minor": 25,
"patch": 0
},
"configurePresets": [
{
"name": "dev-gcc",
"displayName": "Développement GCC (avec ccache)",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-gcc",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "g++-15",
"CMAKE_C_COMPILER": "gcc-15",
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
"CMAKE_C_COMPILER_LAUNCHER": "ccache",
"CMAKE_CXX_STANDARD": "23",
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "dev-clang",
"displayName": "Développement Clang (avec ccache)",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-clang",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "clang++-20",
"CMAKE_C_COMPILER": "clang-20",
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
"CMAKE_C_COMPILER_LAUNCHER": "ccache",
"CMAKE_CXX_STANDARD": "23",
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "release",
"displayName": "Release (sans ccache)",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-release",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "g++-15",
"CMAKE_C_COMPILER": "gcc-15",
"CMAKE_CXX_STANDARD": "23",
"CMAKE_BUILD_TYPE": "Release"
}
}
]
}Utilisation :
# Configurer avec le preset dev-gcc (ccache activé)
cmake --preset dev-gcc
# Compiler
cmake --build --preset dev-gcc
# Configurer avec le preset release (sans ccache)
cmake --preset releaseChaque membre de l'équipe utilise les mêmes presets, garantissant une configuration identique. Les presets de développement incluent ccache pour la vitesse ; le preset release peut l'omettre si la reproductibilité bit-à-bit est prioritaire. Nous approfondirons les CMake Presets à la section 27.6.
Cette approche exploite les liens symboliques créés par le paquet ccache dans /usr/lib/ccache. En plaçant ce répertoire en tête du PATH, chaque appel à g++, gcc, clang++, etc. est intercepté par ccache de manière totalement transparente — ni CMake, ni Make, ni aucun autre outil n'a besoin d'être modifié.
Ajoutez cette ligne à votre ~/.bashrc (ou ~/.zshrc selon votre shell) :
# Activer ccache globalement via le PATH
export PATH="/usr/lib/ccache:$PATH"Rechargez le shell :
source ~/.bashrcwhich g++
# Output :
# /usr/lib/ccache/g++
# Vérifier que c'est bien un lien vers ccache
file /usr/lib/ccache/g++
# Output :
# /usr/lib/ccache/g++: symbolic link to ../../bin/ccache
# Le vrai compilateur reste accessible
/usr/bin/g++ --version | head -1Désormais, toute compilation C/C++ sur cette machine passe par ccache, quel que soit l'outil qui l'invoque : CMake, Make, Ninja, scripts manuels, ./configure && make, etc.
Quand ccache est invoqué sous le nom g++ (via le lien symbolique), il examine le nom sous lequel il a été appelé (argv[0]), détermine que le compilateur réel est /usr/bin/g++, et procède à sa logique habituelle de hash/cache. Ce mécanisme fonctionne pour tous les compilateurs supportés : gcc, g++, cc, c++, clang, clang++, et leurs variantes versionnées (g++-15, clang++-20, etc.).
Selon votre installation Ubuntu et la version du paquet ccache, les liens symboliques versionnés (comme g++-15 ou clang++-20) peuvent ne pas être présents dans /usr/lib/ccache. Si c'est le cas, vous pouvez les créer manuellement :
sudo ln -sf /usr/bin/ccache /usr/lib/ccache/g++-15
sudo ln -sf /usr/bin/ccache /usr/lib/ccache/gcc-15
sudo ln -sf /usr/bin/ccache /usr/lib/ccache/clang++-20
sudo ln -sf /usr/bin/ccache /usr/lib/ccache/clang-20 Vérification :
which g++-15
# Output attendu :
# /usr/lib/ccache/g++-15| Aspect | Verdict |
|---|---|
| Simplicité de mise en place | ✅ Excellente — une ligne dans .bashrc |
| Couverture | ✅ Totale — tous les outils en bénéficient |
| Transparence | ✅ Aucune modification des fichiers de build |
| Explicite / traçable | ❌ Un collègue ne voit pas que ccache est actif |
| Reproductibilité | ❌ Dépend de la configuration du poste |
| Contrôle fin | ❌ Pas de moyen d'exclure un projet spécifique |
Si vous avez besoin de compiler sans ccache ponctuellement (par exemple pour un benchmark de compilation ou pour diagnostiquer un problème) :
# Option 1 : contourner le PATH pour une commande
CCACHE_DISABLE=1 cmake --build build
# Option 2 : utiliser le chemin absolu du compilateur
/usr/bin/g++-15 -std=c++23 -O2 -c main.cpp -o main.o
# Option 3 : retirer temporairement ccache du PATH
export PATH=$(echo "$PATH" | sed 's|/usr/lib/ccache:||')La variable d'environnement CCACHE_DISABLE=1 est la méthode la plus propre : ccache reçoit l'appel mais le transmet immédiatement au compilateur réel sans consulter ni alimenter le cache.
Une troisième approche, historique mais déconseillée, consiste à définir ccache g++ comme compilateur CMake :
# ⚠️ Non recommandé
cmake -B build -G Ninja -DCMAKE_CXX_COMPILER="ccache;g++-15"ou avec un script wrapper :
#!/bin/bash
# /usr/local/bin/ccache-g++
exec ccache g++-15 "$@"cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=/usr/local/bin/ccache-g++Ces approches fonctionnent techniquement, mais posent des problèmes : CMake ne détecte plus correctement le compilateur (les checks internes échouent parfois), les IDEs peuvent être confus, et l'identification de la version du compilateur dans les messages de CMake est erronée. La variable CMAKE_CXX_COMPILER_LAUNCHER a été créée spécifiquement pour résoudre ces problèmes — utilisez-la.
Si vous travaillez avec un Makefile écrit à la main (sans CMake), deux méthodes s'offrent à vous.
La méthode la plus explicite :
# Makefile avec ccache
CXX = ccache g++-15
CC = ccache gcc-15
CXXFLAGS = -std=c++23 -Wall -Wextra -O2
CFLAGS = -Wall -Wextra -O2
SRCS = main.cpp utils.cpp engine.cpp
OBJS = $(SRCS:.cpp=.o)
TARGET = programme
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $@ $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: cleanDans cette configuration, make invoque ccache g++-15 ... pour chaque compilation. La syntaxe ccache g++-15 est traitée par le shell comme une commande (ccache) suivie de ses arguments (g++-15, les flags, etc.).
Si /usr/lib/ccache est en tête de votre PATH (approche 2), vous n'avez rien à modifier dans le Makefile :
# Makefile classique — ccache est transparent via le PATH
CXX = g++-15
CC = gcc-15
CXXFLAGS = -std=c++23 -Wall -Wextra -O2
# ... (le reste du Makefile est identique)g++-15 résout vers /usr/lib/ccache/g++-15, qui est ccache. Aucune modification du Makefile nécessaire.
Pour un Makefile qui fonctionne avec ou sans ccache, selon la préférence du développeur :
# Le développeur peut activer ccache avec : make CCACHE=ccache
CCACHE ?=
CXX = $(CCACHE) g++-15
CC = $(CCACHE) gcc-15
CXXFLAGS = -std=c++23 -Wall -Wextra -O2
SRCS = main.cpp utils.cpp engine.cpp
OBJS = $(SRCS:.cpp=.o)
TARGET = programme
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $@ $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: cleanUtilisation :
# Sans ccache
make -j$(nproc)
# Avec ccache
make -j$(nproc) CCACHE=ccacheLa variable ?= donne une valeur par défaut (vide) qui peut être surchargée en ligne de commande. Quand CCACHE est vide, $(CCACHE) g++-15 se réduit à g++-15 (Make ignore l'espace en tête).
Si vous travaillez avec le build system Meson (présenté à la section 28.4), l'intégration se fait différemment. Meson ne dispose pas d'un équivalent direct à CMAKE_CXX_COMPILER_LAUNCHER, mais il détecte et utilise ccache automatiquement s'il est présent dans le PATH. Ce comportement est activé par défaut.
Pour forcer ou désactiver cette détection :
# Forcer l'utilisation de ccache (créer un fichier cross/native)
# Dans un native file (ex: native.ini) :
# [built-in options]
# cmake_prefix_path = ...
# Ou simplement via le PATH (méthode recommandée)
export PATH="/usr/lib/ccache:$PATH"
meson setup build Pour désactiver ccache avec Meson :
# Via la variable d'environnement
CCACHE_DISABLE=1 meson setup buildPour un temps de build optimal, ccache ne suffit pas : il n'accélère que la compilation (transformation de .cpp en .o). L'étape de liaison (assemblage des .o en exécutable ou bibliothèque) n'est pas cachée par ccache. Pour accélérer cette étape également, combinez ccache avec le linker rapide lld (projet LLVM) ou mold :
# Installation de lld
sudo apt install lld
# Configuration CMake complète : ccache + Ninja + lld
cmake -B build -G Ninja \
-DCMAKE_CXX_COMPILER=clang++-20 \
-DCMAKE_C_COMPILER=clang-20 \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \
-DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=lld"Avec GCC, vous pouvez également utiliser lld ou mold :
# Installation de mold
sudo apt install mold
# Configuration CMake : ccache + Ninja + mold + GCC
cmake -B build -G Ninja \
-DCMAKE_CXX_COMPILER=g++-15 \
-DCMAKE_C_COMPILER=gcc-15 \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" \
-DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold"La chaîne complète ccache + Ninja + lld (ou mold) est celle qui offre les meilleurs temps de build en 2026 :
| Composant | Accélère | Remplace |
|---|---|---|
| ccache | Compilation (.cpp → .o) |
Rien — intercepte le compilateur |
| Ninja | Orchestration du build | Make |
| lld / mold | Liaison (.o → exécutable) |
GNU ld |
| Approche | Portée | Explicite | Effort | Contexte recommandé |
|---|---|---|---|---|
CMAKE_CXX_COMPILER_LAUNCHER |
Un projet CMake | ✅ Oui | Faible | Projets CMake (recommandé) |
| CMake Presets | Un projet CMake | ✅ Oui | Moyen | Projets d'équipe avec CMake |
find_program dans CMakeLists.txt |
Un projet CMake | ✅ Oui | Moyen | Projets open source |
PATH /usr/lib/ccache |
Toute la machine | ❌ Non | Faible | Développement local, tous outils |
Préfixe ccache dans Makefile |
Un projet Make | ✅ Oui | Faible | Makefiles sans CMake |
| Wrapper script / substitution | Un projet | ❌ Non | Élevé | ❌ Éviter |
Pour la suite de cette formation, nous utiliserons systématiquement l'approche CMAKE_CXX_COMPILER_LAUNCHER=ccache, soit en ligne de commande, soit via CMake Presets.
CMAKE_CXX_COMPILER_LAUNCHER=ccacheest la méthode recommandée pour les projets CMake : elle est explicite, portable, et compatible avec tous les générateurs (Ninja, Make, etc.).- Le PATH
/usr/lib/ccacheest la méthode la plus simple pour un usage global : une seule ligne dans.bashrcet toute compilation C/C++ de la machine est accélérée, quel que soit le build system. - N'utilisez pas la substitution du compilateur (
CMAKE_CXX_COMPILER="ccache;g++") — la variableCOMPILER_LAUNCHERexiste pour ça. - Pour un Makefile sans CMake, préfixez la variable
CXXou utilisez l'approche PATH. - Combinez ccache avec Ninja (orchestration rapide) et lld ou mold (liaison rapide) pour des temps de build optimaux.
CCACHE_DISABLE=1permet de désactiver ccache ponctuellement sans modifier la configuration.