Leçon 2 : Compilation séparée
Objectifs de la leçon 2 « compilation séparée »
- Déduire les avantages de la programmation modulaire.
- Ecrire un programme informatique sur des fichiers séparés.
-
Identifier les commandes qui permettent la compilation séparée de
plusieurs fichiers sources.
-
Identifier les commandes qui permettent l’édition de liens de
plusieurs fichiers objets.
- Reconnaitre les outils de déclarations des fonctions et d’inclusion
des fichiers en-tête.
Plan de la leçon 2 « compilation séparée »
o 2.1 Introduction
o 2.2 Exemple
o 2.3 Compilation de plusieurs fichiers
o 2.4 Déclarations des fonctions et inclusion des fichiers en-
tête
24
2.1 Introduction :
En langage C, il est possible, et même conseillé, de partager le code source sur plusieurs
fichiers. En effet, lorsqu’un programme est constitué de nombreuses fonctions, il est
préférable de les diviser en plusieurs fichiers sources. Ceci est le principe de la
Publicité
programmation modulaire, qui consiste à découper un programme informatique en des
fichiers séparés tels qu’un seul fichier source contient la fonction main. Ceci permet de :
- Avoir des bouts de codes plus lisibles et réutilisables.
- Donner une structure plus lisible au programme.
- Quand un changement est nécessaire, seul le fichier source contenant le
changement doit être recompilé, et non pas l’ensemble du programme, ce
qui permet d’optimiser la maintenance du code et surtout le temps de
compilation.
Toutefois, la programmation modulaire impose une compilation séparée des différents fichiers
qui composent le programme. Notons qu’afin d’éviter la compilation répétitive des mêmes
fichiers qui n’ont pas été modifiés, on met souvent en place un mécanisme de compilation
conditionnelle, qui tient compte d’un ensemble de commandes pour savoir ce qui doit être
compilé ou pas. Pour ce faire, on fait recours à l’outil « makefile » qui fera l’objet de la leçon
4.
2.2 Exemple :
Soit les deux programmes « comp_sep.c » et « fonctions.c » suivants :
Figure 2.1 Capture d’écran du fichier « comp_sep.c ».
25
Figure 2.2 Capture d’écran du fichier « fonctions.c ».
En essayant de compiler le programme « comp_sep.c », le compilateur C affiche que les deux
fonctions « somme » et « produit » ne sont pas déclarées et l’éditeur de liens « ld » (link
editor), qui est un éditeur de liens GNU (utiliser « man ld » pour plus d’informations sur les
options de cette commande), détecte que les deux mêmes fonctions ne sont pas définies quand
il essaie de générer un exécutable. Le problème se résume au fait que les deux fonctions sont
Publicité
assis hors dans un autre fichier. De même, en essayant de compiler le programme
« fonctions.c », l’éditeur de liens « ld » détecte que la fonction principal « main » est indéfini
quand il essaie de produire un exécutable. Encore une fois, le problème est que la totalité du
programme ne correspond pas à un seul fichier.
26
2.3 Compilation de plusieurs fichiers :
La procédure de compilation, d’édition des liens, et d’exécution du programme que nous
avons réparti sur deux fichiers, devrait être comme suit :
- Compiler d’abord chacun des programmes sources (« .c ») séparément tout
en utilisant l’option « -c » de la commande « gcc », comme suit :
gcc –c comp_sep.c
gcc –c fonctions.c
- Relier ensuite les deux fichiers objets produits (« .o ») en un seul
programme exécutable, comme suit :
gcc-o executable comp_sep.o fonctions.o
- Lancer enfin l’exécution de l’exécutable produit, comme suit :
./executable
Notons qu’il est possible de faire les deux premières étapes (compilation et édition des liens)
en un seul coup, comme suit :
gcc -o executable comp_sep.c fonctions.c
27
En modifiant le programme principal « comp_sep.c » et ceci en changeant par exemple
Publicité
l’ordre des appels des deux fonctions, il faut refaire toutes les étapes énumérées ci-dessus,
sauf qu’il n’est pas nécessaire de recompiler le programme « fonctions.c » car il n’a pas
changé. En effet, seuls les fichiers modifiés doivent être recompilés, ce qui permet
d’économiser du temps.
28
2.4 Déclarations des fonctions et inclusion des fichiers en-tête :
Malgré que l’éditeur des liens réussit à produire un exécutable, chaque fois qu’on compile le
programme « comp-sep.c » avec la commande « gcc –Wall », le compilateur affiche que
« somme » et « produit » sont des fonctions non-déclarées. En effet, vu que ces deux
fonctions ne sont pas déclarées dans le programme principal « comp_sep.c », le compilateur
n’a aucun moyen de vérifier qu’elles sont utilisées correctement. Si nous faisons une erreur
(par exemple, en utilisant trop d’arguments, trop peu d’arguments, ou le mauvais type
d’arguments), nous ne le saurons pas jusqu’à ce que le programme affiche des résultats
incorrects ou se bloque lors de l’exécution même. Si nous voulons profiter des avantages de la
vérification de type, nous devons être sûrs que tout est déclaré. Pour ce faire, il suffit d’ajouter
les deux lignes suivantes dans le fichier « comp_sep.c » (au-dessus de la fonction « main ») :
int sonme (int );
int produit (int );
29
Toutefois, dans le cas où plusieurs programmes utilisent les fonctions contenues dans le
fichier « fonctions.c », il est indispensable de rappeler dans chaque programme les en-têtes
des fonctions qui seront utilisées dans ce programme. Il s’agit d’une procédure fastidieuse et
Publicité
sujette d’erreurs, notamment dans le cas de modifications fréquentes des fonctions (par
exemple, les déclarations dans le fichier « comp_sep.c » peuvent devenir différentes des en-
têtes dans le fichier « fonctions.c »). Pour cela, il est préférable de créer un nouveau fichier
« fonctions.h » qui ne contient que les déclarations des fonctions du fichier « fonctions.c ».
Figure 2.3 Capture d’écran du fichier « fonctions.h ».
Ensuite, il suffit de modifier le programme principal « comp_sep.c » et ceci en éliminant les
déclarations ajoutées des deux fonctions « somme » et « produit » tout en y ajoutant la ligne
« #include "fonctions.h" » dans l’entête du fichier. Il s’agit d’une direction au compilateur à
se comporter comme si le contenu du fichier « fonctions.h » a été effectivement saisis ici.
Notons que le nom du fichier a été entouré avec des guillemets au lieu de crochets, comme
c’est le cas pour les fichiers d’en-têtes prédéfinis, vu que le fichier « fonctions.h » se trouve
dans le même répertoire que le programme source « comp_sep.c ». En effet, « #include
"fonctions.h" » indique que le fichier d’en-tête « fonctions.h » se trouve dans le répertoire
courant, alors que si on met « #include <fonctions.h> » la commande « gcc » cherchera le
fichier d’en-tête « fonctions.h » dans le répertoire « /usr/include ». Ainsi, pour pouvoir utiliser
les fonctions contenues dans « fonctions.h », il suffit de mettre la ligne « #include
"fonctions.h" » dans le programme et aucune copie des déclarations n’est plus nécessaire.
30
31