Compilation et Création de Bibliothèques en C
Ce document présente les principes fondamentaux de la compilation, de l'édition de liens, et de la création et utilisation de bibliothèques en langage C sous Linux. Il s'adresse aux étudiants et développeurs souhaitant comprendre comment créer des fichiers objets, des bibliothèques statiques et dynamiques, et comment les utiliser dans un programme principal.
D'après le document Compilation et Création de Bibliothèques en C
Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.
Document source
Programming, C Language, Libraries · PDF · 10 pages
Afficher l'aperçu du document
Ce document présente les principes fondamentaux de la compilation, de l'édition de liens, et de la création et utilisation de bibliothèques en langage C sous Linux. Il s'adresse aux étudiants et développeurs souhaitant comprendre comment créer des fichiers objets, des bibliothèques statiques et dynamiques, et comment les utiliser dans un programme principal.
Création des fichiers sources et fichiers d'en-tête
Une bibliothèque en C est constituée d'un fichier source contenant plusieurs fonctions, mais sans fonction main. Ce fichier source peut être compilé en :
- un fichier objet (.o)
- une bibliothèque statique (.a)
- une bibliothèque dynamique (.so)
Le programme principal, qui contient la fonction main, peut ensuite utiliser les fonctions et variables globales de cette bibliothèque.
Exemple de fichier source de bibliothèque : toto.c
#include <stdio.h>
int ma_variable=5;
void ma_fonction()
{
printf("Bienvenue dans Ma Fonction !\n");
}
int mon_addition(int i,int j)
{
printf("Bienvenue dans Mon Addition !\n");
return (i+j);
}
Fichier d'en-tête associé : toto.h
int ma_variable;
void ma_fonction();
int mon_addition(int i,int j);
Remarques importantes :
- Le fichier d'en-tête n'est pas généré automatiquement, il doit être écrit manuellement.
- Dans la déclaration des paramètres des fonctions, chaque paramètre doit avoir son type explicitement indiqué, même si plusieurs paramètres sont du même type. Par exemple,
int i, int jest correct, maisint i,jne l'est pas.
Programme principal utilisant la bibliothèque : titi.c
#include <stdio.h>
#include "toto.h"
int main(void)
{
printf("---- Début du programme principal ----\n");
ma_fonction();
printf("Ma_variable vaut : %i\n", ma_variable);
printf("6+7=%i\n", mon_addition(6,7));
printf("---- Fin du programme principal ----\n");
return 0;
}
Note : #include "toto.h" indique que le fichier d'en-tête se trouve dans le répertoire courant. Si on écrit #include <toto.h>, gcc cherchera dans le répertoire système /usr/include.
Compilation des fichiers sources
1. Création et utilisation d'un fichier objet
Pour compiler le fichier source toto.c en fichier objet toto.o, on utilise l'option -c de gcc :
gcc -c toto.c
Cette commande produit le fichier objet toto.o sans effectuer l'édition de liens.
La commande objdump -t toto.o affiche la table des symboles du fichier objet, montrant les fonctions et variables définies.
Compilation du programme principal titi.c
Une compilation simple :
gcc titi.c
génère une erreur de lien :
undefined reference to `ma_fonction`
undefined reference to `mon_addition`
Car le corps des fonctions est dans toto.o, non indiqué à l'éditeur de liens.
Pour corriger cela, il faut indiquer le fichier objet lors de la compilation :
gcc titi.c toto.o
Le programme s'exécute alors correctement :
---- Début du programme principal ----
Bienvenue dans Ma Fonction !
Ma_variable vaut : 5
Bienvenue dans Mon Addition !
6+7=13
---- Fin du programme principal ----
2. Création et utilisation d'une bibliothèque statique
Une bibliothèque statique sous Linux a l'extension .a. Pour créer une bibliothèque statique libtoto.a à partir de toto.o :
ar cr libtoto.a toto.o
ranlib libtoto.a
La table des symboles peut être affichée avec :
objdump -t libtoto.a
Pour compiler titi.c en utilisant cette bibliothèque statique :
gcc titi.c libtoto.a
Le programme s'exécute alors de la même manière qu'avec le fichier objet.
Avantages : Le code de la bibliothèque est intégré dans l'exécutable, qui n'est plus dépendant des bibliothèques externes.
Inconvénient : Toute modification de la bibliothèque nécessite de recompiler le programme principal.
3. Création et utilisation d'une bibliothèque dynamique
Une bibliothèque dynamique sous Linux a l'extension .so. Pour créer une bibliothèque dynamique libtoto.so :
gcc -o libtoto.so -shared toto.o
La table des symboles est visible avec :
objdump -t libtoto.so
Pour compiler titi.c en utilisant la bibliothèque dynamique :
gcc -ltoto -L. titi.c
-ltotoindique à l'éditeur de liens d'utiliserlibtoto.so-L.indique que la bibliothèque se trouve dans le répertoire courant
Sans l'option -L., gcc cherche les bibliothèques dans /usr/lib par défaut.
4. Récapitulatif des commandes gcc
gcc toto.c: compilation + édition de liens → exécutablea.outgcc -c toto.c: compilation seule → fichier objettoto.ogcc toto.o: édition de liens seule → exécutablea.out
Pour un exécutable, une seule fonction main doit être présente. Si des fonctions externes sont utilisées, il faut indiquer leurs fichiers objets ou bibliothèques à gcc.
Exemple de compilation de titi.c avec la bibliothèque toto :
gcc titi.c toto.cgcc titi.c toto.ogcc titi.c libtoto.agcc titi.c -ltoto
Utilitaires pour la gestion des bibliothèques partagées
- ldd <programme> : affiche les bibliothèques partagées utilisées par un programme.
- ldconfig : régénère les liens symboliques dans les répertoires de bibliothèques partagées (listés dans
/etc/ld.so.conf), permettant de gérer plusieurs versions d'une bibliothèque sans arrêter le système. L'option-vaffiche les bibliothèques installées. - export LD_LIBRARY_PATH=`pwd` : ajoute le répertoire courant au chemin de recherche des bibliothèques partagées.
- ltrace : suit les appels aux fonctions des bibliothèques dynamiques effectués par un programme, utile pour le débogage.
Exemple d'utilisation de ltrace
Pour un programme a.out compilé avec libtoto.so, la commande :
ltrace a.out
affiche les appels aux fonctions de la bibliothèque, comme :
ma_fonction()
printf("Bienvenue dans Ma Fonction !\n")
mon_addition(6,7)
printf("Bienvenue dans Mon Addition !\n")
La commande :
ldd a.out
montre les bibliothèques partagées utilisées, par exemple :
libtoto.so => /usr/lib/libtoto.so
libc.so.6 => /lib/tls/libc.so.6
Utilisation des bibliothèques existantes dans le système
Les fonctions courantes sont souvent déjà disponibles dans des bibliothèques installées, par exemple pour afficher une image JPEG ou lire un fichier MP3.
1. Connaître les bibliothèques installées
La commande :
ldconfig -v
affiche toutes les bibliothèques installées. Pour rechercher une bibliothèque liée au traitement JPEG :
ldconfig -v | grep jpeg
On trouve par exemple libjpeg.so dans /usr/lib.
2. Connaître les fonctions disponibles dans une bibliothèque
Pour afficher la table des symboles d'une bibliothèque :
objdump -T /usr/lib/libjpeg.so
On peut filtrer les fonctions avec :
objdump -T /usr/lib/libjpeg.so | grep Base
Ce qui affiche une liste des fonctions exportées, par exemple :
- jpeg_read_header
- jpeg_start_decompress
- jpeg_finish_decompress
- etc.
3. Trouver le fichier d'en-tête associé
Les fichiers d'en-tête sont généralement dans /usr/include. Pour trouver celui lié à JPEG :
ls /usr/include/*jpeg*.h
On obtient par exemple /usr/include/jpeglib.h.
Note : le fichier d'en-tête ne porte pas toujours le même nom que la bibliothèque partagée (ex. libjpeg.so vs jpeglib.h).
4. Exemple d'utilisation de la bibliothèque libjpeg.so
Le programme suivant affiche la résolution d'une image JPEG :
/* Ce programme test.c affiche la résolution d'une image toto.jpg en utilisant libjpeg.so */
#include <stdio.h>
#include <jpeglib.h>
int main(void)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *file;
char *fichier = "toto.jpg";
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
if ((file = fopen(fichier, "rb")) == NULL)
{
fprintf(stderr, "Erreur : impossible d'ouvrir le fichier texture.jpg\n");
exit(1);
}
jpeg_stdio_src(&cinfo, file);
jpeg_read_header(&cinfo, TRUE);
printf("La largeur de l'image est %i pixels\n", cinfo.image_width);
printf("La hauteur de l'image est %i pixels\n", cinfo.image_height);
return 0;
}
Pour compiler ce programme :
gcc -ljpeg test.c
À l'exécution, on obtient par exemple :
La largeur de l'image est 400 pixels
La hauteur de l'image est 342 pixels
Glossaire des termes clés
- Fichier objet (.o) : fichier produit par la compilation d'un fichier source, contenant du code machine non lié.
- Bibliothèque statique (.a) : archive de fichiers objets intégrée dans l'exécutable lors de l'édition de liens.
- Bibliothèque dynamique (.so) : bibliothèque partagée chargée au moment de l'exécution, permettant la mutualisation du code.
- Éditeur de liens (linker) : outil qui combine plusieurs fichiers objets et bibliothèques pour produire un exécutable.
- Table des symboles : liste des fonctions et variables définies ou utilisées dans un fichier objet ou une bibliothèque.
- gcc : compilateur GNU pour le langage C, qui effectue compilation et édition de liens.
- ar : utilitaire pour créer des archives, utilisé pour fabriquer des bibliothèques statiques.
- ranlib : utilitaire qui génère un index pour une archive, facilitant l'accès aux symboles.
- ldd : commande affichant les bibliothèques partagées utilisées par un exécutable.
- ldconfig : commande qui met à jour les liens symboliques des bibliothèques partagées du système.
- ltrace : outil pour tracer les appels aux fonctions des bibliothèques dynamiques d'un programme.
- Fichier d'en-tête (.h) : fichier contenant les déclarations de fonctions et variables, utilisé pour l'interface entre sources.
Points clés à retenir
- Un fichier source de bibliothèque ne contient pas de fonction
mainet peut être compilé en fichier objet, bibliothèque statique ou dynamique. - Le fichier d'en-tête doit être écrit manuellement et déclare les prototypes des fonctions et variables globales.
- Pour utiliser une bibliothèque dans un programme, il faut indiquer à l'éditeur de liens le fichier objet ou la bibliothèque correspondante.
- Les bibliothèques statiques sont intégrées à l'exécutable, tandis que les bibliothèques dynamiques sont chargées à l'exécution.
- Les outils
objdump,ldd,ldconfigetltracesont essentiels pour gérer et déboguer les bibliothèques. - Les bibliothèques système sont souvent déjà installées et documentées, avec leurs fichiers d'en-tête dans
/usr/include. - Pour compiler un programme utilisant une bibliothèque système, il faut inclure le fichier d'en-tête et lier la bibliothèque avec
-l.
Commentaires
Aucun commentaire pour le moment. Posez la première question.