Comment fusionner deux bibliothèques statiques «ar» en une seule?

90

J'ai 2 statiques bibliothèques Linux, créées par ar cr, libabc.aet libxyz.a.
Je veux les fusionner dans une bibliothèque statique libaz.a.
Comment puis-je faire ceci.

Je veux créer une bibliothèque statique fusionnée, pas pour donner les deux bibliothèques au lien final des applications.

osgx
la source
7
Voir aussi: libtoollibtool -static -o new.a old1.a old2.a
-solution
2
cela fonctionne parfaitement, juste un petit doute si ces bibliothèques ont un fichier commun.
bindingofisaac
libtool -static -o new.a old1.a old2.a ne fonctionne pas sous linux (centos 7)
départ

Réponses:

60

Vous pouvez extraire l'objet des deux .afichiers et créer votre .afichier en utilisant les .os extraits :

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o
codaddict
la source
63
Danger, Will Robinson! Cela ne fonctionne que si les noms des membres dans libabc.a et libxyz.a ne se chevauchent pas. Sinon, vous en écraserez un et il sera perdu.
David donné le
6
De plus, libabc.apeut contenir des objets ayant le même nom (provenant de répertoires différents) - le réassemblage ne fonctionnera pas alors!
Igor R.
16
ar -cn'a pas fonctionné pour moi (Ubuntu 14.04). J'ai ar: no operation specified. Je l'ai fait à la ar -qcplace et cela a bien fonctionné.
Max
ar t lib.a peut être utilisé pour afficher les fichiers dans la bibliothèque sans extraire réellement les fichiers.
raj_gt1
comment puis-je faire cela dans automake?
shuva
120

Il existe au moins trois façons de procéder de manière native . La première manière et la plus portable est d'utiliser libtool. Après avoir construit les autres bibliothèques également avec libtool, vous pouvez les combiner simplement en ajoutant les libs .la à une variable automake libaz_la_LIBADD, ou directement à partir d'un Makefile avec quelque chose comme:

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

Les deux autres sont au moins disponibles lors de l'utilisation de GNU ar. Vous pouvez utiliser un script MRI (nommé par exemple libaz.mri), tel que:

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

puis exécutez ar comme:

ar -M <libaz.mri

Ou vous pouvez utiliser une archive fine (option -T), qui permettra d'ajouter d'autres archives sans les imbriquer à l'intérieur, bien que l'inconvénient soit que si vous souhaitez distribuer la bibliothèque statique, l'objet détaché sera manquant:

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

Toutes les méthodes ci-dessus gèrent gracieusement les noms de membres qui se chevauchent à partir des archives d'origine.

Sinon, vous devrez décompresser dans différents répertoires et reconditionner à nouveau, pour éviter de remplacer les noms de membres qui se chevauchent:

mkdir abc; cd abc; ar -x ../libabc.a
mkdir xyz; cd xyz; ar -x ../libxyz.a
ar -qc libaz.a abc xyz
Guillem Jover
la source
19
Pour ceux qui veulent une archive normale (pas mince), une chose simple qui peut être faite est de créer une archive légère, puis de la convertir en une archive normale. Quelque chose comme: ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M. Cela crée une libaz.aarchive légère temporaire , puis convertit l'archive légère en une archive normale (vous pouvez donc la déplacer / la distribuer). Cela gère également gracieusement lorsque les noms de votre bibliothèque ont des caractères spéciaux (espacés, plus ou virgules) (ie ar cqT libbundle.a libfoo++.a 'libbar baz.a'). Mais +1 de moi!
Cornstalks
Quel est l'inconvénient du premier exemple de script IRM donné?
jb
Bonne réponse! C'est bien de voir certaines options qui ne nécessitent pas d'extraction et de réacheminement. Je pense aussi que l'idée de @Cornstalks est bonne. Peut-être faudrait-il ajouter à la réponse?
Ampoule
Hé quand j'essaye d'utiliser la commande pour libtoolque j'obtiens ces erreurs: libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' Des idées pour résoudre ce problème?
Lars Nielsen du
@Guillem @Cornstalks Excellente réponse. Que faire si l' --Wl,-whole-archiveoption est requise dans la commande de liaison d'origine pour plusieurs lib * .a, et que je dois combiner toutes les lib * .a dans one.a. Lors de la liaison à nouveau, --Wl,-whole-archivene fonctionnera pas avec one.a. Quelle est votre suggestion? stackoverflow.com/questions/56323197/…
thinkdeep
10

Si vous le faites simplement comme:

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

vous perdrez certains fichiers objets s'il y a des membres avec le même nom dans aa et ba, vous devez donc extraire les membres de différentes archives dans un dossier différent:

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

de plus, il est possible qu'il y ait plusieurs membres du même nom dans une archive (disons dans aa), si vous exécutez ar x aa , vous n'en obtiendrez qu'un pour les membres du même nom.

La seule façon d'extraire tous les membres du même nom dans une archive est de spécifier le numéro de membre par l'option '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
...

ce serait un travail fastidieux, vous devrez donc écrire un script plus sophistiqué pour faire ce travail.

Une solution facultative est que vous pouvez combiner plusieurs archives dans une bibliothèque partagée:

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

de cette façon, l'éditeur de liens gérera tout pour vous!

samuel.zzy220
la source
1
Samuel, merci. Mais lors de la combinaison dans une bibliothèque partagée, tous les objets doivent être compilés avec -fPIC.
osgx
0

Mieux encore, vous effectuez un lien partiel sur chaque bibliothèque et faites une archive des deux fichiers objets résultants. De cette façon, il fonctionne comme les bibliothèques partagées le feraient

Vous faites un lien partiel avec

gcc -r --nostdlib

donc soit au lieu de créer l'archive intermédiaire, soit après l'avoir réextrait, exécutez

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

puis

ar -cr $LIBNAME_JOINED.a $LIBNAME_A.o $LIBNAME_B.o
Allan Jensen
la source
Cela ne répond pas vraiment à la question posée - comme il a demandé des bibliothèques. Souvent, vous n'avez même pas de sources pour les bibliothèques, ou vous souhaitez les conserver préconstruites pour d'autres raisons.
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

maintenant vous avez deux versions de "macroblock-10.o"

loi wey
la source
0
ar crsT libaz.a libabc.a libxyz.a

Ici, vous créez une archive d'archives, puis vous «aplatissez» le résultat avec le drapeau T. Je ne sais pas comment cela fonctionnera avec les fichiers .o du même nom qui pourraient être contenus dans.

Evgeny Yashin
la source