Não consegue encontrar .so no mesmo diretório que o executável?

36

Eu tenho um executável que precisa vincular com libtest.so dinamicamente, então eu os coloco no mesmo diretório, então:

cd path_to_dir
./binary

Mas entendi:

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

Como pode ser impossível encontrar o libtest.so , que já está no mesmo diretório do próprio executável?

    
por linuxer 10.06.2011 / 10:54

5 respostas

22

O carregador nunca verifica o diretório atual em busca de objetos compartilhados, a menos que seja explicitamente direcionado para via $LD_LIBRARY_PATH . Veja a página ld.so(8) man para mais detalhes.

    
por 10.06.2011 / 10:56
53

Embora você possa definir LD_LIBRARY_PATH para permitir que o vinculador dinâmico saiba onde procurar, existem opções melhores. Você pode colocar sua biblioteca compartilhada em um dos locais padrão, veja /etc/ld.so.conf (no Linux) e /usr/bin/crle (no Solaris) para a lista desses locais

Você pode transmitir -R <path> para o vinculador ao criar seu binário, o que adicionará <path> à lista de diretórios verificados para sua biblioteca compartilhada. Aqui está um exemplo. Primeiro, mostrando o problema:

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 (guias devem ser usadas):

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

Vamos executar:

$ 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

Como consertar isso? Adicione -R <path> aos sinalizadores do vinculador (aqui, definindo 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!

Olhando para o binário, você pode ver que ele precisa de libtest.so.0 :

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

O binário irá procurar por suas bibliotecas, além dos locais padrão, no diretório especificado:

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

Se você deseja que o binário seja exibido no diretório atual, você pode definir o RPATH como $ORIGIN . Isso é um pouco complicado, porque você precisa ter certeza de que o cifrão não seja interpretado por make. Aqui está uma maneira de fazer isso:

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

Para carregar os objetos compartilhados no mesmo diretório do seu executável, basta executar:

$ LD_LIBRARY_PATH=. ./binary

Nota: Não modificará a variável LD_LIBRARY_PATH do seu sistema. A alteração afeta apenas isso, e somente isso, a execução do seu programa.

    
por 18.06.2015 / 11:14
3

Para quem ainda luta sem uma resposta, encontrei uma com a seguinte sugestão:

Você pode tentar atualizar o ld.so.cache usando: sudo ldconfig -v

Trabalhei para mim.

    
por 29.08.2015 / 02:06
0

Para qualquer pessoa que use o CMake para sua compilação, você pode definir o CMAKE_EXE_LINKER_FLAGS para o seguinte:

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

Isso propagará corretamente os sinalizadores do vinculador para todos os tipos de compilação (por exemplo, Debug, Release, etc ...) para procurar arquivos .so no diretório de trabalho atual primeiro.

    
por 13.08.2018 / 01:24