2.11. Appel d'un compilateur C
La notice d'utilisation succincte d'un compilateur C est la
suivante :
cc compile les fichiers se terminant par '.c', assemble ceux qui se terminent par '.s' et passe les options non mentionnées ci-dessous à l'éditeur de lien 'ld'.
utilisation : cc [options] fichier ...
options :
-c compile seulement, sans édition de liens; les fichiers objets ont pour nom celui obtenu en remplaçant '.c' ou '.s' par '.o'
-Dchaine[=valeur] demande au préprocesseur de définir 'chaine' avec 'valeur'
-Uchaine demande au préprocesseur de retirer toute définition initiale de 'chaine'
-Ichemin demande de rechercher les fichiers 'include'dans le répertoire 'chemin'
-E demande de lancer seulement le préprocesseur et d'écrire sa sortie sur stdout
-S demande de compiler en langage d'assemblage, sans assembler; les fichiers résultats ont pour nom celui obtenu en remplaçant '.c' par '.s'
-g demande de produire les informations de mise au point
-O2 demande d'optimiser le code
A- Décrire
brièvement les étapes essentielles de la production de
programme.
B- Dans ce contexte, expliquer l'option
-c et la commande suivante :
cc -c toto.c
C- Décrire
le rôle d'un préprocesseur et expliquez les options
-D,
-U,
-I. Comment interprétez-vous les
deux commandes suivantes :
cc -DBUFSIZE=2048 -DUNIX -c schmilblick.c
cc -DBUFSIZE=1024 -DMS_DOS -c schmilblick.c
D- Décrire
brièvement les fonctions du metteur au point, et expliquer le rôle
de l'option -g dans la chaîne de
production de programme.
E- Quel est le rôle de l'option
-O2? Expliquer la commande
suivante :
cc -O2 toto.c -o toto
F- Expliquer
l'utilité des options -E et
-S.
Solution de l'exercice
2.11.
2.11.1. Question A.
La construction d'un programme se fait souvent de façon
modulaire. En effet, dès qu'il est d'une certaine taille, il est
nécessaire de le morceler, pour manipuler des entités
cohérentes et dont on maîtrise la complexité. Le
découpage modulaire permet aussi la réutilisation des modules dans
différents programmes. Ces modules peuvent être écrits dans
différents langages (évolués ou d'assemblage). Chacun d'eux
doit alors être traduit pour donner un module objet de sémantique
équivalente, mais dans un langage intermédiaire proche du langage
de la machine. C'est le rôle des compilateurs ou des assembleurs d'assurer
cette traduction. Ces modules objets doivent ensuite être regroupés
pour constituer un programme exécutable. C'est le rôle de
l'éditeur de liens d'une part de translater les modules pour qu'ils
puissent résider dans des emplacements de mémoire centrale
différents, et d'autre part de résoudre les liens entre les
modules, en associant les liens à satisfaire d'un module avec un lien
utilisable situé dans un autre module. Enfin, le programme
exécutable doit être mis en mémoire centrale pour son
exécution. C'est le rôle du chargeur d'assurer cette mise en
mémoire (translation finale éventuelle) et de préparer son
environnement d'exécution (construction de la machine
abstraite).
2.11.2. Question B.
La notice d'utilisation précise dès le
début que cc assure la compilation
des modules écrits en langage C, l'assemblage des modules en langage
d'assemblage et l'édition de liens de l'ensemble des modules. En d'autres
termes, il s'agit d'un programme qui enchaîne l'ensemble des
activités de la chaîne de production de programme, à
l'exception du chargement. Cela facilite la construction des programmes
constitués de peu de modules.
L'option permet d'empêcher cet enchaînement
lorsque le programme final est constitué de plusieurs modules qui sont
compilés séparément. Elle est particulièrement utile
lorsqu'on utilise des outils automatiques comme le
make qui détermine les
opérations strictement nécessaires à la construction d'un
programme en évitant celles qui ne sont pas utiles.
Ainsi la commande cc -c
toto.c est une demande de compilation sans édition de liens
du fichier toto.c. Le résultat sera
mis dans le fichier toto.o.
2.11.3. Question C.
Le rôle du préprocesseur est de faire un
traitement sur le texte source lui-même avant la compilation proprement
dite. Il permet de paramétrer le texte source, et de fixer les valeurs
des paramètres au moment de la compilation. Un même texte source
peut alors être utilisé dans diverses situations, comme on le
montrera avec les deux commandes. En particulier, le préprocesseur
réalise essentiellement trois modifications :
- remplacement des chaînes qui lui ont
été définies par la valeur correspondante,
- insertion ou suppression de portions de textes,
suivant qu'une chaîne est définie ou
non,
- inclusion d'un autre fichier, dans le
texte.
L'option -D
permet précisément de donner une définition à une
chaîne, valable pour cette compilation, sans modifier le fichier source
lui-même. Evidemment, ceci n'a de sens que si le fichier source fait
référence à cette chaîne.
L'option -U permet de
supprimer une définition présente dans le fichier, pour cette
compilation.
L'option -I permet de
préciser le répertoire où il y a lieu de rechercher les
fichiers qui sont mentionnés dans une clause
'#include' du fichier source. C'est
particulièrement utile pour permettre de regrouper dans un
répertoire spécifique les fichiers utilisés en
inclusion.
Les deux commandes suivantes concernent la compilation du
même fichier en langage C.
cc -DBUFSIZE=2048 -DUNIX -c schmilblick.c
cc -DBUFSIZE=1024 -DMS_DOS -c schmilblick.c
Elles
définissent d'une part la chaîne
BUFSIZE comme une constante avec des
valeurs différentes dans les deux cas et d'autre part deux chaînes
différentes sans leur donner de valeur. La première définit
la chaîne UNIX, et la seconde la
chaîne MS_DOS. Ces deux chaînes
seront plutôt utilisées, dans le fichier, pour insérer ou
supprimer du texte. Intuitivement, le fichier
schmilblick.c contient un module qui est
paramétré pour être compilé soit pour un
système UNIX, soit pour un
système MS_DOS. La première
commande produira le module objet adapté à
UNIX, alors que la seconde produira celui
adapté à MS_DOS.
Répétons que ceci n'a de sens que si le fichier contient des
clauses '#ifdef UNIX' ou
'#ifdef MS_DOS'.
2.11.4. Question D.
Des outils ont été construits pour permettre la
mise au point d'un programme. Ces outils sont appelés metteurs au point.
Les fonctionnalités essentielles sont les suivantes :
- mettre ou supprimer des points d'arrêt
dans le programme en cours de test,
- consulter ou
modifier les variables lorsque le programme est
arrêté,
- relancer l'exécution
du programme après un
arrêt,
- exécuter le programme en pas
à pas.
Il est plus facile pour l'utilisateur de
désigner les points d'arrêt ou les variables sous une forme proche
du langage dans lequel il a écrit les modules, c'est-à-dire sous
forme symbolique, en utilisant les identificateurs des modules. Pour cela, il
faut que le metteur au point puisse faire la transformation entre ces
identificateurs et les adresses en mémoire centrale. Ceci
nécessite la coopération entre les constituants essentiels de la
chaîne de production de programme. L'option
-g demande au compilateur de rajouter dans
le module objet les informations qui sont utiles au metteur au point, comme par
exemple, la table des symboles et la table des numéros de lignes. Ces
informations seront modifiées par l'éditeur de liens qui tiendra
compte des translations effectuées, et les mettra dans le fichier qui
contient le programme exécutable, où le metteur au point ira les
chercher.
2.11.5. Question E.
L'écriture des modules dans un langage
évolué implique une description de haut niveau,
éloignée des contraintes matérielles. L'optimisation est
une opération effectuée par le compilateur sur le code produit de
façon à en améliorer l'efficacité. C'est une
opération coûteuse en temps, car elle est complexe. Elle est
inutile sur des modules qui ne sont pas complètement au point. Elle peut
d'ailleurs perturber la mise au point car elle peut entraîner des
déplacements d'instructions et des suppressions de variables. C'est
pourquoi elle doit être optionnelle.
La commande cc -O2 toto.c -o
toto est une demande de compilation du fichier
toto.c. Le résultat sera mis dans le
fichier toto.o. Cette compilation doit se
faire avec optimisation de code. Ensuite l'éditeur de liens est
appelé sur le fichier toto.o, avec
les options -o toto. On peut penser que
cette option permet de donner le toto au
fichier résultat de l'édition de liens.
2.11.6. Question F.
L'option -E permet de
consulter le résultat du traitement du texte source par le
préprocesseur. On peut y voir deux intérêts. D'une part,
lorsque le texte source contient des commandes complexes au
préprocesseur, cela permet de vérifier leur bonne
interprétation. D'autre part, cela permet d'utiliser le
préprocesseur lui-même sur des textes quelconques, qui ne sont pas
des modules en langages C. Si on désire conserver le résultat du
traitement, il suffira alors de rediriger la sortie
stdout vers un fichier.
L'option -S permet
d'obtenir le résultat de la compilation en langage d'assemblage. Son
utilité est en général réservé à des
spécialistes. D'une part, Elle permet de se servir du compilateur comme
première étape de préparation d'un module en langage
d'assemblage, qui est ensuite adapté et modifié selon les besoins.
Si le compilateur est doté d'un bon optimiseur, cette possibilité
est souvent d'un intérêt limité. D'autre part elle permet de
connaître le code produit par le compilateur sous une forme lisible, ce
qui peut s'avérer parfois utile dans des situations de mise au point
difficiles.