next up previous
Next: À propos de ce Up: Initiation au langage C Previous: Les bibliothèques standards

Sous-sections

La compilation

  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.


  
Figure 10.1: Des fichiers sources à l'exécutable
\begin{figure}\index{compilation!phases successives}
\setlength{\unitlength}{0....
...sembleur}
{\footnotesize\itshape Éditions des liens}
\end{picture} \end{figure}

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 différents fichiers

   
fichiers sources (*.c, *.h)

Les fichiers sources contiennent le programme original. Tous les autres fichiers sont recalculables à partir des seuls fichiers sources. L'extension <<.c>> est réservée aux fichiers directement compilables. L'extension <<.h>> est réservée aux fichiers inclus par le préprocesseur.

   
fichiers sources après préprocesseur (*.i)

Après passage dans le préprocesseur, les fichiers en-têtes <<.h>> sont directement intégrés dans le source <<.c>>. Toutes les macro-commandes sont expansées. Les commentaires sont supprimés. Il ne reste plus aucune directive propre au préprocesseur.

   
fichiers assembleurs (*.s)

Le fichier assembleur est le résultat de la compilation d'un fichier source. L'assembleur est un langage spécifique à la machine choisie. A chaque fichier source <<.c>> correspond un fichier en assembleur. La plupart des compilateurs ne stockent pas ce fichier intermédiaire et, en appelant seul l'assembleur, produise directement un fichier objet. L'extension <<.s>> est réservée aux fichiers en assembleur.

   
fichiers objets (*.o)

Un fichier objet contient le code nécessaire à la définition des objets (variables ou fonctions) qu'il contient. Ce code peut faire référence à des objets indéfinis (externes au fichier objet). Un fichier objet contient une table des objets qu'il définit et des objets externes qu'il utilise. L'extension <<.o>> est réservée aux fichiers objets.

     
fichiers bibliothèques (*.a)

Une bibliothèque archive plusieurs fichiers objets en un seul fichier. L'extension <<.a>> est réservée aux fichiers bibliothèque (library en anglais). Une bibliothèque contient une table des fichiers objets qu'elle contient.

   
fichiers exécutables

Les fichier exécutable constitue le programme lui-même. Il est utilisable en tant que nouvelle commande.

   
fichiers images mémoire (core)

    Le fichier 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.

préprocesseur

      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.

   
les commentaires

Les commentaires en C débutent par <</* >> 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.

#include

  La directive <<#include>> permet d'inclure un autre fichier à l'intérieur d'un fichier source. Ce fichier est tout d'abord cherché dans le même répertoire que le fichier source (.c) puis dans une liste de répertoires prédéfinis. Cette liste est spécifique au compilateur utilisé. En général, elle regroupe les chemins d'accès des répertoires contenant les fichiers d'en-têtes (.h) liés aux fonctions systèmes. Un fichier en-tête peut lui-même inclure d'autres fichier en-tête.

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"

#define

La directive <<#define>> permet de définir la suite de caractères qui devra remplacer un symbole donné. Cela permet de définir une bonne fois pour toutes, un symbole constant. Il devient alors facile de changer la valeur de ce symbole en changeant sa définition.

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);

autres directives

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.

la suite de la compilation

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.

les commande à l'EMAC

  Le tableau 10.1 résume les commandes à utiliser sur les stations de travail de l'EMAC pour faire du C.


 
 
Tableau 10.1: Commandes de compilation (de l'EMAC)
Commande Système Distributeur ANSI débogueur
cc SunOS 4.1.x Sun non dbx - xdbx
gcc SunOS 4.1.x GNU oui gdb - xxgdb
acc SunOS 4.1.x Sun oui dbx - xdbx
cc Solaris 2.x Sun oui dbx - workshop
gcc Solaris 2.x GNU oui gdb - ddd

Note : Depuis l'été 1997, la plupart des stations de travail de l'EMAC utilisent le système Solaris 2.x.


next up previous
Next: À propos de ce Up: Initiation au langage C Previous: Les bibliothèques standards

Copyright © EMAC - 1997 - Paul GABORIT