c++ - tipos - librerias de c
g++: ¿En qué orden deberían estar vinculadas las bibliotecas estáticas y dinámicas? (5)
Digamos que obtuvimos un ejecutable principal llamado "my_app" y usa muchas otras bibliotecas: 3 bibliotecas están vinculadas estáticamente, y otras 3 están vinculadas dinámicamente. ¿En qué orden deberían estar vinculados con "my_app"?
Pero, ¿en qué orden deberían estar vinculados?
Digamos que tenemos libSA (como en Static A) que depende de libSB, y libSC que depende de libSB:
libSA -> libSB -> libSC
y tres bibliotecas dinámicas: libDA -> libDB -> libDC
( libDA
es el básico, libDC
es el más alto)
¿En qué orden deberían estar vinculados? el básico primero o último?
g++ ... -g libSA libSB libSC -lDA -lDB -lDC -o my_app
parece el orden correcto, pero ¿es así? ¿Qué pasa si hay dependencias entre una biblioteca dinámica y una estática, o de otra manera?
En el caso estático, realmente no importa, porque en realidad no vincula bibliotecas estáticas; todo lo que hace es empaquetar algunos archivos de objetos en un solo archivo. Todo lo que tiene que hacer es compilar sus archivos objeto, y puede crear bibliotecas estáticas de inmediato.
La situación con las bibliotecas dinámicas es más intrincada, hay dos aspectos:
Una biblioteca compartida funciona exactamente de la misma manera que la biblioteca estática (a excepción de los segmentos compartidos, si están presentes), lo que significa que puede hacer lo mismo: simplemente enlace su biblioteca compartida tan pronto como tenga los archivos objeto. Esto significa, por ejemplo, que los símbolos de libDA aparecerán como indefinidos en libDB
Puede especificar las bibliotecas a las que vincular en la línea de comando al vincular objetos compartidos. Esto tiene el mismo efecto que 1., pero marca LibDB como que necesita libDA.
La diferencia es que si usa la forma anterior, debe especificar las tres bibliotecas (-DA, -lDB, -lDC) en la línea de comando al vincular el ejecutable. Si usa este último, solo debe especificar -lDC y extraerá los otros automáticamente al momento del enlace. Tenga en cuenta que el tiempo de enlace es justo antes de que se ejecute su programa (lo que significa que puede obtener diferentes versiones de símbolos, incluso desde diferentes bibliotecas).
Todo esto se aplica a UNIX; Windows DLL funciona de manera bastante diferente.
Editar después de la aclaración de la pregunta:
Cita del manual de información ld
.
El vinculador buscará un archivo solo una vez, en la ubicación donde se especifica en la línea de comando. Si el archivo define un símbolo que no estaba definido en algún objeto que apareció antes del archivo en la línea de comando, el vinculador incluirá los archivos correspondientes del archivo. Sin embargo, un símbolo indefinido en un objeto que aparece más adelante en la línea de comando no hará que el vinculador busque nuevamente en el archivo.
Vea la opción `- (''para una forma de forzar al enlazador a buscar archivos múltiples veces.
Puede enumerar el mismo archivo varias veces en la línea de comando.
Este tipo de búsqueda de archivos es estándar para los vinculadores de Unix. Sin embargo, si usa `ld ''en AIX, tenga en cuenta que es diferente del comportamiento del enlazador de AIX.
Eso significa:
Cualquier biblioteca estática u objeto que dependa de otra biblioteca debe colocarse antes en la línea de comando. Si las bibliotecas estáticas dependen el uno del otro de forma circular, puede, por ejemplo. use la opción -(
línea de comando, o coloque las bibliotecas en la línea de comando dos veces ( -lDA -lDB -lDA
). El orden de las bibliotecas dinámicas no importa.
Es una buena práctica mantener las bibliotecas independientes entre sí para evitar problemas de orden de enlace.
Este es el tipo de pregunta que mejor se resuelve con un ejemplo trivial. ¡De Verdad! Tómese 2 minutos, codifique un ejemplo simple y ¡pruébelo! Aprenderás algo, y es más rápido que preguntar.
Por ejemplo, archivos dados:
a1.cc
#include <stdio.h>
void a1() { printf("a1/n"); }
a2.cc
#include <stdio.h>
extern void a1();
void a2() { printf("a2/n"); a1(); }
a3.cc
#include <stdio.h>
extern void a2();
void a3() { printf("a3/n"); a2(); }
aa.cc
extern void a3();
int main()
{
a3();
}
Corriendo:
g++ -Wall -g -c a1.cc
g++ -Wall -g -c a2.cc
g++ -Wall -g -c a3.cc
ar -r liba1.a a1.o
ar -r liba2.a a2.o
ar -r liba3.a a3.o
g++ -Wall -g aa.cc -o aa -la1 -la2 -la3 -L.
Muestra:
./liba3.a(a3.o)(.text+0x14): In function `a3()'':
/tmp/z/a3.C:4: undefined reference to `a2()''
Mientras:
g++ -Wall -g -c a1.C
g++ -Wall -g -c a2.C
g++ -Wall -g -c a3.C
ar -r liba1.a a1.o
ar -r liba2.a a2.o
ar -r liba3.a a3.o
g++ -Wall -g aa.C -o aa -la3 -la2 -la1 -L.
Tiene éxito (Solo se cambia el orden de los parámetros -la3 -la2 -la1).
PD:
nm --demangle liba*.a
liba1.a:
a1.o:
U __gxx_personality_v0
U printf
0000000000000000 T a1()
liba2.a:
a2.o:
U __gxx_personality_v0
U printf
U a1()
0000000000000000 T a2()
liba3.a:
a3.o:
U __gxx_personality_v0
U printf
U a2()
0000000000000000 T a3()
De hombre nm :
Si es minúsculo, el símbolo es local; si es mayúscula, el símbolo es global (externo).
"T" El símbolo está en la sección de texto (código).
"U" El símbolo no está definido.
Las dependencias para vincular una biblioteca o ejecutable tienen que estar presentes en tiempo de enlace, por lo que no puede vincular libXC antes de que esté presente libXB. No importa si estática o dinámicamente.
Comience con la más básica, que no tiene (o solo está fuera de su proyecto) dependencias.
Trabajé en un proyecto con un grupo de bibliotecas internas que lamentablemente dependían unas de otras (y empeoraron con el tiempo). Terminamos "resolviendo" esto configurando SCons para especificar todas las librerías dos veces al vincular:
g++ ... -la1 -la2 -la3 -la1 -la2 -la3 ...