2010-04-28 9 views
66

Estoy compilando un programa de C++ usando g++ y ld. Tengo una biblioteca .so que quiero que se use durante la vinculación. Sin embargo, existe una biblioteca del mismo nombre en /usr/local/lib, y ld está eligiendo esa biblioteca sobre la que especifico directamente. ¿Cómo puedo arreglar esto?¿Cómo especificar la preferencia de la ruta de la biblioteca?

Para los ejemplos a continuación, mi archivo de biblioteca es /my/dir/libfoo.so.0. Cosas que he intentado que no funcionan:

  • mi comando g ++ es g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • añadiendo /my/dir al principio o al final de mi $PATH en` variables
  • añadiendo /my/dir/libfoo.so.0 como argumento para g ++
+0

¿Qué otros archivos 'libfoo. *' Existen y dónde - '.so' sin los' .0', '.a', etc etc.? –

Respuesta

69

Añada la ruta a donde su nueva biblioteca es LD_LIBRARY_PATH (tiene nombre ligeramente diferente en Mac ...)

Su solución debería funcionar con el uso de las opciones -L/my/dir -lfoo, en tiempo de ejecución use LD_LIBRARY_PATH para apuntar a la ubicación de su biblioteca.

O

Utilice la opción rpath a través de gcc para ligador - ruta de búsqueda de biblioteca de tiempo de ejecución, se utilizará en lugar de buscar en el directorio estándar (opción de gcc):

-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH) 

Esto es bueno para una solución temporal. El vinculador busca primero LD_LIBRARY_PATH para las bibliotecas antes de buscar directorios estándar.

Si no desea actualizar permanentemente LD_LIBRARY_PATH puede hacerlo sobre la marcha de la línea de comandos:

LD_LIBRARY_PATH=/some/custom/dir ./fooo 

puede comprobar cuáles bibliotecas enlazador sabe sobre el uso (ejemplo):

/sbin/ldconfig -p | grep libpthread 
     libpthread.so.0 (libc6, OS ABI: Linux 2.6.4) => /lib/libpthread.so.0 

Y se puede comprobar qué biblioteca de la aplicación está utilizando:

ldd foo 
     linux-gate.so.1 => (0xffffe000) 
     libpthread.so.0 => /lib/libpthread.so.0 (0xb7f9e000) 
     libxml2.so.2 => /usr/lib/libxml2.so.2 (0xb7e6e000) 
     librt.so.1 => /lib/librt.so.1 (0xb7e65000) 
     libm.so.6 => /lib/libm.so.6 (0xb7d5b000) 
     libc.so.6 => /lib/libc.so.6 (0xb7c2e000) 
     /lib/ld-linux.so.2 (0xb7fc7000) 
     libdl.so.2 => /lib/libdl.so.2 (0xb7c2a000) 
     libz.so.1 => /lib/libz.so.1 (0xb7c18000) 
+10

'LD_LIBRARY_PATH' se busca en el tiempo de ejecución, en el momento de la compilación que desea establecer' LIBRARY_PATH'. Consulte https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html –

+1

Si su biblioteca es completamente diferente de la biblioteca del sistema, es decir, es la que debe usar siempre, utilice la solución rpath. LD_LIBRARY_PATH es un truco para las pruebas y no debería ser necesario para hacer que un ejecutable funcione correctamente. – user2746401

+0

es DYLD_LIBRARY_PATH para Mac – cbinder

16

Especificación de la absoluta ruta a la biblioteca debería funcionar bien:

g++ /my/dir/libfoo.so.0 ... 

¿Se acordó de quitar el -lfoo una vez que ha añadido la ruta absoluta?

+1

Esta solución también funcionó bien para mí, tratando de vincularla con una versión de Qt5 que no sea el paquete de desarrollo de distribución. Gracias. – wump

+0

¿Cómo hacer que esto funcione para símbolos versionados '@'? Ejemplo mínimo: https://github.com/cirosantilli/cpp-cheat/blob/0b4b1bdeed693d16129b282ce0c8145499bf34f6/shared-library/symbol-version/Makefile#L13 –

8

Como alternativa, puede utilizar las variables de entorno LIBRARY_PATH y CPLUS_INCLUDE_PATH, que indican respectivamente dónde buscar para las bibliotecas y dónde buscar los encabezados (CPATH también hará el trabajo), sin especificar el -L y opciones -I .

Editar: CPATH incluye cabecera con -I y CPLUS_INCLUDE_PATH con -isystem.

+0

¿Podría agregar ejemplos de uso? –

+0

'export LIBRARY_PATH =/ruta/a/lib' en la misma sesión de consola donde está compilando –

0

Si se usa uno para trabajar con DLL en Windows y me gustaría omitir .so números de versión en linux/QT, agregar "CONFIG + = plugin" eliminará los números de versión.Usar la ruta absoluta a .so, dándole al enlazador funciona bien, como mencionó el Sr. Klatchko.

10

Esta es una vieja pregunta, pero nadie parece haber mencionado esto.

Estabas teniendo suerte de que la cosa estaba vinculando a todos.

Usted necesita para cambiar

g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp 

a esto:

g++ -g -Wall -o my_binary -L/my/dir bar.cpp -lfoo 

Su enlazador realiza un seguimiento de los símbolos que necesita para resolver. Si lee primero la biblioteca, , no tiene ningún símbolo necesario, por lo que ignora los símbolos que contiene. Especifique las bibliotecas después de las cosas que necesitan para vincularlas, de modo que su enlazador tenga símbolos para encontrar en ellas.

Además, -lfoo hace que busque específicamente un archivo llamado libfoo.a o libfoo.so según sea necesario. No libfoo.so.0. Entonces ln el nombre o cambie el nombre de la biblioteca según corresponda.

Para citar la página man gcc:

-l library 
    ... 
    It makes a difference where in the command you 
    write this option; the linker searches and processes 
    libraries and object files in the order they are 
    specified. Thus, foo.o -lz bar.o searches library z 
    after file foo.o but before bar.o. If bar.o refers 
    to functions in z, those functions may not be loaded. 

Agregar el archivo directamente a la línea de comandos g++ 's debería haber funcionado, a menos, por supuesto, lo pones antes de bar.cpp, provocando que el enlazador ignorar por carecer de los símbolos necesarios, porque todavía no se necesitaban símbolos.

Cuestiones relacionadas