2010-04-29 12 views
14

Estoy portando un sistema existente de Windows a Linux. La construcción está estructurada con múltiples bibliotecas estáticas. Me encontré con un error de enlace en el que no se podía encontrar un símbolo (definido en libA) en un objeto de libB. La línea enlazador parecía¿Cómo lidiar con dependencias recursivas entre bibliotecas estáticas usando el vinculador binutils?

g ++ test_obj.o prueba -LA -LB -o

El problema, por supuesto, es que en el momento en el enlazador encuentra que necesita el símbolo de Liba, que ya ha pasado por, y no vuelve a explorar, por lo que simplemente se equivoca aunque el símbolo esté ahí para tomarlo.

Mi idea inicial fue, por supuesto, simplemente intercambiar el enlace (a -lB -lA) para que luego se escanee libA, y se eliminen los símbolos que falten de libB que estén en libA. ¡Pero luego descubrí que en realidad hay una dependencia recursiva entre libA y libB! Supongo que el enlazador de Visual C++ maneja esto de alguna manera (¿vuelve a escanear por defecto?).

modos de tratamiento de este he considerado:

  • utilizar objetos compartidos. Desafortunadamente, esto no es deseable desde la perspectiva de requerir la compilación de PIC (este es el código de rendimiento sensible y perder% ebx para mantener el GOT realmente dolería), y los objetos compartidos no son necesarios.

  • Construya un mega ar de todos los objetos, evitando el problema.

  • Reestructurar el código para evitar la dependencia recursiva (que obviamente es lo correcto, pero estoy intentando hacer este puerto con cambios mínimos).

¿Tiene otras ideas para solucionar esto? ¿Hay alguna manera de convencer al enlazador de binutils para que vuelva a analizar las bibliotecas que ya ha examinado cuando falta un símbolo?

Respuesta

18

Sólo hacer esto:

g++ test_obj.o -lA -lB -lA  -o test 

Cuando el enlazador lee la primera Liba en la línea de comandos, que va a descartar el objeto/símbolos en los mismos que nadie ha dependido todavía, por ejemplo, todos los símbolos que libB necesita, pero no test_obj.o. Entonces solo haz que lea libA nuevamente, y recogerá esos símbolos también.

+2

Esta pregunta y la respuesta es un gran ejemplo de una solución elegante que salta a la vista, tales ... Se lee casi como el remate de una broma ...:) – dicroce

10

Mientras @nos proporciona una solución simple, no escala cuando hay múltiples bibliotecas involucradas y las dependencias mutuas son más complejas. Para solucionar los problemas, ld proporciona --start-group archives --end-group.

En su caso particular:

g++ test_obj.o --start-group -lA -lB --end-group -o test 
+0

g ++ test_obj.o -Wl, - grupo-inicio -lA -lB -Wl, - grupo-final -o test – yokto

Cuestiones relacionadas