78 votes

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

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

cd path_to_dir
./binary

Mais j'ai eu ça :

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 ?

80voto

Wilhelm Points 2542

Bien que vous puissiez définir LD_LIBRARY_PATH pour que l'éditeur de liens dynamiques 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 endroits

Vous pouvez passer -R <path> à l'éditeur de liens lors de la construction de votre binaire, qui ajoutera <path> à la liste des répertoires analysés pour votre bibliothèque partagée. Voici un exemple. D'abord, montrer 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");
}

hello.c :

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

Makefile (les tabulations doivent être utilisées) :

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

Faisons-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 le paramètre 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 cherchera ses bibliothèques, en dehors des emplacements standards, dans le répertoire spécifié :

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

Si vous voulez que le binaire cherche dans le répertoire actuel, vous pouvez définir le RPATH comme suit $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 le faire :

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

47voto

David Points 344

Le chargeur ne vérifie jamais la présence d'objets partagés dans le répertoire courant, à moins qu'il n'y soit explicitement invité par le biais de la commande $LD_LIBRARY_PATH . Voir le ld.so(8) pour plus de détails.

36voto

SwanS Points 391

Pour charger les objets partagés à partir du même répertoire que votre exécutable, il suffit d'exécuter :

$ LD_LIBRARY_PATH=. ./binary

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

15voto

Paul Points 56

Pour toute personne utilisant CMake pour leur construction, vous pouvez définir le CMAKE_EXE_LINKER_FLAGS à ce qui suit :

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

Cela propagera correctement les drapeaux de l'éditeur de liens pour tous les types de construction (par exemple, Debug, Release, etc...) pour rechercher les fichiers .so dans le répertoire de travail actuel en premier.

5voto

Ian Frisbie Points 71

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

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

Ça a marché pour moi.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X