Compilation

publicité
Chapitre 1
Compilation
C
1
e chapitre ne constitue pas un cours de compilation, naturellement, mais donne les bases nécessaires à
l’utilisation raisonnée d’un compilateur. Après une présentation très générale d’un ordinateur, nous ferons la différence entre langage machine, assembleur et langages de haut niveau. Ensuite nous étudierons
les différentes phases dans la compilation d’un logiciel.
Modèle de l’ordinateur
Le modèle d’ordinateur encore utilisé aujourd’hui correspond à l’architecture de Von Neumann. Ce dernier, mathématicien
hongrois, l’a proposée en 1945. Le modèle est schématisé sur la figure 1.1.
Unité de
contrôle
Unité arithmétique
Registres
Unité d’entrées
sorties
Mémoire contenant les programmes
et les donnés
Fig. 1.1 – Modèle de Von Neumann
Le processeur de l’ordinateur, qui regroupe l’unité de contrôle, l’unité arithmétique et l’unité d’entrées/sorties
est un condensé d’électronique, capable d’effectuer des actions qui ont été câblées. Ces actions, très primitives,
constituent le jeu d’instructions de la machine. Programmer un ordinateur consiste à lui indiquer les instructions
(les actions) qu’il doit effectuer, dans l’ordre. Un tel programme est dit programme en langage machine, et c’est le
seul langage que l’ordinateur connaı̂t. Les actions possibles sont, par exemple, consulter le contenu de la mémoire
ou des registres, y écrire, déclencher une opération d’entrées/sorties, ou bien modifier le déroulement du programme
lui-même en omettant d’exécuter certains actions, ou en exécutant à nouveau certaines d’entre elles. Un processeur
peut exécuter une seule instruction à la fois (en première approximation).
Le texte du programme lui-même est écrit dans la mémoire. C’est le système d’exploitation (qui est lui même un
programme, et qui est lancé au démarrage de la machine1 ) qui se charge d’exécuter tel ou tel programme inscrit
en mémoire.
2
Langage machine
Un programme en langage machine est difficilement lisible. Il est uniquement constitué de nombres. Certains de
ces nombres codent les actions à effectuer, et d’autres, par exemple, des adresses en mémoire, ou des valeurs.
On peut imaginer que chaque action, avec ses opérandes, est codée sur un nombre de 8 bits. Les deux premiers
identifient l’opération, le suivant un numéro de registre et les cinq suivants une adresse en mémoire. L’opération
de charger (Load) le contenu de l’adresse 12 dans le registre A (numéroté 0) sera codée par : 01 0 01100=76 si
1 Comme
MacOS, GNU/Linux ou Windows.
1
2
Compléments Algo-Prog – Gea 2–
l’action Load porte le code 01. Naturellement, les microprocesseurs actuels ont un jeu d’instructions plus large et
des données plus grandes. En conclusion, un programme écrit en langage machine est clairement illisible.
Une autre façon d’écrire un programme, plutôt que sous forme de nombres, constitue le langage assembleur2 .
L’instruction précédente serait écrite Load A,12, ce qui est déjà plus évocateur que 76. Néanmoins, de nos jours, le
langage assembleur est assez peu utilisé3 . Il a laissé sa place à essentiellement deux types de langages : les langages
compilés et les langages interprétés. Dans le premier cas (C, C++, Fortran, Pascal, Cobol, Ada, ...), le programmeur
écrit le code source de son programme dans un langage évolué, par exemple le C, qui n’est pas compréhensible par
la machine. Puis, un logiciel nommé compilateur aura pour tâche de transformer ce code source en langage machine.
Cette opération est appelée la compilation. Une fois transformé en langage machine, le programme est exécutable
par la machine, mais n’est plus compréhensible par un humain. Une autre particularité des langages compilés est
que les programmes exécutables sont dépendants de la plate-forme. Un programme en langage machine est en effet
dépendant du type de microprocesseur (du type de matériel en général), et du système d’exploitation (à cause des
appels-systèmes). Par conséquent, un programme compilé sur un PC Intel avec Linux ne fonctionnera pas sur le
même PC Intel avec Windows, ni sur une machine à base de 68000 avec Linux...
Un langage interprété (Basic, Logo, Lisp, Prolog...) s’utilise à l’aide d’un interpréteur. Un interpréteur est un
programme qui va lire le code source, et exécuter une à une, chacune des opérations qu’il contient. Un programme
écrit dans un langage interprété est souvent plus lent, en moyenne, qu’un programme compilé, pour la bonne raison
que l’interpréteur doit, à la volée, comprendre et traduire le texte du programme pour demander à la machine de
l’exécuter.
3
Compilation d’un programme en C
Nous entendons ici par compilation les deux étapes suivantes :
– la compilation proprement dite ;
– puis d’édition de liens.
La première étape transforme un fichier source C en fichier objet, (à peu de choses près des bouts de programme
écrits en langage machine). L’étape d’édition de liens regroupe des fichiers objets entre eux de façon à obtenir un
programme complet, écrit en langage machine, qui peut être exécuté.
La distinction entre les deux étapes est souvent nécessaire à la compréhension des erreurs. Une erreur de compilation
signifie généralement que le compilateur n’a pas compris ce qui est inscrit dans le code source. Une erreur d’édition
de liens signifie souvent qu’il manque quelque chose aux fichiers objets pour créer un programme complet.
La plupart des environnements de développement intégrés (IDE) maintiennent cette différence et la création d’un
programme s’effectue en deux étapes : Compile, puis Link. Avec un compilateur en ligne de commandes comme
gcc, ces deux étapes sont distinctes aussi :
– gcc -c fic1.c
Compilation de fic1.c, création de fic1.o
– gcc -c fic2.c
Compilation de fic2.c, création de fic2.o
– gcc -o programme fic1.o fic2.o
Édition de lien, les fichiers fic1.o et fic2.o sont regroupés pour
former le programme nommé programme
Ces deux étapes peuvent être regroupées en une ligne :
– gcc -o programme fic1.c fic2.c
mais il n’en reste pas moins vrai que les deux étapes sont effectuées
successivement.
L’intérêt de ce type de compilation (dite compilation séparée) est de minimiser les temps de compilation. Lorsqu’un
fichier est modifié, seul celui-ci doit être recompilé, et l’édition de liens doit également être refaite.
Lorsqu’une application est composée de plusieurs centaines de fichiers, alors qu’une compilation complète peut
durer plus d’une heure, une recompilation due à une modification mineure ne prendra que deux ou trois minutes.
Techniquement parlant, il est à noter qu’un fichier d’en-tête .h inclus dans un fichier .c fait partie intégrante de
ce dernier. Donc la modification d’un .h implique la recompilation de tous les .c l’incluant (ainsi que l’édition de
liens). Et de même si l’on modifie un .h inclus dans un autre .h lui-même inclus dans un .c...
Les IDE se chargent de gérer et d’optimiser les compilations. En ligne de commandes, un outil spécial est chargé
de ce travail : la commande make et le fichier Makefile.
2 Ce terme est utilisé par abus. L’assembleur est le logiciel qui transforme un programme écrit sous forme de mnémoniques en langage
machine. Par extension, on appelle aussi assembleur le langage constitué par ces mnémoniques.
3 En ce qui concerne l’informatique domestique. En informatique industrielle ou embarquée, il n’est pas rare d’utiliser l’assembleur.
3
1. Compilation
4
4.1
Paramétrer Dev-C++
Chemins d’inclusions et de bibliothèques
On suppose que les bibliothèques installées par le programmeur sont situées dans C :/usr/lib et que les fichiers
d’en-tête correspondants sont dans C :/usr/include. Ces deux chemins doivent être précisés dans les boı̂tes
suivantes Outils/Options du compilateur/Répertoires :
Boı̂te 1
4.2
Boı̂te 2
Options d’édition de liens
Les bibliothèques à lier doivent être précisées dans les options du projet (Projet / Options du projet / Paramètres),
comme indiqué sur la boı̂te 3.
4.3
Option ((tous les warnings))
Vous devez prendre l’ahabitude de profiter de toutes les possibilités du compilateur pour vous aider. En particulier,
certains Warnings sont passés sous silence par défaut. Une simple option indique au compilateur qu’il vous prévienne
de constructions douteuses et vous permette de gagner beaucoup de temps de débuggage. L’option -Wall doit être
indiquée à partir du menu (Projet / Options du projet / Paramètres) comme indiqué sur la boı̂te 4.
Boı̂te 3
Boı̂te 4
Téléchargement