2009-03-20 21 views
13

Suponga que he decir tres C bibliotecas estáticas libColor.a que depende de libRGB *. * A que a su vez depende de libPixel.a. La biblioteca libColor.a se dice que dependerá de biblioteca libRGB.a ya que hay algunas referencias en libColor.a a algunas de símbolos definidos en libRGB.a. ¿Cómo combino todas las bibliotecas anteriores en una nueva libNewColor.a que es independiente?bibliotecas estáticas

Independiente significa que la nueva biblioteca debe tener todos los símbolos definidos. Por lo tanto, al vincular solo necesito dar -lNewColor. El tamaño de la nueva biblioteca debe ser mínima, es decir que no debe contener ningún símbolo en libRGB.a que no se utiliza por libColor.a etc. probé suerte con varias opciones en ar comando (usado para crear y actualizar bibliotecas/archivos estáticos).

+0

Usted puede mirar alternativamente en la dirección http: // stackoverflow. com/questions/8170450/combine-static-libraries/8170851 # 8170851 y use libt ool – Bruce

+0

Tenga en cuenta que el paso de minimización realmente no es necesario. Con las bibliotecas estáticas, el vinculador solo obtendrá los archivos objeto que necesita, a diferencia de las bibliotecas compartidas que incluyen todo. Hay razones y ventajas para cada enfoque; simplemente son diferentes. Y realmente no necesita preocuparse mientras trabaja con bibliotecas estáticas. –

Respuesta

11

1/Extraiga TODOS los archivos de objeto de cada biblioteca (usando ar) e intente compilar su código sin las bibliotecas o cualquiera de los archivos de objeto. Probablemente obtendrá una carga completa de símbolos indefinidos. Si no obtiene símbolos indefinidos, vaya al paso 5.

2/Tome la primera y descubra qué archivo de objeto satisface ese símbolo (usando nm).

3/Anote ese archivo objeto y luego compile su código, incluido el nuevo archivo objeto. Usted obtendrá una nueva lista de símbolos no definidos o, si no hay ninguno, vaya al paso 5.

4/Ir al paso 2.

5/Combinar todos los ficheros objeto en su lista (si los hay) en una sola biblioteca (de nuevo con ar).

Bang! Ahí tienes. Intente vincular su código sin ninguno de los objetos, pero con la nueva biblioteca.

Todo esto podría automatizarse con relativa facilidad con un script de shell.

+2

Innecesariamente complicado, puedes extraer todos los archivos .o en una .a grande, ya que cuando finalmente se vincula a un ejecutable, el enlazador descartará los que no se usen de todos modos – MarkR

+2

@MarkR, @AIB quería el tamaño de la * biblioteca * ser mínimo, no el tamaño del ejecutable. – paxdiablo

+0

Lo acepto, aunque me encantaría un oneliner que lo haga. Como pasar algunas opciones a ld para vincular solo con los símbolos necesarios, etc. – AIB

5

Una biblioteca estática no es mucho más que un archivo de algunos archivos de objeto (.o). Lo que puede hacer es extraer todos los objetos en las dos bibliotecas (usando "ar x") y luego usar "ar" para unirlos en una nueva biblioteca.

15

Una característica poco usada del archivador de GNU es la secuencia de comandos de archivo, que es una interfaz sencilla pero potente, y puede hacer exactamente lo que quiere, por ejemplo, si el siguiente script se llama script.ar:

CREATE libNewColor.a 
ADDLIB libColor.a 
ADDLIB libRGB.a 
ADDLIB libPixel.a 
SAVE 
END 

entonces se podría invocar ar de la siguiente manera:

ar -M < script.ar 

y que se obtendría libNewColor.a que contiene todos los archivos .o de libColor.a libRGB.a y libPixel.a.

Además, también puede agregar regularmente.o archivos, así como con el comando ADDMOD:

CREATE libNewColor.a 
ADDLIB libColor.a 
ADDLIB libRGB.a 
ADDLIB libPixel.a 
ADDMOD someRandomCompiledFile.o 
SAVE 
END 

Además, es muy fácil de generar estos scripts en Makefile, por lo que suelen crear una regla makefile bien genérica para la creación de archivos que en realidad genera la secuencia de comandos e invoca ar en el guión. Algo como esto:

$(OUTARC): $(OBJECTS) 
    $(SILENT)echo "CREATE [email protected]" > $(ODIR)/$(ARSCRIPT) 
    $(SILENT)for a in $(ARCHIVES); do (echo "ADDLIB $$a" >> $(ODIR)/$(ARSCRIPT)); done 
    $(SILENT)echo "ADDMOD $(OBJECTS)" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)echo "SAVE" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)echo "END" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)$(AR) -M < $(ODIR)/$(ARSCRIPT) 

Aunque ahora que lo miro supongo que no funciona si $ (objetos) está vacío (es decir, si lo que desea es combinar archivos sin añadir archivos de objetos adicionales) pero lo haré dejarlo como un ejercicio para el lector a solucionar ese problema, si es necesario ...: D

Aquí están los documentos para esta función:

https://sourceware.org/binutils/docs/binutils/ar-scripts.html#ar-scripts

+0

¡Esto es genial! Excepto que las rutas/libs que tienen un + en el nombre rompen el script. Por ejemplo, openssl tiene libncurses ++. A – Gregory

+0

¡Neat! Esto es mucho más fácil que desempaquetar y reempaquetar archivos de objetos usted mismo. – Thomas

+0

Tenga en cuenta que, por alguna razón, -D no funciona en combinación con -M. Entonces, si desea obtener resultados deterministas, aún necesita la ruta extraer-luego-archivar. –

Cuestiones relacionadas