Les librairies

 

Introduction aux librairies

Les librairies sont des fichiers contenant de fonctions qui peuvent être réutilisées par différentes applications (simultanément ou non)

Il existe deux types de librairies:

- Les librairies statiques qui sont des librairies qui fonctionnent de façon similaires aux objets (.o) que vous créez lors de la compilation d'un code source.

Pour rappel, les fichiers objets (.o) sont des fichiers contenant du code compilé de votre source en C/C++ donc presque exécutable (code machine). Presque car ils manquent certaines informations, comme les adresses des fonctions ou variables qui ne sont pas déclarées dans ce fichier objet, mais dans un tout autre fichier. Ce sera alors le rôle du linker de déterminer ces adresses pour ces fonctions ou variables et de construire à partir des différents fichiers objets (linker <=> lier les différents objets du projet) le code exécutable correspondant.

En fait, il ne s'agit ni plus ni moins que d'un ensemble de fichiers objets (.o) contenus dans un même fichier. Un peu comme une archive, d'où l'extension utilisée .a !

Les avantages étant:

- le fichier exécutable généré contient tout le code nécessaire pour fonctionner (sera inclus dans le code les fonctions de la librairie utilisée).

- Je n'en vois pas d'autres...

Les inconvénients étant:

- qu'il est nécessaire de recompiler tous les programmes utilisant une librairie statique, si celle-ci se voit corrigée d'un bug.

- La taille de l'exécutable est importante (puisqu'il contient tout le code nécessaire).

- Il y a en quelque sorte duplication du code (toutes les applications utilisant la librairie posséde le code binaire de celle-ci).

 

- Les librairies dynamiques qui sont des librairies que les programmes vont utiliser au moment de l'exécution et non plus au moment de la compilation.

 

Leurs avantages:

- Votre programme n'aura pas une taille démesurée (comme ce serait le cas avec les librairies statiques).

- Facilité de maintenance, puisqu'il suffira de corriger un bug présent dans la librairie pour qu'automatiquement les applications soient maj.

- Chargées qu'une seule fois en mémoire même si plusieurs programmes l'utilisent (classique, mais bon à rappeler)

 

Les inconvénients:

- Vous ne pouvez pas apporter de grosses modifications sur une librairie (par exemple pas de modifications de signatures des fonctions permises, car cela rendrait tous les applications l'utilisant incompatibles avec votre nouvelle librairie !)

- Il n'est pas autorisé de supprimer une librairie dynamique, les applications l'utilisant ne fonctionneraient plus. Voire à ne pas la déplacer.

 

Principe de nommage des librairies

Les librairies statiques se nomment libXXXXX.a (a pour archive)

Image non trouvée !Sur AIX, les librairies libXXXXX.a peuvent aussi être dynamiques ! Je ne trouve pas cela très propre...mais ce n'est que mon avis.

 

Les librairies dynamiques se nomment libXXXXX.so (so pour shared object)

où XXXXX est le nom de la librairie (par exemple la librairie dynamique jpeg sera le fichier libjpeg.so...)

 

Image non trouvée !Evidemment, je suis contraint de mettre une note par rapport à ce que j'indique ci-dessus sur l'AIX:

Les .so sont valables sur SUN Solaris/OS et le monde Linux. Vous pouvez aussi en trouver parfois sur AIX.

 

Emplacement des librairies

Les librairies sont recherchées dans:

/usr/local/lib/ pour les librairies perso. utilisables par tous.
/usr/lib/ pour les librairies standards.

Il sera possible de stipuler d'autres chemins lors de la compilation.

De même, il existe des solutions pour indiquer d'autres chemins pour les librairies lors de l'exécution (Voir paragraphe "Les chemins des librairies dynamiques" ci-dessous).

 

Création d'une librairie

Développement

Vous développez votre code normalement, puis vous le compilez tout aussi normalement. Vous aurez un fichier include avec les fonctions que vous voulez voir utilisables. Il vous restera à fournir cet include pour une utilisation dans d'autres applications.

Image non trouvée !Rien n'empêche d'utiliser des librairies dans votre librairie...

Les librairies statiques:

Les librairies statiques sont générées à partir des fichiers objets. Il suffit d'utiliser la commande ar pour produire ces librairies. Cette fonction va archiver dans un fichier l'ensemble de vos fichiers .o

ar -rv nom_librairie liste_des_objets

Exemple : ar -rv libXXXXX.a prog1.o prog2.o prog3.o ... progn.o

Il est possible de créer un index des symboles des membres (ou objets) d'une archive. Pour créer l'index des symboles, il suffit d'utiliser 'ranlib nom_archive' (similaire à 'ar -s'). Elle aura l'avantage d'accélérer la compilation.

 

Les librairies dynamiques:

Les librairies dynamiques sont aussi générées à partir des fichiers objets. Mais là, vous utiliserez le compilateur gcc pour générer la librairie .so de la manière suivante:

gcc -o libXXXXX.so -shared prog1.o prog2.o prog3.o ... progn.o

où en passant par le linkeur:

ld -dY -G -o prog1.o prog2.o prog3.o ... progn.o libXXXXX.so

 

Afficher les dépendances

Il est possible d'afficher les dépendances d'un programme avec des librairies dynamiques en utilisant la commande ldd

ldd nomprogramme

 

Utiliser une librairie dynamique dans votre code

Image non trouvée !Ce qui suit est en principe devenu inutile, le but était de charger une librairie en mémoire, puis de déterminer l'adresse de la (des) fonction(s) à appeler. et de libérer la librairie lorsque le code n'en avait plus besoin. Le compilateur fait maintenant tout ce travail automatiquement.

 

Les chemins des librairies dynamiques

Lorsqu'un programme s'exécute et a besoin d'une librairie dynamique, il va chercher cette librairie sur un chemin connu (courant, /lib/usr/lib).

Parfois, les librairies dynamiques ne se trouvent pas dans le bon répertoire, et le programme s'arrête car il ne la trouve pas ! Il faudra alors modifier le cache système lié aux librairies dynamiques pour résoudre ce problème de chemin.

- Vous pourrez modifier la variable d’environnement LD_LIBRARY_PATH afin d’y ajouter le chemin souhaité :
setenv LD_LIBRARY_PATH $LD_LIBRARY_PATH:/ nouveau_chemin
ou export LD_LIBRARY_PATH= $LD_LIBRARY_PATH:/ nouveau_chemin

Par exemple, vous pourrez ajouter votre répertoire si vous créez vos propres librairies (~\lib par exemple si vos librairies se trouvent sous lib à partir de votre répertoire courant).

Image non trouvée !Toujours sur AIX ! la variable se nomme : LIBPATH et non LD_LIBRARY_PATH.

Ne fonctionne pas sous Linux...on utilisera la méthode suivante:

Modification du fichier de paramétrage du cache : /etc/ld.so.conf
Suite à la modification, il faut regénérer le cache: /sbin/ldconfig (Evidemment, il faudra être administrateur !)

 

Compiler des programmes utilisant une librairie

Voir chapitre sur le compilateur GCC/G++ ainsi que sur la commande make.

 


Connaître le contenu d'une librairie statique

La commande ar permet de construire une librairie statique. De même, elle pourra lister son contenu (chaque objet .o):

ar -t nomlibrairie

Vous pourrez aussi lister la table de symboles via la fonction nm:
/usr/bin/nm libXXXXX.a

Dans le résultat:

U : undefined (implémentation externe)
T : implémenté à l’intérieur

De la même manière, si l'index des symboles est défini (voir création d'une librairie), il sera possible de lister les symboles par membre (objet) de l'archive

Pour cela, utilisez 'nm -s' ou 'nm --print-armap' pour lister cet index.

 

Exemple de librairies

Source de la librairieImage non trouvée !L'include utile pour les codes y faisant appelImage non trouvée !un exemple de codeImage non trouvée !

 

 

Bête librairie retournant le résultat d'une addition deux arguments passés en paramètre...

Compilez la librairie (exemple gcc -c add.c -o add.o)

Construisez votre librairie statique (ar -rv libadd.a add.o) ou dynamique (gcc -o libadd.so -shared -o add.o, avec une remarque sur AIX, l'extension de la librairie devant être .a et vous ne pourrez donc pas avoir les deux en même temps !!!)

Image non trouvée !Recopiez votre librairie dynamique (sous /usr/lib en administrateur par exemple) ou configurez comme il faut votre plate-forme pour qu'il trouve votre librairie dynamique...(Je n'ai jamais eu à faire cela sur un AIX, mais à faire sous Linux !)

Compilez l'exemple de test addition (gcc -c testadd.c -o testadd.o)

Puis linkez votre librairie avec votre code de test:

gcc testadd.o -Lchemin_ou_se_trouve_votre_librairie -ladd -o testadd

Testez votre programme.

Image non trouvée !Vous pourrez tester ensuite si votre code est compilé avec une librairie statique, le fait de renommer votre librairie n'empêchera pas le lancement du code, alors que votre code râlera si compilé avec une librairie dynamique...