¿Cómo fusionar dos bibliotecas estáticas "ar" en una?

90

Tengo bibliotecas estáticas Linux 2, creado por ar cr, libabc.ay libxyz.a.
Quiero fusionarlos en una biblioteca estática libaz.a.
Cómo puedo hacer esto.

Quiero crear una biblioteca estática combinada, no dar ambas bibliotecas al enlace final de las aplicaciones.

osgx
fuente
7
Ver también: libtoollibtool -static -o new.a old1.a old2.a
-based
2
Funciona perfecto, solo una pequeña duda si esas bibliotecas tienen un archivo común. o (pero en cuanto a funcionalidad son diferentes) ¿seguirá funcionando?
bindingofisaac
libtool -static -o new.a old1.a old2.a dosen not work on linux (centos 7)
vacing

Respuestas:

60

Puede extraer el objeto de ambos .aarchivos y crear su .aarchivo utilizando los .os extraídos :

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o
codaddict
fuente
63
¡Peligro, Will Robinson! Esto solo funciona si los nombres de los miembros de libabc.ay libxyz.a no se superponen. De lo contrario, sobrescribirá uno y se perderá.
David dado el
6
Además, libabc.apuede contener objetos con el mismo nombre (originados en diferentes directorios) - ¡el reensamblaje no funcionará entonces!
Igor R.
16
ar -cno funcionó para mí (Ubuntu 14.04). Tengo ar: no operation specified. En su ar -qclugar, lo hice y funcionó bien.
Máximo
ar t lib.a se puede utilizar para ver los archivos en la biblioteca sin tener que extraerlos.
raj_gt1
¿Cómo puedo hacer eso en automake?
shuva
120

Hay al menos tres formas de hacer esto de forma nativa . La primera y más portátil forma es usar libtool. Después de haber construido las otras bibliotecas también con libtool, puede combinarlas simplemente agregando las .la libs a una variable libaz_la_LIBADD de automake, o directamente desde un Makefile con algo como:

libtool --mode=link cc -static -o libaz.la libabc.la libxyz.la

Los otros dos están disponibles al menos cuando se usa GNU ar. Puede utilizar un script de MRI (llamado, por ejemplo, libaz.mri), como:

create libaz.a
addlib libabc.a
addlib libxyz.a
save
end

y luego ejecute ar como:

ar -M <libaz.mri

O puede usar un archivo delgado (opción -T), que permitirá agregar otros archivos sin anidarlos dentro, aunque la desventaja es que si desea distribuir la biblioteca estática, faltará el objeto separado:

ar -rcT libaz.a libabc.a libxyz.a

Todos los métodos anteriores manejan con gracia los nombres de miembros superpuestos de los archivos originales.

De lo contrario, tendría que descomprimir en directorios diferentes y volver a empaquetar, para evitar reemplazar nombres de miembros superpuestos:

mkdir abc; cd abc; ar -x ../libabc.a
mkdir xyz; cd xyz; ar -x ../libxyz.a
ar -qc libaz.a abc xyz
Guillem Jover
fuente
19
Para aquellos que desean un archivo normal (no delgado), una cosa simple que se puede hacer es crear un archivo delgado y luego convertirlo en un archivo normal. Algo así como: ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M. Esto crea un libaz.aarchivo delgado temporal y luego convierte el archivo delgado en uno normal (para que pueda moverlo / distribuirlo). Esto también maneja con gracia cuando los nombres de su biblioteca tienen caracteres especiales (espaciado, más o comas) (es decir ar cqT libbundle.a libfoo++.a 'libbar baz.a'). ¡Pero +1 de mí!
Cornstalks
¿Cuál es la desventaja del primer ejemplo de guión de resonancia magnética dado?
jb
¡Buena respuesta! Es bueno ver algunas opciones que no requieren que extraigas y recuperes. También creo que la idea de @Cornstalks es buena. ¿Quizás debería agregarse a la respuesta?
Bombilla
Oye, cuando intento usar el comando libtool, obtengo estos errores: ¿ libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' Alguna idea de cómo solucionarlo?
Lars Nielsen
@Guillem @Cornstalks Gran respuesta. ¿Qué sucede si --Wl,-whole-archivese requiere la opción en el comando de vinculación original para múltiples lib * .a, y necesito combinar todos los lib * .a en one.a. Cuando vuelva a vincular, --Wl,-whole-archiveno funcionará con one.a. ¿Cuál es tu sugerencia? stackoverflow.com/questions/56323197/…
thinkdeep
10

Si simplemente lo hace como:

ar x a.a
ar x b.a
ar c c.a  *.o 

perderá algunos archivos de objeto si hay miembros con el mismo nombre tanto en aa como en ba, por lo que debe extraer miembros de diferentes archivos en una carpeta diferente:

ar x a.a && mv *.o a_objs
ar x b.a && mv *.o b_objs
ar c c.a a_objs/*.o b_objs/*.o

además, es posible que haya varios miembros del mismo nombre en un archivo (digamos en aa), si ejecuta ar x aa , obtendrá solo uno para los miembros del mismo nombre.

La única forma de extraer todos los miembros del mismo nombre en un archivo es especificar el número de miembro mediante la opción 'N':

ar xN 1 a.a  xxx.c.o && mv xxx.c.o xxx.c.1.o
ar xN 2 b.a  xxx.c.o && mv xxx.c.o xxx.c.2.o
...

este sería un trabajo tedioso, por lo que tendrá que escribir un guión más sofisticado para hacer ese trabajo.

Una solución opcional es que puede combinar varios archivos en una biblioteca compartida:

g++ -shared -o c.so -Wl,--whole-archive a.a b.a 

de esta manera, el enlazador se encargará de todo por usted.

samuel.zzy220
fuente
1
Samuel, gracias. Pero al combinarlo en una biblioteca compartida, todos los objetos deben compilarse con -fPIC.
osgx
0

Aún mejor, realiza un enlace parcial en cada biblioteca y ellos hacen un archivo de los dos archivos de objeto resultantes. De esa forma funciona como lo harían las bibliotecas compartidas

Haces enlaces parciales con

gcc -r --nostdlib

así que en lugar de hacer el archivo intermedio o después de volver a extraerlo, ejecute

gcc -r --nostdlib $CFLAGS $OBJECTS_A -o $LIBNAME_A.o
gcc -r --nostdlib $CFLAGS $OBJECTS_B -o $LIBNAME_B.o

entonces

ar -cr $LIBNAME_JOINED.a $LIBNAME_A.o $LIBNAME_B.o
Allan Jensen
fuente
En realidad, no responde a la pregunta formulada, como pidió las bibliotecas. Muchas veces ni siquiera tiene las fuentes de las bibliotecas o desea mantenerlas compiladas previamente por otras razones.
pholat
0
ar -x libx264.a
mkdir sub && cd sub
ar -m ../libx264.a `ar -t ../libx264.a |sort|uniq|grep "\.o"`
ar -x ../libx264.a

ahora tienes dos versiones de "macroblock-10.o"

ley wey
fuente
0
ar crsT libaz.a libabc.a libxyz.a

Aquí, crea un archivo de archivos y luego 'aplana' (adelgazamiento) el resultado con la bandera T. No estoy seguro de cómo funcionará con archivos del mismo nombre .o que podrían estar contenidos en.

Evgeny Yashin
fuente