2011-10-27 11 views
12

Necesito construir dos bibliotecas compartidas de terceros, por lo que sus archivos .so serán reutilizados por otros proyectos. Sin embargo, después de la compilación, una de estas bibliotecas contiene una ruta de acceso codificada a otra. Esta ruta no es válida en otras máquinas y causa advertencias del enlazador. ¿Cómo puedo evitar que la ruta completa se incruste en los archivos .so resultantes?¿Cómo construir una biblioteca compartida (.so) sin rutas de dependencia completas codificadas?

Detalles:

primera fuente de biblioteca: ~/dev/A
segunda fuente de biblioteca: ~/dev/B

Ambos tienen configure script para generar hacer que los archivos. La biblioteca B depende de A. Así, en primer construyo A:

$ ~/dev/A/configure --prefix=~/dev/A-install 
$ make && make install 

Entonces construir B:

$ ~/dev/B/configure --prefix=~/dev/B-install --with-A=~/dev/A-install 
$ make && make install 

entonces quiero cargar el contenido de ~/dev/A-install y ~/dev/B-install a nuestro servidor de archivos, por lo que otros equipos y construir máquinas se pueden utilizar los binarios Pero consiguen advertencias de vinculador cuando tratan de utilizar B:

/usr/bin/ld: warning: libA.so.2, needed by /.../deps/B/lib/libB.so, not found (try using -rpath or -rpath-link) 

Cuando corro ldd libB.so Da:

... 
libA.so.2 => /home/alex/dev/A-install/lib/libA.so.2 

Obviamente existe esta ruta sólo en mi máquina y no se puede encontrar en otras máquinas.

¿Cómo puedo eliminar el camino completo codificado desde libB.so?

Gracias.

+0

¿Cómo se vincula? Con libtool? En ese caso, 'patchelf' podría ayudarlo a deshacerse de la ruta codificada (el RPATH). –

+0

¿Por qué no usar un prefijo que no depende de su entorno, es decir '~'? ¿Por qué no usar algo como say '/ opt' como prefijo que no depende de la variable de entorno como' $ HOME' ('~')? Puede intentar ['LD_PRELOAD'] (http://stackoverflow.com/questions/426230/what-is-the-ld-preload-trick) –

+0

Idealmente, podría cambiar el script' configure' para evitar este problema. Si desea editar las bibliotecas, he oído cosas buenas sobre elfsh (http://www.eresi-project.org). – Beta

Respuesta

4

usted tiene que utilizar --prefix valor que será válido en el tiempo de ejecución ambiente para ambos paquetes!

Que se reemplaza prefix o DESTDIR (prefix reemplaza al prefijo, DESTDIR se antepone a ella, pero funciona de forma más fiable) en la línea de comando make durante la instalación. Al igual que:

~/dev/A$ ./configure 
~/dev/A$ make 
~/dev/A$ make install prefix=~/dev/A-install 
~/dev/B$ ./configure --with-A=~/dev/A-install 
~/dev/B$ make 
~/dev/B$ make install prefix=~/dev/B-install 

o (que se prefiere y es así como todas las herramientas de generación de paquetes utilizan):

~/dev/A$ ./configure 
~/dev/A$ make 
~/dev/A$ make install DESTDIR=~/dev/A-install 
~/dev/B$ ./configure --with-A=~/dev/A-install/usr/local 
~/dev/B$ make 
~/dev/B$ make install prefix=~/dev/B-install 

porque de esta manera va a instalar a ~/dev/A-install/$prefix, así que con prefijo predeterminado ~/dev/A-install/usr/local. La ventaja de esta última opción es que, si redefine algunas rutas de instalación específicas sin hacer referencia al prefijo (por ejemplo, --sysconfdir=/etc), DESTDIR seguirá colisionado, mientras que no se verá afectado por prefix.

+0

Gracias Jan! 'DESTDIR' es exactamente lo que necesitaba. –

-1

Tal vez el uso de los -rpath y -soname opciones para ld podría ayudar a (suponiendo un paquete binutils o binutils.gold para ld en un sistema Linux reciente)?

+0

¿Quiere usar estos indicadores con mi aplicación o con la biblioteca 'B'? –

+0

Bueno, exactamente lo contrario. Él necesita * STOP * usando -ruta; el rpath se está almacenando, pero está totalmente equivocado. –

+0

... y -rpath está siendo agregado por libtool de su abominación .la, por lo que necesita decirle a libtool que no lo ponga allí en primer lugar ... –

2
-Wl,-rpath,~/deps/A/lib:~/deps/B/lib:~/dev/MyApp/bin 

Esta opción del vinculador es responsable de guardar la ruta dentro de la biblioteca. Necesitas de alguna manera eliminar esto.

Consulte con ./configure --help si hay alguna opción que podría influir en esto. Otra opción es editar manualmente el archivo MAKE y eliminar esta opción.

== == Edit2 Una cosa más

-L~/deps/A/lib -L~/deps/B/lib ~/deps/A/lib/libA.so ~/deps/B/lib/libB.so 

Si libA.so y libB.so no tienen SONAME, vinculándolos como "~/deps/A/lib/libA.so" también causará salvar la ruta. Soname se configura utilizando la opción del vinculador -Wl,-soname,<soname> al compilar una biblioteca compartida.

Si soname está configurado en la biblioteca compartida, vincularlo con el formulario "~/deps/A/lib/libA.so" es correcto.

Como mencionó Jan en los comentarios, la mejor manera es usar "-Llibrary/path -llibrary_name" sin rpath.

-L~/deps/A/lib -L~/deps/B/lib -lA -lB 
+0

IIRC el -Lpath -lname no codifica * full * ruta mientras 'ruta/nombre' (no' -l'; no puede escribir '-lpath/nombre') * lo * codifica. Entonces, la combinación '-L' +' -l' debe ser utilizada, y no debe usarse '-Wl, -rpath', porque eso agrega la ruta de regreso después de que el uso de' -l' lo evitó. –

+0

De todos modos, es libtool el que agrega el rpath y lo hace para que todo funcione en el caso más común en el que desee instalar cosas en su hogar. –

+0

@ Jan Hudec No dije que -L/-l es el problema (rpath es), solo mencioné que hay una duplicación innecesaria de la ruta de la biblioteca en varios parámetros. De todos modos, eliminando la edición para evitar confusiones. –

0

Me quedé atrapada pensando que tenía el mismo problema. Ninguna de las respuestas anteriores me ayudó. Siempre que trataba

ldd libB.so 

que obtendría en la salida:

libA.so.1 => /home/me/localpath/lib/libA.so.1.0 

y así que pensé que tenía un camino codificado. Resulta que había olvidado que tenía LD_LIBRARY_PATH configurado para pruebas locales. Borrado LD_LIBRARY_PATH significaba que ldd encuentra instalada la biblioteca correcta en/usr/lib/

+1

Utilice 'objdump -p libB.so | grep NECESITO' para ver, no 'ldd'. – minghua

1

cuando corro LDD libB.so da:

libA.so.2 =>/home/alex/dev/A-install/lib/libA.so.2

La solución de bajo nivel para este problema es utilizar la opción "-soname = libA.so" cuando se vincula la biblioteca libA.so. Al tener SONAME definido para un objeto compartido, el vinculador no incrustará las rutas absolutas cuando se vincule con ese objeto compartido.

El OP usa "configure", por lo que esta no es una solución fácil de implementar a menos que esté dispuesto a entrar en las entrañas del Makefile generado por el script de configuración.

Cuestiones relacionadas