web-dev-qa-db-fra.com

Vous ne trouvez pas .so dans le même répertoire que l'exécutable?

J'ai un exécutable qui doit être lié à libtest.so dynamiquement, donc je les mets dans le même répertoire, puis:

cd path_to_dir
./binary

Mais j'ai ceci:

error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

Comment peut-il être incapable de trouver libtest.so qui se trouve déjà dans le même répertoire que l'exécutable lui-même?

47
linuxer

Le chargeur ne vérifie jamais le répertoire courant pour les objets partagés à moins qu'il ne soit explicitement dirigé vers via $LD_LIBRARY_PATH. Consultez la page de manuel ld.so(8) pour plus de détails.

29

Bien que vous puissiez définir LD_LIBRARY_PATH pour que l'éditeur de liens dynamique sache où chercher, il existe de meilleures options. Vous pouvez placer votre bibliothèque partagée dans l'un des emplacements standard, voir /etc/ld.so.conf (sous Linux) et /usr/bin/crle (sur Solaris) pour la liste de ces lieux

Tu peux passer -R <path> à l'éditeur de liens lors de la construction de votre binaire, ce qui ajoutera <path> à la liste des répertoires analysés pour votre bibliothèque partagée. Voici un exemple. Tout d'abord, montrant le problème:

libtest.h:

void hello_world(void);

libtest.c:

#include <stdio.h>
void hello_world(void) {
  printf("Hello world, I'm a library!\n");
}

bonjour c:

#include "libtest.h"
int main(int argc, char **argv) {
  hello_world();
}

Makefile (des onglets doivent être utilisés):

all: hello
hello: libtest.so.0
%.o: %.c
        $(CC) $(CFLAGS) -fPIC -c -o $@ $<
libtest.so.0.0.1: libtest.o
        $(CC) -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
libtest.so.0: libtest.so.0.0.1
        ln -s $< $@
clean:
        rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0

Lançons-le:

$ make
cc  -fPIC -c -o libtest.o libtest.c
cc -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
ln -s libtest.so.0.0.1 libtest.so.0
cc     hello.c libtest.so.0   -o hello
$ ./hello 
./hello: error while loading shared libraries: libtest.so.0: cannot open shared object file: No such file or directory

Comment le réparer? Ajouter -R <path> aux drapeaux de l'éditeur de liens (ici, en définissant LDFLAGS).

$ make clean
(...)
$ make LDFLAGS="-Wl,-R -Wl,/home/maciej/src/tmp"
(...)
cc   -Wl,-R -Wl,/home/maciej/src/tmp  hello.c libtest.so.0   -o hello
$ ./hello 
Hello world, I'm a library!

En regardant le binaire, vous pouvez voir qu'il a besoin de libtest.so.0:

$ objdump -p hello | grep NEEDED
  NEEDED               libtest.so.0
  NEEDED               libc.so.6

Le binaire recherchera ses bibliothèques, en dehors des emplacements standard, dans le répertoire spécifié:

$ objdump -p hello | grep RPATH
  RPATH                /home/maciej/src/tmp

Si vous voulez que le binaire regarde dans le répertoire courant, vous pouvez définir le RPATH sur $Origin. C'est un peu délicat, car vous devez vous assurer que le signe dollar n'est pas interprété par make. Voici une façon de procéder:

$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$Origin'"
$ objdump -p hello | grep RPATH
  RPATH                $Origin
$ ./hello 
Hello world, I'm a library!
59
automatthias

Pour charger les objets partagés à partir du même répertoire que votre exécutable, exécutez simplement:

$ LD_LIBRARY_PATH=. ./binary

Remarque: Cela ne modifiera pas la variable LD_LIBRARY_PATH de votre système. Le changement n'affecte que cela, et seulement cela, l'exécution de votre programme.

18
SwanS

Pour tous ceux qui luttent encore sans réponse, j'en ai trouvé un moi-même avec la suggestion suivante:

Vous pouvez essayer de mettre à jour le ld.so.cache en utilisant: Sudo ldconfig -v

A travaillé pour moi.

4
Ian Frisbie

Pour toute personne utilisant CMake pour sa construction, vous pouvez définir le CMAKE_EXE_LINKER_FLAGS aux éléments suivants:

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$Origin'")

Cela propage correctement les indicateurs de l'éditeur de liens pour tous les types de build (par exemple, Debug, Release, etc ...) pour rechercher d'abord les fichiers .so dans le répertoire de travail actuel.

4
Michael Goldshteyn

L'éditeur de liens dynamique décidera où chercher les bibliothèques. Dans le cas de Linux, l'éditeur de liens dynamique est généralement GNU ld.so (ou une alternative qui se comportera généralement de manière identique pour des raisons de compatibilité.].

Pour citer des extraits de Wikipedia:

L'éditeur de liens dynamique de la bibliothèque GNU C recherche les bibliothèques partagées aux emplacements suivants:

  1. Les chemins (séparés par deux-points) dans le DT_RPATH attribut de section dynamique du binaire s'il est présent et le DT_RUNPATH l'attribut n'existe pas.
  2. Les chemins (séparés par deux points) dans la variable d'environnement LD_LIBRARY_PATH, sauf si l'exécutable est un binaire setuid/setgid, auquel cas il est ignoré. LD_LIBRARY_PATH peut être substitué en appelant l'éditeur de liens dynamique avec l'option --library-path (par exemple /lib/ld-linux.so.2 --library-path $ HOME/mylibs myprogram).
  3. Les chemins (séparés par deux-points) dans le DT_RUNPATH attribut de section dynamique du binaire s'il est présent.
  4. Recherche basée sur le fichier de cache ldconfig (souvent situé à /etc/ld.so.cache) qui contient une liste compilée des bibliothèques candidates précédemment trouvées dans le chemin de la bibliothèque augmentée (définie par /etc/ld.so.conf). Si, cependant, le binaire était lié au -z nodefaultlib option de l'éditeur de liens, les bibliothèques dans les chemins de bibliothèque par défaut sont ignorées.
  5. Dans le chemin d'accès par défaut approuvé /lib, et alors /usr/lib. Si le binaire a été lié avec l'option de l'éditeur de liens -z nodefaultlib, cette étape est ignorée.

Source: https://en.wikipedia.org/wiki/Rpath

0
Mecki