2011-06-22 18 views
11

¿Existen herramientas decentes para determinar el orden de enlace estático óptimo con g ++ en Linux? Estoy familiarizado con los problemas generales, incluido (si es necesario) el uso de referencias repetidas a una única biblioteca o --start-group y --end-group para resolver dependencias circulares, pero lo que me gustaría, si es posible, es una herramienta que tomará un montón de archivos .a y escupirá un buen orden de enlace estático para ellos, repitiendo bibliotecas si es necesario, mientras mantiene la repetición al mínimo.Buscando una herramienta de orden de enlace estático en Linux

Antecedentes: Estoy trabajando en un proyecto con alrededor de 800K líneas de código C++ heredado, y tratando de refactorizarlo en trozos más pequeños y más manejables. Algunos de los archivos existentes son monolitos enormes. Hoy he estado luchando con un único archivo .h de línea de 34K que definió 113 clases y estructuras. Muchas de las clases se definieron casi en su totalidad en línea en el archivo .h. Al dividir esto en fragmentos más pequeños y migrar parte del código de implementación en archivos .cpp, el orden de enlace requerido en Linux sigue cambiando. Probablemente se deba a que cada biblioteca que incluía el archivo .h solía compilar su propia implementación de las clases que necesitaba, y ahora tienen que vincularse a una implementación común en un solo archivo de biblioteca. A largo plazo probablemente reorganicemos algunas de las clases en diferentes bibliotecas, y rompamos algunas de las cadenas de dependencia, pero ahora las dependencias están bastante enredadas, y estoy tratando de minimizar las perturbaciones al código que podrían cambiar el comportamiento. Prefiero no tener que seguir averiguando manualmente el orden de enlace correcto cada vez que cambie. Sugerencias?

Respuesta

4

No conozco ninguno, pero puede implementar uno usted mismo. Solo use nm para obtener una lista de símbolos de cada biblioteca estática, use esto para construir un gráfico de dependencia, luego realice una ordenación topológica sobre el gráfico para el orden de enlace apropiado.

De forma alternativa, utilice enlaces parciales (ld -r) en lugar de bibliotecas estáticas. Dado que esto produce un archivo .o fusionado, su enlace final puede declarar las bibliotecas en cualquier orden, y todas se vincularán correctamente. La desventaja es que el vinculador no podrá descartar los archivos fuente no utilizados, ya que ya están vinculados en archivos monolíticos antes de que estén disponibles los datos de uso (puede solucionar esto pasando -ffunction-sections -fdata-sections durante la compilación y -Wl,--gc-sections en el enlace final, aunque esto puede impacto cuánto tiempo lleva compilar)

+1

he pensado en eso, pero el problema es un poco más complicado que eso. El tipo topológico funciona si necesita esperar a todos los que lo llaman antes de ser incluido. Pero eso no es necesario aquí: si la biblioteca A tiene un símbolo a que necesita un símbolo b de la biblioteca B, está bien (y de hecho, puede ser necesario) que B preceda a A en el orden de enlace mientras haya alguien antes en la orden que también requiere b. Probablemente podría trabajar con un algoritmo razonable, pero tomaría tiempo, y mientras tanto, hay trabajo con plazos para hacerlo. Así que preferiría una solución probada en batalla que ya esté allí. – dewtell

+0

@dewtell: Puede haber casos en los que este enfoque no funcione, pero ¿está seguro de que su código base es uno de ellos? –

+0

@Andrew - bastante seguro. En función de las inclusiones de los archivos .h, hay muchos casos en que el archivo1a en lib1 hace referencia a un símbolo definido en el archivo2a en lib2, mientras que el archivo2b en lib2 hace referencia a un símbolo definido en el archivo1b en lib1. – dewtell

1

Puede usar bibliotecas compartidas en lugar de estáticas y compilar con la opción -fPIC.

+0

Esta no es una buena idea para nosotros en el corto plazo, ya que cambiaría radicalmente la forma en que enviamos e instalamos el programa, y ​​presentamos una nueva fuente de errores. A la larga, es algo que podríamos mirar, pero probablemente no solo para resolver este problema en particular. – dewtell

Cuestiones relacionadas