I. À quoi servent les en-têtes précompilés (Pre-Compiled Header : PCH) ?

Afin de bien comprendre l'utilité des en-têtes précompilés, nous allons d'abord rappeler le processus de génération d'un exécutable à partir des fichiers source.

C:\Article_Dvp\documents\BCBPCH\image1.png

La première étape est le préprocesseur, qui va traiter toutes les instructions commençant par un # (include, define). C'est donc cette étape qui va remplacer tous les #include par le contenu du fichier spécifié, ce qui par exemple pour l'instruction #include <vcl.h> va provoquer la lecture de 354 fichiers et générer 220 000 Lignes (visible en exécutant le précompilateur par clic droit Préprocesseur)

C:\Article_Dvp\documents\BCBPCH\image2.png

Si on ajoute Firedac, TChart, DevExpress on obtiendra 365 000 lignes.

Ensuite le résultat du préprocesseur va être transmis au compilateur (ces deux opérations sont généralement exécutées ensemble lors de la compilation).

Ces étapes auront lieu pour chaque fichier source (.cpp) donc, si par exemple, votre projet contient 20 fichiers sources qui incluent en moyenne 300 k lignes et 400 fichiers, la compilation devra traiter 6 millions de lignes issues de 8000 fichiers ce qui peut prendre un peu de temps.

Si on considère que vos fichiers source font moins de 3000 lignes chacun en moyenne, on voit vite que le précompilateur et le compilateur passent plus de 99 % de leur temps à traiter les fichiers des bibliothèques qui ne changent jamais. De surcroit ce traitement est similaire pour chacun des fichiers source.

Les en-têtes précompilés sont un mécanisme qui va permettre de ne traiter qu'une fois un ensemble de fichiers et de les précompiler afin de mutualiser cet effort entre les fichiers source du projet et entre les compilations successives ce qui va avoir un impact très significatif sur le temps de compilation.

II. Mise en œuvre

Ce concept n'est pas nouveau, cette fonction est présente de façon transparente depuis très longtemps dans le compilateur classique bcc32.

 
Sélectionnez
#include <vcl.h>
#include <vector>
#pragma hdrstop
#include "Unit1.h"

Dans cet exemple vcl.h et vector étaient précompilés alors que unit1.h ne l'était pas.

Avec le compilateur bcc32 classique, dans un fichier .cpp tout ce qui est avant #pragma hdrstop est précompilé.

Mais avec le précompilateur Clang, la logique est différente. Le principe est d'utiliser un fichier (PCH.h par exemple) qui contiendra les fichiers header que l'on souhaite précompiler et d'inclure ce fichier dans le processus de compilation au moyen d'une option passée en ligne de commande au compilateur.

Dans les dernières versions de C++ Builder, tout nouveau projet est créé avec un tel fichier, mais pour les projets existants que vous souhaitez porter sur Clang, il vous faudra le faire vous-même.

Étape 1 : créez un fichier PCH.h (ou tout autre nom qui vous convient) et remplissez-le avec les includes des bibliothèques que vous utilisez fréquemment dans votre projet sous forme d'instructions #include classique.

#include <vcl.h> sera un minimum qui améliorera les performances.

Il sera pertinent d'y ajouter d'autres headers.

Attention, certains headers ne fonctionnent pas correctement dans les PCH, par exemple ceux contenant des #pragma (c'est le cas de certains include FireDac).

On veillera à ne pas y mettre des fichiers headers qui changent fréquemment afin de ne pas recompiler trop souvent le fichier PCH et de perdre une partie du bénéfice qu'il apporte normalement en réutilisant les données entre les compilations successives.

Étape 2 : définissez ce fichier pour l'utilisation comme fichier d'en-tête précompilé dans le gestionnaire de projet, par un clic droit sur le fichier et clic sur « Utiliser pour la précompilation » dans le menu contextuel.

Cette opération va intégrer la précompilation des en-têtes dans le processus de génération du projet et ajouter l'option -include-pch .\Win32\Debug\Pch.pch dans la ligne de commande du compilateur qui va faire une inclusion implicite du fichier Pch.h dans sa version précompilée (Pch.pch) avant de lire le fichier source.

III. Utilisation de l'expert en-tête précompilé

Cet expert permet d'analyser le projet pour déterminer les fichiers qu'il serait pertinent de précompiler.

Attention ! Cet expert semble avoir été conçu pour le compilateur classique et les modifications qu'il fait dans le projet ont tendance à désactiver les réglages existants (supprimer l'utilisation du fichier PCH existant) et à ne faire la configuration que pour le compilateur classique, il faudra donc appliquer manuellement l'étape 2 décrite précédemment à l'issue de l'exécution de cet expert.

C:\Article_Dvp\documents\BCBPCH\image3.png
C:\Article_Dvp\documents\BCBPCH\image4.png
C:\Article_Dvp\documents\BCBPCH\image5.png
C:\Article_Dvp\documents\BCBPCH\image6.png
C:\Article_Dvp\documents\BCBPCH\image7.png

Le changement du nom du fichier de sortie dans cet écran a tendance à ne pas bien fonctionner, donc ne le changez pas, ça vous évitera des soucis. Vous pouvez aussi vous contenter de l'analyse affichée dans l'écran précédent pour gérer vous-même votre fichier.

IV. Project options 

Dans les options du projet, une partie est dédiée à la gestion des en-têtes précompilés, cependant cette page est surtout utilisée par le compilateur classique comme vous le voyez dans cette image et sur cette page de la documentation : http://docwiki.embarcadero.com/RADStudio/Berlin//en/C%2B%2B_Compiler_Precompiled_Headers

C:\Article_Dvp\documents\BCBPCH\image8.png

V. Conclusion 

Nous avons vu qu'il est facile de mettre en place les en-têtes précompilés, il y a jusque quelques petits pièges à éviter, mais vous verrez que le jeu en vaut la chandelle, car les gains en temps de compilation de vos projets en seront grandement réduits.

VI. Remerciements

Merci à Claude Leloup pour la relecture orthographique.