una que programacion librerías librerias libreria lenguaje estatica entre dinámicas dinamicas dinamica diferencia desarrolladas crear creacion crea con compilar como biblioteca gcc dll dependencies g++

gcc - que - Vinculación con la biblioteca dinámica con dependencias



que es una libreria en programacion (4)

Esta es una publicación interesante. También me estaba golpeando la cabeza con esto, pero creo que echas en falta un punto aquí.

La idea es la siguiente, ¿verdad?

main.cpp =(depends)=> libB.so =(depends)=> libA.so

Consideremos además eso ...

  • En a.cpp (y solo allí) defines una clase / variable, llamémosla "symA"
  • En b.cpp (y solo allí) define una clase / variable, vamos a llamarlo "symB".
  • symB usa symA
  • main.cpp usa symB

Ahora, libB.so y libA.so se han compilado como describió anteriormente. Después de eso, tu primera opción debería funcionar, es decir:

g++ main.cpp -o main -I. -L. -lB

Supongo que su problema proviene del hecho de que

en main.cpp también se refiere a symA

¿Estoy en lo correcto?

Si usa un símbolo en su código, entonces ese símbolo debe encontrarse en un archivo .so

La idea de interreferenciar bibliotecas compartidas (es decir, crear API) es que los símbolos en las capas más profundas están ocultos (piense en pelar cebollas) y no se usan. .. es decir, no se refiere a symA en su main.cpp, sino solo a symB en su lugar (y deje que symB se refiera a symA solamente).

Considere la siguiente situación:

  • Biblioteca compartida libA.so, sin dependencias.
  • Biblioteca compartida libB.so, con libA.so como su dependencia.

Quiero compilar un archivo binario que enlace con el libB. ¿Debo vincular el binario con libB solo o con libA?

¿Hay alguna forma de vincular solo con las dependencias directas, permitiendo la resolución de símbolos no resueltos de las dependencias para el tiempo de ejecución?

Me preocupa el hecho de que la implementación de bibliotecas libB pueda cambiar en el futuro, introduciendo otras dependencias (libC, libD, libE, por ejemplo). ¿Voy a tener problemas con eso?

En otras palabras:

  • archivos libA: a.cpp ah
  • archivos libB: b.cpp bh
  • archivos principales del programa: main.cpp

Por supuesto, b.cpp incluye ah y main.cpp incluye bh

Comandos de compilación:

g++ -fPIC a.cpp -c g++ -shared -o libA.so a.o g++ -fPIC b.cpp -c -I. g++ -shared -o libB.so b.o -L. -lA

¿Cuál de las siguientes opciones debería usar?

g++ main.cpp -o main -I. -L. -lB

o

g++ main.cpp -o main -I. -L. -lB -lA

No pude usar la primera opción. El enlazador se queja de los símbolos no resueltos de la biblioteca libA. Pero me suena un poco extraño.

Muchas gracias.

- Comentarios actualizados:

Cuando enlace el binario, el enlazador intentará resolver todos los símbolos del main y el libB. Sin embargo, libB tiene símbolos indefinidos de libA. Es por eso que el enlazador se queja de eso.

Es por eso que también necesito vincularme con libA. Sin embargo, encontré una forma de ignorar los símbolos no resueltos de las bibliotecas compartidas. Parece que debería usar la siguiente línea de comando para hacer eso:

g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs

Parece que todavía es posible usar la opción -rpath . Sin embargo, necesito entenderlo un poco mejor.

¿Alguien sabe posibles trampas al usar la -Wl,-unresolved-symbols=ignore-in-shared-libs ?

- Comentarios actualizados 2:

-rpath no debe usarse para este propósito. Es útil forzar que se encuentre una biblioteca en un directorio determinado. El -unresolved-symbol se ve mucho mejor.

Gracias de nuevo.


Otra opción es usar libtool

Si cambia la llamada g++ a libtool --mode=compile g++ para compilar el código fuente y luego libtool --mode=link g++ para crear la aplicación fuera de libB , entonces libA se vinculará automáticamente.


Para la vinculación dinámica solo con dependencias directas, puede usar -Wl,--as-needed con la adición de las -Wl,--as-needed después de -Wl,--as-needed :

gcc main.c -o main -I. -L. -Wl,--as-needed -lB -lA

Para verificar las dependencias directas, debe usar readelf en lugar de ldd porque ldd también muestra las dependencias indirectas.

$ readelf -d main | grep library 0x0000000000000001 (NEEDED) Shared library: [libB.so] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]

ldd también muestra las dependencias indirectas:

$ LD_LIBRARY_PATH=. ldd ./main linux-vdso.so.1 (0x00007fff13717000) libB.so => ./libB.so (0x00007fb6738ed000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb6734ea000) libA.so => ./libA.so (0x00007fb6732e8000) /lib64/ld-linux-x86-64.so.2 (0x00007fb673af0000)

Si usa cmake , puede agregar las siguientes líneas para incluir solo dependencias directas:

set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}")


Parece que ya has recorrido la mayor parte del camino. Bien hecho con tu investigación. Veamos si puedo ayudar a aclarar el "por qué" detrás de esto.

Esto es lo que hace el enlazador. Cuando vincula su ejecutable (''main'' arriba) tiene algunos símbolos (funciones y otras cosas) que no están resueltos. Buscará en la lista de bibliotecas que siguen, tratando de resolver los símbolos no resueltos. En el camino, descubre que algunos de los símbolos son proporcionados por libB.so, por lo que observa que ahora los resuelve esta biblioteca.

Sin embargo, también descubre que algunos de esos símbolos usan otros símbolos que aún no se han resuelto en su ejecutable, por lo que ahora también necesita resolverlos. Sin vincular con libA.so, su aplicación estaría incompleta. Una vez que se vincula con libA.so, se resuelven todos los símbolos y se completa el enlace.

Como viste, el uso de -unresolved-symbols-in-shared-libs , no soluciona el problema. Simplemente lo difiere para que esos símbolos se resuelvan en tiempo de ejecución. Eso es lo que -rpath es para: especificar las bibliotecas que se buscarán en tiempo de ejecución. Si esos símbolos no se pueden resolver, su aplicación no podrá iniciarse.

No es fácil averiguar las dependencias de la biblioteca porque un símbolo podría ser provisto por más de una biblioteca y estar satisfecho al vincularse con cualquiera de ellas.

Aquí hay otra descripción de este proceso: ¿por qué el orden en que se vinculan las bibliotecas a veces causa errores en GCC?