La compilation est un terme qui recouvre en fait plusieurs opérations successives qui permettent de transformer un ensemble de fichiers sources en un programme utilisable.
La figure 10.1 décrit ces différentes opérations et les fichiers produits. La plupart des compilateurs effectue l'ensemble de la transformation en un seul passage (tout du moins du point de vue de l'utilisateur). Pour demander au compilateur de n'effectuer qu'une partie de la transformation, il faut lui passer des options particulières.
Chacune des phases de la transformation effectue ses propres vérifications et engendre donc ses propres messages d'erreur.
Nous allons commencer par présenter les différents type de fichiers puis, pour chacune des phases, nous détaillerons ses objectifs et ses moyens de contrôle.
Les fichier exécutable constitue le programme lui-même. Il est utilisable en tant que nouvelle commande.
core
constitue l'image mémoire
exacte d'un programme à un instant donné (ce fichier
est généralement produit lors d'une erreur). À partir
de cette image mémoire (et de l'exécutable lui-même),
on peut examiner l'état de toutes la variables et même
faire continuer le programme.
Lors de sa compilation, chaque fichier source subit une première phase de transformation par simple remplacement de texte et inclusion de fichiers. C'est le préprocesseur qui se charge de cette phase. Dans cette opération, les noms des fichiers inclus sont remplacés par leurs contenus, les macrocommandes sont expansée et les commentaires sont supprimés.
/*
>> et se terminent par
<<*/
>>. Ils peuvent être placés partout où il est possible de
placé un espace. Ils ne peuvent pas être imbriqués les uns
dans les autres.
Normalement le nom du fichier à inclure est placé entre guillemets
("
). S'il est placé entre inférieur et supérieur (<>
),
ce fichier n'est cherché que dans la liste des répertoires
prédéfinis et non pas dans le répertoire courant :
/* stdlib.h est un fichier système */
#include <stdlib.h>
/* monfichier.h est un fichier en-tête a moi... */
#include "monfichier.h"
Par exemple, on peut définir TVA comme étant 18,6% de la manière suivante :
#define TVA 18.6
...
prixTTC = prixHT * (1 + TVA/100);
À partir de ce moment, à chaque fois que le préprocesseur
rencontrera le symbole TVA
, il le remplacera par
18.6
.
Ceci facilite la modification du programme. Par exemple si le taux de TVA devient 20,6%, il est plus facile de modifier la ligne précédente que tous les endroits où le taux de TVA était utilisé :
#define TVA 20.6
...
prixTTC = prixHT * (1 + TVA/100);
La directive #define peut prendre des paramètres pour définir des macrocommandes.
Par exemple, on peut définir la macrocommande MAX
de
la manière suivante :
#define MAX(a, b) ((a > b) ? a : b)
À chaque fois que le préprocesseur rencontrera le symbole
MAX
suivi de deux arguments entre parenthèses, il le
remplacera par la définition donnée dans laquelle a
et
b
seront remplacés par les deux textes fournis. Par
exemple la ligne suivante :
a = MAX(3 - b, 18);
sera remplacée par :
a = (( 3 - b > 18 ) ? 3 - b : 18);
Le préprocesseur propose beaucoup d'autres directives telles que
#if
, #ifdef
, #else
qui permettent de faire de la
compilation conditionnelle. Nous ne rentrerons pas dans le détail de
ces directives.
Une fois la phase de « préprocessing » passée, on passe à la phase de compilation proprement dite. C'est cette phase qui génère la plupart des messages d'erreur.
Les bons compilateurs essaient de produire des messages d'erreur les plus claires possibles. Mais il est impossible de garantir que ces messages sont bons sinon le compilateur corrigerait lui-même les erreurs s'il était sûr de son diagnostique.
Le résultat de la compilation est un fichier en code assembleur qui sera passé à l'assembleur. Cette phase ne devrait généralement pas échouée ou produire de messages (sauf par manque d'espace disque).
Le fichier produit est alors un fichier objet (en code machine).
Il ne reste plus que la phase d'édition des liens qui va relier tous les fichiers objets, les bibliothèques utilisateurs et les bibliothèques systèmes pour produire enfin l'exécutable. C'est lors de cette phase que la machine détecte les objets définis plusieurs fois dans différents fichiers objets ou ceux qui ne sont définis nulle part.
Le tableau 10.1 résume les commandes à utiliser sur les stations de travail de l'EMAC pour faire du C.
Note : Depuis l'été 1997, la plupart des stations de travail de l'EMAC utilisent le système Solaris 2.x.