Le processus de liaison exposé – Bibliothèques statiques vs dynamiques
Création d’une bibliothèque statique et dynamique
Pour une bibliothèque statique, le code objet des fichiers binaires (extension .o
) est combiné dans un seul fichier d’archive avec une extension .a
. Cette archive est similaire à une boîte à outils qui contient tous les outils susceptibles d’être utilisés dans les programmes qui appellent cette bibliothèque lors de la liaison. Les outils sont insérés aux endroits où ils sont nécessaires. Dans l’image ci-dessous, j’ai une série de fichiers .c
.
Puisqu’une bibliothèque est une archive de code objet, je dois convertir tous ces fichiers .c
en fichiers .o
en utilisant la commande suivante:
gcc -Wall -Wextra -Werror -pedantic -c *.c
L’option -c
arrête le processus de compilation juste avant la liaison après que les fichiers de code objet aient été générés. J’ai maintenant tous les fichiers de code objet:
Si je lance la commande ar -rc libholbertonschool.a *.o
, je peux archiver ces fichiers dans un seul fichier de bibliothèque .a
. La commande ar
sert à l’archivage, l’option -r
sert à déplacer les membres qui ont l’extension .o
, et l’option -c
sert à créer l’archive si elle n’existe pas. Un fichier de bibliothèque commence par un préfixe lib
et a une extension .a
. L’étape finale qui est nécessaire sur certains systèmes est d’indexer le contenu de l’archive pour accélérer la liaison. Ceci peut être fait avec ranlib libholbertonschool.a
. J’ai maintenant une bibliothèque qui contient le code objet pour toutes les fonctions de l’image ci-dessus.
Utilisation de la bibliothèque statique
Pour utiliser cette bibliothèque avec un certain fichier de test, je dois compiler le fichier de test avec la bibliothèque en utilisant l’une ou l’autre des deux commandes suivantes :
gcc test.c ./libholbertonschool.a -o exename
gcc test.c -L. -lholbertonschool -o exename
Les deux font la même chose, mais la seconde est légèrement plus cryptique. L’option -L.
recherche les bibliothèques dans le répertoire courant et l’option -l
qui est connectée à holbertonschool
recherche le fichier de bibliothèque implicitement où un préfixe lib
et un suffixe .a
sont supposés. Sans compiler avec un fichier de bibliothèque, gcc
lancera une erreur puisque les fonctions qu’il essaie de lier ne sont pas fournies. En fournissant une bibliothèque dans la compilation, le compilateur peut maintenant rechercher dans la bibliothèque les fonctions dont il a besoin et les insérer là où elles sont nécessaires.
Bibliothèques dynamiques
Créer des bibliothèques dynamiques est légèrement différent des bibliothèques statiques, mais les concepts sont généralement les mêmes. J’ai le même nombre de fichiers .c
et le fichier d’en-tête qui définit leurs prototypes dans un fichier appelé lists.h
.
Pour créer la bibliothèque dynamique, qui a un .so
(signifiant objet partagé), la commande de compilation suivante peut être entrée:
gcc -fPIC -Wall -Werror -Wextra -pedantic *.c -shared -o libholberton.so
Le drapeau -fPIC
représente le code indépendant de la position qui est requis pour la liaison dynamique. Sa signification est exactement ce qu’elle semble être – puisque les bibliothèques liées dynamiquement peuvent être stockées n’importe où dans la mémoire où elles conviennent, ce drapeau permet au fichier de la bibliothèque d’être utilisé indépendamment de l’endroit où il est stocké.
Le drapeau -shared
permet de créer une archive partagée et l’option -o
nous permet de renommer le fichier de sortie en libholberton.so
.
Après avoir exécuté cette commande, j’ai maintenant une bibliothèque partagée !
La ligne libholberton.so => not found
m’indique que la dépendance de la bibliothèque dynamique que je viens de créer n’est pas remplie. Pour corriger cela, il faut comprendre la variable d’environnement $LD_LIBRARY_PATH
. Sous Linux, cette variable est une liste, séparée par deux points, de répertoires dans lesquels le système cherche des fichiers de bibliothèque. Dans l’image ci-dessus, vous pouvez voir que l’écho de cette variable à l’état actuel montre qu’elle est vide et donc, ma tentative d’exécuter le programme (len
) ne fonctionne pas car la bibliothèque partagée ne peut pas être chargée.
Mon répertoire courant ressemble à ceci:
Comme vous pouvez le voir, le fichier de la bibliothèque est situé dans le même répertoire que mon fichier principal et mon fichier d’en-tête (répertoire de travail courant). Observez l’image suivante:
La commande export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
met à jour la variable d’environnement $LD_LIBRARY_PATH
avec un .:
qui indique que le système doit rechercher les bibliothèques dans le répertoire de travail courant. La commande export
rend ce changement global afin que tout shell puisse accéder à la même valeur. Ainsi, lorsque je fais écho à la variable, je vois mes mises à jour. En exécutant ldd len
à nouveau, je vois que libholberton.so
est à l’emplacement d’adresse 0x00007fb9216b9000
qui est probablement son emplacement dans le répertoire de travail actuel en mémoire. Ainsi, la dépendance de l’exécutable à la bibliothèque partagée est maintenant remplie et le programme retourne 9
qui est la longueur du mot « Holberton
« .