Soluzione 1:
Mentre puoi impostare LD_LIBRARY_PATH per far sapere al linker dinamico dove cercare, ci sono opzioni migliori. Puoi mettere la tua libreria condivisa in uno dei posti standard, vedi /etc/ld.so.conf
(su Linux) e /usr/bin/crle
(su Solaris) per l'elenco di questi luoghi
Puoi superare -R <path>
al linker durante la creazione del binario, che aggiungerà <path>
all'elenco delle directory scansionate per la tua libreria condivisa. Ecco un esempio. Innanzitutto, mostrando il problema:
libtest.h:
void hello_world(void);
libtest.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
ciao.c:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Makefile (devono essere utilizzate le schede):
all: hello
hello: libtest.so.0
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o [email protected] $<
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 $< [email protected]
clean:
rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0
Eseguiamolo:
$ 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
Come sistemarlo? Aggiungi -R <path>
ai flag del linker (qui, impostando 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!
Guardando il binario, puoi vedere che ha bisogno di libtest.so.0
:
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
Il binario cercherà le sue librerie, a parte le posizioni standard, nella directory specificata:
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
Se vuoi che il binario cerchi nella directory corrente, puoi impostare RPATH su $ORIGIN
. Questo è un po' complicato, perché devi assicurarti che il simbolo del dollaro non sia interpretato da make. Ecco un modo per farlo:
$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
RPATH $ORIGIN
$ ./hello
Hello world, I'm a library!
Soluzione 2:
Il caricatore non controlla mai la directory corrente per gli oggetti condivisi a meno che non sia esplicitamente diretto tramite $LD_LIBRARY_PATH
. Vedi il ld.so(8)
pagina man per maggiori dettagli.
Soluzione 3:
Per caricare gli oggetti condivisi dalla stessa directory del tuo eseguibile, esegui semplicemente:
$ LD_LIBRARY_PATH=. ./binary
Nota:non modificherà la variabile LD_LIBRARY_PATH del tuo sistema. La modifica riguarda solo questa, e solo questa, esecuzione del tuo programma.
Soluzione 4:
Per chiunque utilizzi CMake per la propria build, puoi impostare CMAKE_EXE_LINKER_FLAGS
al seguente:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
Questo propagherà correttamente i flag del linker per tutti i tipi di build (ad es. Debug, Release, ecc...) per cercare prima i file .so nella directory di lavoro corrente.
Soluzione 5:
Per chiunque stia ancora lottando senza una risposta, ne ho trovata una io stesso con il seguente suggerimento:
Potresti provare ad aggiornare ld.so.cache usando:sudo ldconfig -v
Ha funzionato per me.