Comment spécifiez-vous l'emplacement des bibliothèques dans un binaire? (Linux)

34

Pour cette question, je vais utiliser un exemple spécifique, mais cela se généralise à peu près à tout binaire sous Linux qui ne semble pas trouver ses bibliothèques dépendantes. Donc, j'ai un programme qui ne fonctionnera pas à cause des bibliothèques manquantes:

./cart5: error while loading shared libraries: libcorona-1.0.2.so: cannot open shared object file: No such file or directory

ldd fait la lumière sur la question:

linux-vdso.so.1 =>  (0x00007fff18b01000)
libcorona-1.0.2.so => not found
libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/libstdc++.so.6 (0x00007f0975830000)
libm.so.6 => /lib/libm.so.6 (0x00007f09755af000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f0975399000)
libc.so.6 => /lib/libc.so.6 (0x00007f0975040000)
libz.so.1 => /lib/libz.so.1 (0x00007f0974e2b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0975b36000)

Cependant, corona est installé:

oliver@human$ find / -name libcorona-1.0.2.so 2> /dev/null

/usr/local/lib64/libcorona-1.0.2.so
/home/oliver/installed/corona-1.0.2/src/.libs/libcorona-1.0.2.so

Comment dire au binaire où chercher la bibliothèque "manquante"?

Mala
la source

Réponses:

43

Pour une fois, définissez la variable LD_LIBRARY_PATHsur une liste de répertoires séparés par deux-points pour la recherche. Ceci est similaire aux PATHexécutables, sauf que les répertoires système standard sont également recherchés après ceux spécifiés dans l'environnement.

LD_LIBRARY_PATH=/usr/local/lib64 ./cart5

Si vous avez un programme qui conserve les bibliothèques dans un emplacement non standard et n'est pas en mesure de les trouver par lui-même, vous pouvez écrire un script wrapper:

#!/bin/sh
if [ -n "$LD_LIBRARY_PATH" ]; then
  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib64
else
  LD_LIBRARY_PATH=/usr/local/lib64
fi
export LD_LIBRARY_PATH
exec /path/to/cart5 "$@"

La liste des répertoires système standard est conservée /etc/ld.so.conf. Les systèmes récents permettent à ce fichier d'inclure d'autres fichiers; si le vôtre contient quelque chose comme include /etc/ld.so.conf.d/*.conf, créez un nouveau fichier appelé /etc/ld.so.conf.d/mala.confcontenant les répertoires que vous souhaitez ajouter. Après avoir modifié /etc/ld.so.confou un fichier inclus, exécutez /sbin/ldconfigpour que vos modifications prennent effet (cela met à jour un cache).

( LD_LIBRARY_PATHs'applique également à de nombreux autres unités, y compris FreeBSD, NetBSD, OpenBSD, Solaris et Tru64. HP-UX a SHLIB_PATHet Mac OS X a DYLD_LIBRARY_PATH. /etc/ld.so.confa des analogues sur la plupart des unités mais l'emplacement et la syntaxe diffèrent plus largement.)

Gilles 'SO- arrête d'être méchant'
la source
1
Fantastique, merci beaucoup. Je n'avais aucune idée de /etc/ld.so.conf, et cela me sera très utile à l'avenir.
Mala
15

Si vous souhaitez éviter LD_LIBRARY_PATH, vous pouvez également le faire, lors de la liaison:

gcc -o exename -L/path/to/dynamiclib/ -lnameofLib \
    -Wl,-R/path/to/dynamiclib/ sourceCode1.c ...

-Wl, ... est utilisé pour passer des commandes supplémentaires à l'éditeur de liens, et dans ce cas, avec -R, vous dites à l'éditeur de liens de stocker ce chemin comme "chemin de recherche par défaut" pour le .so.

Je note de nombreux petits conseils comme celui-ci sur mon site:

https://www.thanassis.space/tricks.html

ttsiodras
la source
Mais si la bibliothèque en question elle-même a des bibliothèques partagées à rechercher, le rpath stocké dans le binaire n'est pas appliqué récursivement aux recherches de sous-bibliothèque. Je n'ai trouvé aucun moyen de contourner cela autre que de définir LD_LIBRARY_PATH dans l'environnement, qui est ensuite appliqué aux recherches récursives ...
Ethan
@Ethan: Vrai. Mais ce qui est également vrai, c'est que les scénarios habituels où vous voulez "empaqueter" des bibliothèques partagées pour certains fichiers binaires, sont ceux où vous les avez tous placés ensemble; Par exemple, vous /opt/mypackage/bin/someBinaryaurez besoin de bibliothèques dans lesquelles vous stockez /opt/mypackage/lib/. Presque tous les logiciels propriétaires installés sous / opt suivent cette règle - ce qui signifie que la manière indiquée ci-dessus couvrira toutes ces installations. Ils ajouteront ensuite généralement un lien symbolique sous / usr / bin qui pointe vers le binaire sous / opt - sachant que le "chemin de recherche par défaut" trouvera les .sos sous le /opt/.../libdossier approprié .
ttsiodras
oui, dans mon cas, je voulais tester un paquet en établissant une liaison avec son répertoire de construction plutôt que de l'installer ... (mais le paquet avait plusieurs .so internes avec quelques interdépendances ... diverses solutions de contournement mais juste ennuyeuses)
Ethan
0

Cela indique que libcorona n'est pas installé dans le bon chemin. Déplacez le répertoire libcorona dans le bon chemin, le problème sera résolu.

Rathi
la source
Comment est-ce mieux que d'autres réponses?
Toto
@Toto contrairement aux autres réponses, vous installez essentiellement manuellement les fichiers ... Bien que cela ne signifie pas exactement que cette réponse est meilleure, mais c'est une option qui devrait être envisagée (les gens le font également sous Windows en copiant les bibliothèques dans system32 / sysWOW64 lorsque leurs applications ne les trouvent pas), pas que ce soit recommandé, car il est fortement déconseillé.
Tcll