Solución 1:
Si bien puede configurar LD_LIBRARY_PATH para que el vinculador dinámico sepa dónde buscar, hay mejores opciones. Puede poner su biblioteca compartida en uno de los lugares estándar, consulte /etc/ld.so.conf
(en Linux) y /usr/bin/crle
(en Solaris) para obtener la lista de estos lugares
Puedes pasar -R <path>
al enlazador al construir su binario, que agregará <path>
a la lista de directorios escaneados para su biblioteca compartida. Aquí hay un ejemplo. Primero, mostrando el problema:
pruebalib.h:
void hello_world(void);
pruebalib.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
hola.c:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Makefile (se deben usar tabuladores):
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
Ejecutémoslo:
$ 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 arreglarlo? Agregar -R <path>
a las banderas del enlazador (aquí, configurando 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!
Mirando el binario, puede ver que necesita libtest.so.0
:
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
El binario buscará sus bibliotecas, además de los lugares estándar, en el directorio especificado:
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
Si desea que el binario busque en el directorio actual, puede configurar RPATH en $ORIGIN
. Esto es un poco complicado, porque debe asegurarse de que make no interprete el signo de dólar. Esta es una forma de hacerlo:
$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
RPATH $ORIGIN
$ ./hello
Hello world, I'm a library!
Solución 2:
El cargador nunca verifica el directorio actual en busca de objetos compartidos a menos que se le dirija explícitamente a través de $LD_LIBRARY_PATH
. Ver el ld.so(8)
página man para más detalles.
Solución 3:
Para cargar los objetos compartidos desde el mismo directorio que su ejecutable, simplemente ejecute:
$ LD_LIBRARY_PATH=. ./binary
Nota:No modificará la variable LD_LIBRARY_PATH de su sistema. El cambio solo afecta a esta, y solo esta, ejecución de su programa.
Solución 4:
Para cualquiera que use CMake para su compilación, puede configurar el CMAKE_EXE_LINKER_FLAGS
a lo siguiente:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
Esto propagará correctamente las banderas del enlazador para todos los tipos de compilación (por ejemplo, depuración, lanzamiento, etc.) para buscar primero los archivos .so en el directorio de trabajo actual.
Solución 5:
Para cualquiera que todavía lucha sin una respuesta, encontré una yo mismo con la siguiente sugerencia:
Puede intentar actualizar ld.so.cache usando:sudo ldconfig -v
Funcionó para mí.