<
Media
>
Article

Recompiler vos projets C et C++ plus rapidement avec ccache

7 min
10
/
03
/
2022


ccache
est un compiler cache, sous licence GPLv3. Il permet d'accélérer la recompilation de projets C et C++, mais aussi CUDA ou encore Objective-C et Objective-C++ (quelqu'un utilise encore ces 2 langages en 2022 ?). Il supporte les principaux compilateurs du marché: GCC, Clang, MSVC.

Fonctionnement

Comment ccache améliore le build d'un projet ? C'est en fait très simple. Quand vous compilez un fichier, il met le résultat en cache. Quand vous recompilez ce même fichier avec les mêmes options, il récupère directement le fichier objet du cache au lieu de le compiler vraiment.

Vous allez me dire :

Super, mais <span class="css-span">make</span> ne recompile que les fichiers qui ont besoin de l'être, alors pourquoi <span class="css-span">ccache</span> ferait mieux ?

Tout simplement parce <span class="css-span">make</span> regarde l'état de votre projet et le compare au précédent build. Imaginez exécuter les commandes suivantes :

<pre><code>make
make clean
make<code><pre>

Deux scénarios sont possibles lors de l'exécution de la dernière commande :

  1. Vous n'avez pas <span class="css-span">ccache</span>, et <span class="css-span">make</span> recompile tous les fichiers.
  2. Vous avez <span class="css-span">ccache</span>, tous les fichiers objets sont récupérés du cache et le build est très rapide.

Le bonheur quand tu changes de branche

Vous allez me dire que vous faites rarement des <span class="css-span">make</span> clean pour le plaisir. C'est vrai. Mais pensez à un scénario qui vous arrive souvent : le changement de branche avec Git (ou SVN, ou autre).

Imaginez un dossier dans lequel vous avez cloné votre dépôt Git. Vous êtes sur la branche <span class="css-span">master</span> et vous avez compilé l'intégralité du projet. Vous faites un checkout d'une autre branche et vous travaillez sur cette branche. Une heure plus tard, vous revenez sur <span class="css-span">master</span>.

Avec <span class="css-span">ccache</span>, recompiler la branche <span class="css-span">master</span> sera extrêmement rapide car tout est déjà dans le cache !

Le cache n'est pas limité à un dossier. Si vous avez plusieurs branches dans plusieurs dossiers, et que certains fichiers sont compilés de la même manière dans plusieurs branches, alors <span class="css-span">ccache </span>vous fera aussi gagner du temps.

Mettre en place ccache sur son projet

Attention les yeux, ça va aller vite !

Vous téléchargez <span class="css-span">ccache</span>, vous l'installez et vous l'ajouter au PATH.

Vous ajoutez les lignes suivantes à votre <span class="css-span">CMakeLists.txt</span> :

<pre><code>find_program(CCACHE_PROGRAM ccache)

if (CCACHE_PROGRAM)
   message(NOTICE "ccache is enabled (found here: ${CCACHE_PROGRAM})")
   set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "\"${CCACHE_PROGRAM}\"")
   set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "\"${CCACHE_PROGRAM}\"")
else ()
   message(FATAL_ERROR "ccache has not been found")
endif ()<code><pre>

Voilà, c'est tout !

Aucun effet visible ?

Vous avez activé <span class="css-span">ccache</span> et vous ne voyez aucun effet. Ce n'est pas étonnant. Sur le site officiel, on peut lire :

The most important aspect of a compiler cache is to always produce exactly the same output that the real compiler would produce. [...] The only way you should be able to tell that you are using ccache is the speed.

Dans un usage normal, quand vous travaillez sur une branche particulière, vous ne verrez aucun effet. La différence est visible dans certaines situations, notamment quand vous changez de branche, quand vous activez ou désactiver une option de compilation du projet, quand vous modifiez un header inclus dans de nombreux fichiers sources.

De plus, vous ne verrez pas de différence dans la liste de fichiers que CMake dit compiler ; vous verrez une différence sur le temps de build. En effet, CMake pense compiler la même chose, mais <span class="css-span">ccache</span> intercepte les appels au compilateur et décide s'il doit réellement appeler le compilateur, ou s'il peut récupérer un fichier objet dans son cache et le renvoyer directement.

A titre d'exemple, j'ai fait la manipulation suivante sur le projet sur lequel je bosse quotidiennement en mission :

  1. Je me place dans le dossier où se trouve mon projet et donc mon <span class="css-span">CMakeLists.txt</span>.
  2. Je nettoie le cache avec <span class="css-span">ccache --clear</span>.
  3. Je m'assure de partir d'un projet remis à zéro avec <span class="css-span">cmake --build mon_dossier_de_build --target clean</span>.
  4. Je builde mon projet avec <span class="css-span">cmake --build --preset=mon_preset (*)</span>. Lors de cette étape, <span class="css-span">ccache</span> va mémoriser tous les résultats de compilation.
  5. Je cleane à nouveau mon projet.
  6. Je relance à nouveau une compilation. Cette fois, ccache peut utiliser son cache, créé 2 étapes plus haut, et ne recompiler aucun fichier.

Bilan : le premier build a duré 43 minutes ; le second a duré un peu moins de 4 minutes.

Splendide !

(*) = Si vous ne connaissez pas les CMake presets, je vous encourage à lire mon article sur le sujet, je suis sûr que vous allez aimer !

Conclusion

Je ne sais pas comment j'ai fait pour passer à côté de <span class="css-span">ccache</span> pendant 11 ans, dont presque 6 ans d'utilisation quotidienne de C++. Je ne sais pas, vraiment...

Une chose est sûre : ça fait désormais partie de mon <span class="css-span">CMakeLists.txt</span> template ! Comme je change souvent de branche ou que j'active puis désactive des options de debug, je vois souvent l'effet du cache. J'en suis au début de mon utilisation de ccache et je vais prochainement m'intéresser à la pertinence de le mettre en place sur Jenkins.

Je gagne beaucoup de temps en local grâce à <span class="css-span">ccache</span>, et j'espère que vous en tirerez le même bénéfice !

No items found.
ça t’a plu ?
Partage ce contenu
Pierre

Que la vie de Pierre, expert embarqué Younup, serait terne sans les variadic templates et les fold expressions de C++17. Heureusement pour lui, Python a tué l'éternel débat sur l’emplacement de l’accolade : "alors, à la fin de la ligne courante ou au début de la ligne suivante ?"

Homme de terrain, il est aussi à l’aise au guidon de son VTT à sillonner les chemins de forêt, dans une salle de concert de black metal ou les mains dans les soudures de sa carte électronique quand il doit déboguer du code (bon ça, il aime moins quand même !)

Son vœu pieux ? Il hésite encore... Faire disparaitre le C embarqué au profit du C++ embarqué ? Ou stopper la génération sans fin d'entropie de son bureau.