2011-01-24 27 views
5

Mi proyecto consiste en un par de bibliotecas estáticas, que se unen entre sí en un paso final. Ahora tengo el problema, que el link order of the library is important (de lo contrario me sale un error de enlazador de símbolos indefinido). A veces me encuentro con el problema, que tengo que volver a ordenar las bibliotecas vinculadas (-lcommon -lsetup -lcontrol, etc.). Por el momento, es una prueba y un error estúpidos: reordenar, compilar, verificar errores, reordenar, compilar, etc.¿Cómo se determinan las dependencias entre bibliotecas?

Así que escribí un pequeño programa para mostrarme las inter-bibliotecas-dependencias y me genera el orden de las bibliotecas para vincular. Se lee en los símbolos definidos ('T', 'B', etc.) y no definidos ('U') de nm y elimina el weak symbols ('w', 'W', 'v' y 'V') del ' lista de símbolos indefinida '. Ahora determina para cada símbolo indefinido la biblioteca que lo resuelve.

Pero mi programa me muestra las dependencias circulares ... ¿cuál es mi error?

Si realmente existen, no podría vincular en absoluto ... así que ¿Qué extrañé al analizar la salida nm? ¿O está analizando la salida de nm no de la manera adecuada para obtener estas dependencias?

libcommon.a: 
     U _ZN15HardwareUnit23GetHardwareSerialNumberEv 
libhardware.a: 
00000484 T _ZN15HardwareUnit23GetHardwareSerialNumberEv 
libsecurityaccess.a: 
     U _ZN15HardwareUnit23GetHardwareSerialNumberEv 
--- 
libhardware.a: 
     U _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString 
libsecurityaccess.a: 
00004020 T _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString 
     U _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString 

Respuesta

6

Otra opción para vincular bibliotecas con dependencias circulares es utilizar una opción de enlazador especial para eso. Man ld:

-(archives -) 
    --start-group archives --end-group 
     The archives should be a list of archive files. They may be either 
     explicit file names, or -l options. 

     The specified archives are searched repeatedly until no new 
     undefined references are created. Normally, an archive is searched 
     only once in the order that it is specified on the command line. 
     If a symbol in that archive is needed to resolve an undefined 
     symbol referred to by an object in an archive that appears later on 
     the command line, the linker would not be able to resolve that 
     reference. By grouping the archives, they all be searched 
     repeatedly until all possible references are resolved. 

     Using this option has a significant performance cost. It is best 
     to use it only when there are unavoidable circular references 
     between two or more archives. 

Sin embargo, siempre es más limpio eliminar las dependencias circulares.

+0

¿Hay alguna manera de determinar qué 'dependencias circulares' romperán la compilación y cuáles no? – Charly

+0

El vinculador le indica los nombres de los símbolos que no pudo resolver. –

+0

Sí, esta es la forma en que lo estoy haciendo ahora (cuando no utilizo la 'opción de grupo' - que funciona muy bien, THX !!). Recopilo, reordeno la lista de la biblioteca y me encuentro con el siguiente error del enlazador. Si fuera capaz de calcular las dependencias de antemano, crearía el orden de la biblioteca antes de la compilación y no tendría que hacerlo por prueba y error. (En este momento hay alrededor de 20 bibliotecas y cada una tiene dependencias con otros módulos) – Charly

2

Si realmente tiene una cadena de dependencia circular de las bibliotecas estáticas (y esto no es claro de su pasta; mostrar solamente una dependencia no circular), hay dos opciones:

  1. Retire la dependencia circular de alguna manera; por ejemplo, puede asegurarse de que libcommon no haga referencia a símbolos en libpthardware.
  2. Extraiga los archivos .o individuales de la biblioteca .a y vinculelos directamente. Entonces, el orden del enlace ya no importa.

En el caso de 2., puede que le resulte útil utilizar enlaces parciales en lugar de crear bibliotecas estáticas. En los sistemas que utilizan bintools GNU, esto se puede hacer mediante la invocación de algo como:

ld -r -o libfoo.o foo.o bar.o 

El efecto de esto es combinar foo.o y bar.o en un solo archivo .o. El orden no importa. A continuación, puede simplemente hacer referencia a libfoo.o como un archivo de objeto normal en su paso de enlace final.

Tenga en cuenta que esto puede interfere with the linker's ability to discard unreferenced portions of the static library (normalmente esto se hace al nivel de archivos .o dentro de la .a, creo). Si está utilizando todas o la mayoría de estas bibliotecas, probablemente esto no sea un problema. Sin embargo, si la memoria del código es un problema, es posible que desee consultar automatically discarding unused code at the function level. Si lo hace, pase --gc-sections y -s solo en la etapa de enlace final (¡y evite hacerlo si necesita depurar!). Además, la vinculación estática con las bibliotecas del sistema no parece ser necesaria con el gcc moderno.

+0

Muchas gracias. Esto podría resolver el síntoma, pero al final me interesarían las dependencias entre las bibliotecas. ¿Por qué la salida nm me muestra una dependencia circular, pero la vinculación es exitosa? – Charly

+0

No estoy seguro - en mi experimentación, encontré que ciertos ordenamientos de bibliotecas con una dependencia circular tienen un enlace exitoso, pero no estoy seguro de por qué.Leí tu pregunta preguntando cómo lidiar con la situación, pero si estás más interesado en saber por qué tuvo éxito, sugiero construir un caso de prueba mínimo (debería ser bastante trivial) y enviar una pregunta explícitamente preguntando por qué tiene éxito . – bdonlan

Cuestiones relacionadas