Erro ao carregar bibliotecas compartilhadas

5

Minha árvore de projetos é parecida com isso:

src/
include/
Makefile
lib/
   lib/3rdparylib/

Eu não codifiquei 3rdpartylib , mas decidi incorporar seu código-fonte na minha embalagem do projeto. Eu compilo o software seguindo os seguintes passos:

$ cd lib/3rdpartylib/
$ make
$ ln -s 3rdpartylib.so.0 3rdpartylib.so

Depois eu compilo cada um dos meus arquivos fonte como este:

$ gcc -c src/file.c -I include -o file.o -l 3rdparylib -L lib/3rdpartylib -I lib/3rdpartylib/include

Então eu linko:

$ gcc file1.o file2.o -l3rdpartylib -L lib/3rdpartylib -o myapp

Quando estou na minha máquina principal, funciona perfeitamente. Hoje tentei lançá-lo em outra máquina. É compilado e vinculado sem nenhum problema. No entanto, quando tentei iniciar o aplicativo, recebi a seguinte mensagem de erro.

./ myapp: erro ao carregar bibliotecas compartilhadas: 3rdpartylib.so.0: não é possível abrir o arquivo de objeto compartilhado: Nenhum arquivo ou diretório desse tipo

Eu tentei fazer o seguinte:

export LD_LIBRARY_PATH=/path/to/3rdpartylib.so

Parece funcionar. Mas eu entendo que usar LD_LIBRARY_PATH é uma prática ruim. Incomoda-me ter esta variável configurada toda vez que eu quero executar meu aplicativo.

O que estou perdendo? Por que funciona na minha máquina principal (onde LD_LIBRARY_PATH não está definido para nada) e não na outra máquina? Importa que a outra máquina seja virtual?

Se for de alguma ajuda, minha máquina principal é uma caixa Debian, e minha "nova" máquina é um Sabayon (Gentoo), rodando no Virtualbox.

    
por rahmu 23.11.2011 / 20:53

4 respostas

4

O que importa é a distribuição Linux que cada máquina usa, porque eles manipulam caminhos de bibliotecas de maneira diferente. Na máquina Gentoo (Sabayon), se você quiser que uma biblioteca de terceiros seja utilizável em todo o sistema, você deve:

  • Crie um arquivo em /etc/env.d/ que conterá a configuração adicional do ambiente. Os arquivos são nomeados usando o esquema [0-9][0-9]somename - os dois dígitos iniciais decidem a ordem em que são usados. Uma boa prática requer que suas configurações personalizadas sejam adicionadas (próximo) último , então 99 é um começo adequado, contanto que funcione. Chegar ao ponto: crie um arquivo com o nome

    /etc/env.d/99mythirdpartylib
    

    contendo

    LDPATH=/path/to/your/library
    
  • Para ativar as alterações sem reinicializar, execute como root:

    env-update && source /etc/profile
    

    (que atualizará o ambiente, assim como executará ldconfig ).

Referência , se você quiser um.

    
por 23.11.2011 / 21:32
1

Se você não quiser definir um caminho de pesquisa de biblioteca global para todo o seu sistema com a abordagem /etc/env.d , você poderá:

Basta definir o LD_LIBRARY_PATH para o PATH da sua biblioteca (você o definiu para a biblioteca em si, isso não funcionará), o mesmo que você definiu com o parâmetro -L para gcc eg

export LD_LIBRARY_PATH="$PROJ/lib/3rdpartylib/:$LD_LIBRARY_PATH"

(a última parte é para preservar a variável se já estiver definida, o que não deveria ser normalmente). Isso só funcionará no seu shell atual e você terá que configurá-lo novamente toda vez.

Ou você pode vincular usando um caminho de pesquisa de biblioteca 'estático' como este:

gcc file1.o file2.o -L./lib/3rdpartylib -Wl,-rpath=./lib/3rdpartylib  -l3rdpartylib  -o myapp

-Wl especifica os argumentos da linha de comando que não serão processados pelo gcc, mas serão passados para o vinculador. Como o caminho de pesquisa da biblioteca será escrito no binário, isso funcionará mesmo em máquinas diferentes (desde que a biblioteca exista)

PS: Já que você está falando sobre o caso em que está desenvolvendo um projeto, acho que esse modo temporário é mais apropriado do que colocá-lo em arquivos de configuração de todo o sistema.

    
por 26.03.2012 / 20:49
0

A linha:

$ gcc file1.o file2.o -l3rdpartylib -L lib/3rdpartylib -o myapp

procura por um arquivo chamado lib3rdpartylib.so no caminho da sua biblioteca, que nem inclui lib/3rdpartylib ! Se você olhar para a página do manual gcc, ele afirma que ao especificar um caminho de biblioteca com -L , ele deve vir antes dos -l flags ou não será pesquisado. Realmente, a solução mais simples é apenas vincular a biblioteca em si:

$ gcc file1.o file2.o lib/3rdpartylib/3rdpartylib.so -o myapp

Dessa forma, a biblioteca será pesquisada nos caminhos da biblioteca e carregada dinamicamente quando myapp for executado.

Se você quiser verificá-lo, basta fazer um strace -eopen ./myapp assim que estiver instalado e verificar de onde ele tenta carregar a biblioteca.

    
por 24.11.2011 / 20:18
-1

Você precisa dizer ao seu sistema onde procurar por bibliotecas. Este trabalho é feito por /etc/ld.so.cache . Você pode adicionar bibliotecas ou diretórios inteiros em /etc/ld.so.conf .

Você pode reconstruir o cache fazendo:

# /sbin/ldconfig -v
    
por 24.11.2011 / 17:44