La compilation d'un programme C ++ comprend trois étapes:
Prétraitement: le préprocesseur prend un fichier de code source C ++ et traite les #include
s, #define
s et autres directives de préprocesseur. La sortie de cette étape est un fichier C ++ "pur" sans directives de pré-processeur.
Compilation: le compilateur prend la sortie du pré-processeur et en produit un fichier objet.
Liaison: l'éditeur de liens prend les fichiers objets produits par le compilateur et produit soit une bibliothèque soit un fichier exécutable.
Prétraitement
Le préprocesseur gère les directives du préprocesseur , comme #include
et #define
. Il est indépendant de la syntaxe du C ++, c'est pourquoi il doit être utilisé avec précaution.
Il fonctionne sur un fichier C ++ source à la fois en remplaçant les #include
directives avec le contenu des fichiers respectifs ( ce qui est généralement seulement des déclarations), en faisant le remplacement des macros ( #define
), et en sélectionnant différentes portions de texte en fonction des #if
, #ifdef
et des #ifndef
directives.
Le préprocesseur fonctionne sur un flux de jetons de prétraitement. La substitution de macro est définie comme le remplacement de jetons par d'autres jetons (l'opérateur ##
permet de fusionner deux jetons lorsque cela a du sens).
Après tout cela, le préprocesseur produit une sortie unique qui est un flux de jetons résultant des transformations décrites ci-dessus. Il ajoute également des marqueurs spéciaux qui indiquent au compilateur d'où vient chaque ligne afin qu'il puisse les utiliser pour produire des messages d'erreur sensibles.
Certaines erreurs peuvent être produites à ce stade avec une utilisation intelligente des directives #if
et #error
.
Compilation
L'étape de compilation est effectuée sur chaque sortie du préprocesseur. Le compilateur analyse le code source C ++ pur (désormais sans directives de préprocesseur) et le convertit en code assembleur. Invoque ensuite le back-end sous-jacent (assembleur dans la chaîne d'outils) qui assemble ce code en code machine produisant un fichier binaire réel dans un certain format (ELF, COFF, a.out, ...). Ce fichier objet contient le code compilé (sous forme binaire) des symboles définis dans l'entrée. Les symboles dans les fichiers objets sont désignés par leur nom.
Les fichiers objets peuvent faire référence à des symboles qui ne sont pas définis. C'est le cas lorsque vous utilisez une déclaration et n'en fournissez pas de définition. Le compilateur ne s'en soucie pas et produira volontiers le fichier objet tant que le code source est bien formé.
Les compilateurs vous permettent généralement d'arrêter la compilation à ce stade. Ceci est très utile car avec lui, vous pouvez compiler chaque fichier de code source séparément. L'avantage que cela offre est que vous n'avez pas besoin de tout recompiler si vous ne modifiez qu'un seul fichier.
Les fichiers objets produits peuvent être placés dans des archives spéciales appelées bibliothèques statiques, pour une réutilisation plus facile plus tard.
C'est à ce stade que les erreurs de compilation "normales", comme les erreurs de syntaxe ou les erreurs de résolution de surcharge échouées, sont signalées.
Mise en relation
L'éditeur de liens est ce qui produit la sortie de compilation finale à partir des fichiers objets produits par le compilateur. Cette sortie peut être soit une bibliothèque partagée (ou dynamique) (et bien que le nom soit similaire, ils n'ont pas grand-chose en commun avec les bibliothèques statiques mentionnées précédemment) ou un exécutable.
Il relie tous les fichiers objets en remplaçant les références aux symboles non définis par les adresses correctes. Chacun de ces symboles peut être défini dans d'autres fichiers objets ou dans des bibliothèques. S'ils sont définis dans des bibliothèques autres que la bibliothèque standard, vous devez en informer l'éditeur de liens.
À ce stade, les erreurs les plus courantes sont les définitions manquantes ou les définitions en double. La première signifie que les définitions n'existent pas (c'est-à-dire qu'elles ne sont pas écrites) ou que les fichiers ou bibliothèques d'objets où elles résident n'ont pas été fournis à l'éditeur de liens. Cette dernière est évidente: le même symbole a été défini dans deux fichiers ou bibliothèques d'objets différents.