(Courriels de diversion: <vraisemblance@ordinairement-horripiles.com> <fetu@percussion-vissages.com> <rejeton@contre-visite-insoupconnee.com> <vasodilatatrices@fame-entrelarder.com> <sombraient@remployez-meconnaîtras.com> <guider@muterais-diminuaient.com> <percutants@sevrions-interpellerait.com> <transnationales@avorteras-artistiques.com> <deplafonnais@check-up-ardentes.com> <moyenâgeuse@amadoueras-tampon.com> )
Le 30 Mar, Sebastien Renard écrit : > Enfin, voila ce qui m'amène : je suis en train de compiler un projet > en c++ et j'utilise une librairie (libxerces-c1_1.so) du parseur XML > de Apache. Pour compiler, no pb j'ai inclu la lib dans le makefile, > mais pour l'execution il ne la trouve pas. J'ai mis le fichier dans > /lib, mais j'ai un vague souvenir de "ld" qu'il faut je crois utiliser > pour signaler au systeme la presence de la nouvelle librairie. Quelqu'un > peut-il m'eclairer sur le sujet ? Je ne vais pas répondre directement à ta question. Je vais plutôt tenter d'expliquer comment cela fonctionne, du point de vue de l'utilisation et de la création. D'abord les bibliothèques statiques. Leur nom se termine traditionnellement par '.a'. Ce sont des collections de fichiers objets (.o). On peut extraire ou ajouter des fichiers objets à la bibliothèque avec la commande « ar ». Quand on fait l'édition de liens avec la bibliothèque, les fichiers objets nécessaires pour satisfaire les symboles non encore connus (par exemple printf) sont intégrés dans l'exécutable en cours de création. Tout se passe donc comme si l'on avait cité ces fichiers objets sur la ligne de commande de l'édition de liens. Lors de l'édition de liens, on spécifie la bibliothèque soit par son chemin d'accès (/usr/libi/libtoto.a), soit par -ltoto (auquel cas l'éditeur de liens va la chercher sous le nom de libtoto.a dans divers répertoires). La première méthode permet seule d'avoir des bibliothèques qui soient nommées autrement que libquelquechose. Lors de l'exécution du programme, tout le code est disponible, puisqu'il a été intégré dans le binaire lors de l'édition de liens. C'est du gaspillage, puisque printf.o se retrouve en mémoire autant de fois qu'il y a de programmes actifs qui utilisent printf. C'est pour cela qu'on été inventées les bibliothèques dynamiques (entre autre, car il y a d'autres avantages). Là, le code n'est plus agrégé au binaire du programme : à la place, le binaire se « souvient » qu'il a besoin de tel bout de code (printf), et qu'il peut le trouver dans telle bibliothèque dynamique (libc.so.6). Ces deux informations doivent être enregistrées dans le binaire lors de l'édition de liens. C'est pour cela qu'il faut citer la bibliothèque dynamique sur la ligne de commande de l'édition de liens. Mais la bibliothèque doit aussi être retrouvée lors de l'exécution. Une difficulté supplémentaire vient de ce que le code de la bibliothèque peut évoluer : des bogues sont corrigées, des fonctionnalités ajoutées. Et ce serait con qu'un binaire lié à une version de la bibliothèque ne puisse pas fonctionner si une autre version compatible est seule disponible lors de l'exécution. C'est pour cela que l'éditeur de liens n'enregistre pas le chemin de la bibliothèque (ni même son nom) dans le binaire en cours de création. À la place l'éditeur de liens enregistre le soname de la bibliothèque et une liste de chemins d'accès où chercher lors de l'exécution. Imaginons que je développe une bibliothèque « ation ». Je commence par la version 1.1, mais j'ai la ferme intention de maintenir les versions suivantes compatibles de manière ascendante (c'est-à-dire qu'un programme lié avec la 1.1 fonctionnera avec la 1.2) tant que je ne changerai pas le premier chiffre de la version. Je vais donc créer ma bibliothèque dans un fichier que je nommerai libation.so.1.1. Mais je lui donnerai comme soname « libation.so.1 ». Par exemple avec la ligne de commande : gcc -shared -o libation.so.1.1 -Wl,-h,libation.so.1 -fpic leverLeCoude.c De même pour la 1.2 : gcc -shared -o libation.so.1.2 -Wl,-h,libation.so.1 -fpic leverLeCoude.c De la sorte, je pourrai compiler un programme ainsi : gcc -o 3eme boire.c libation.so.1.1 et, lors de l'exécution, il cherchera le fichier « libation.so.1 ». D'habitude, on préfère citer les bibliothèque par l'option « -l » de l'édition des liens : gcc -o 3eme boire.c -lation L'éditeur de liens va alors chercher le fichier libation.so dans les répertoires cités dans la variable d'environnement LD_LIBRARY_PATH et dans l'option « -L » (plus les répertoires standards /lib et /usr/lib). Mais il n'enregistrera pas dans le binaire le répertoire dans lequel le fichier a été trouvé. À la place, il enregistrera dans le binaire les répertoires cités dans la variable d'environnement LD_RUN_PATH et dans le options « -R » et « -rpath ». C'est là que le binaire ira chercher en priorité sa bibliothèque lors de l'exécution. Mais vous avez remarqué que je n'ai jamais créé de fichier nommé libation.so.1. Comment le programme va-t-il le trouver lors de l'exécution ? Ben, c'est simple : il ne va pas le trouver ; il faut que le fichier existe. C'est un des rôles de ldconfig : il créé un lien symbolique qui renvoie le soname vers le vrai fichier contenant la bibliothèque, celui qui a le plus haut numéro de version s'il y en a plusieurs. Lors de l'exécution, mon programme va tenter de trouver sa bibliothèque dynamique libation.so.1 dans l'ordre : - dans les répertoires cités dans la variable d'environnement LD_LIBRARY_PATH (autre usage de cette variable, donc) ; - dans les répertoires enregistrés dans le binaire lors de l'édition de liens ; - dans les répertoires standards. Mais la plupart des bibliothèques dynamiques seront des bibliothèques contenant des fonctionnalités assez courantes, et ces bibliothèques sont stables : elles ne sont pas souvent changées. C'est donc con de les chercher dans pleins de répertoires : cela ralentit l'exécution. C'est pour cela que l'éditeur de liens dynamique utilise un cache. Le cache est un fichier qui contient une correspondance soname -> fichier pour des répertoires choisis (configurables dans /etc/ld.so.conf). La maintenance de ce cache est l'autre rôle de ldconfig. Résumons : - le chemin de recherche des bibliothèques dynamique n'est pas (forcément) le même lors de l'édition de liens et lors de l'exécution du binaire résultant ; - un fichier libation.so est normalement un lien vers la vraie bibliothèque ; ce lien n'est utilisé que lors de l'édition de liens avec l'option « -l » ; - un fichier libation.x est normalement un lien vers la bibliothèque libation.x.y [*] avec y le plus élevé ; ce lien n'est utilisé que lors de l'exécution. À ma connaissance, tous les systèmes ELF fonctionnent ainsi (du moins, j'en suis sûr pour Sun Solaris). [*] Il peut arriver qu'il y ait plus de nombres dans le nom du fichier. -- Marc Thirion | Toulouse, France Un Travail pour Chacun : http://www.multimania.com/untravailchacun/ Marc.Thirion@ISOscope.com : http://www.ISOscope.com/Pérennité des logiciels et des systèmes --------------------------------------------------------------------- Aide sur la liste: <URL:mailto:linux-31-help@savage.iut-blagnac.fr>Le CULTe sur le web: <URL:http://savage.iut-blagnac.fr/>