Como mesclar duas bibliotecas estáticas “ar” em uma?

92

Eu tenho bibliotecas Linux 2 estáticos, criado por ar cr, libabc.ae libxyz.a.
Quero mesclá-los em uma biblioteca estática libaz.a.
Como posso fazer isso.

Eu quero criar uma biblioteca estática mesclada, não dar as duas bibliotecas ao link final dos aplicativos.

osgx
fonte
8
Consulte também: libtoolsolução baseada em :libtool -static -o new.a old1.a old2.a
osgx
2
funciona perfeitamente, só uma pequena dúvida se essas bibliotecas têm arquivo comum. (mas em termos de funcionalidade são diferentes) ainda vai funcionar?
bindingofisaac
libtool -static -o new.a old1.a old2.a não funciona no linux (centos 7)
desocupado em

Respostas:

62

Você pode extrair o objeto de ambos os .aarquivos e criar seu .aarquivo usando os .os extraídos :

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o
codadicto
fonte
66
Perigo, Will Robinson! Isso funciona apenas se os nomes dos membros em libabc.a e libxyz.a não se sobrepõem. Caso contrário, você sobrescreverá um e ele será perdido.
David Dado
7
Além disso, libabc.apode conter objetos com o mesmo nome (originados de diferentes diretórios) - a remontagem não funcionará!
Igor R.
17
ar -cnão funcionou para mim (Ubuntu 14.04). Eu tenho ar: no operation specified. Eu fiz em ar -qcvez disso e funcionou bem.
Máx.
ar t lib.a pode ser usado para visualizar os arquivos na biblioteca sem realmente extrair os arquivos.
raj_gt1
como posso fazer isso no automake?
shuva
126

Existem pelo menos três maneiras de fazer isso nativamente . A primeira e mais portável maneira é usar libtool. Depois de ter construído as outras bibliotecas também com libtool, você pode combiná-las apenas adicionando as libs .la a uma variável libaz_la_LIBADD automake, ou diretamente de um Makefile com algo como:

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

Os outros dois estão pelo menos disponíveis ao usar o GNU ar. Você pode usar um script de MRI (denominado, por exemplo, libaz.mri), como:

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

e, em seguida, execute ar como:

ar -M <libaz.mri

Ou você pode usar um arquivo fino (opção -T), que permitirá adicionar outros arquivos sem colocá-los aninhados dentro, embora a desvantagem seja que se você quiser distribuir a biblioteca estática, o objeto separado ficará ausente:

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

Todos os métodos acima lidam perfeitamente com nomes de membros sobrepostos dos arquivos originais.

Caso contrário, você teria que desempacotar em diretórios diferentes e empacotar novamente, para evitar a substituição de nomes de membros sobrepostos:

mkdir abc; cd abc; ar -x ../libabc.a
mkdir xyz; cd xyz; ar -x ../libxyz.a
ar -qc libaz.a abc xyz
Guillem Jover
fonte
19
Para aqueles que desejam um arquivo normal (não thin), uma coisa simples que pode ser feita é criar um arquivo thin e depois convertê-lo em um arquivo normal. Algo como: ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M. Isso cria um thin temporário libaz.ae, em seguida, converte o arquivo thin em um normal (para que você possa movê-lo / distribuí-lo). Isso também funciona perfeitamente quando os nomes de sua biblioteca têm caracteres especiais (espaçados, sinais de mais ou vírgulas) (ou seja ar cqT libbundle.a libfoo++.a 'libbar baz.a'). Mas 1 de mim!
Cornstalks de
Qual é a desvantagem do primeiro exemplo de script de ressonância magnética dado?
jb
Boa resposta! É bom ver algumas opções que não requerem a extração e reaquecimento. Também acho que a ideia do @Cornstalks é boa. Talvez deva ser adicionado à resposta?
Lightbulb1,
Ei, quando tento usar o comando para libtool, recebo estes erros: libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' Alguma ideia de como consertar isso?
Lars Nielsen
@Guillem @Cornstalks Ótima resposta. E se a --Wl,-whole-archiveopção for exigida no comando de vinculação original para vários lib * .a, e eu precisar combinar todos os lib * .a em one.a. Ao vincular novamente, --Wl,-whole-archivenão funcionará com one.a. Qual é a sua sugestão? stackoverflow.com/questions/56323197/…
thinkdeep
10

Se você simplesmente fizer isso:

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

você perderá alguns arquivos de objeto se houver membros com o mesmo nome em aa e ba, portanto, você precisa extrair membros de arquivos diferentes para pastas diferentes:

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

além disso, é possível que haja vários membros com o mesmo nome em um arquivo (digamos em aa), se você executar ar x aa , obterá apenas um para aqueles membros com o mesmo nome.

A única maneira de extrair todos os membros do mesmo nome em um arquivo é especificar o número do membro pela opção '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
...

isso seria um trabalho tedioso, então você terá que escrever um script mais sofisticado para fazer esse trabalho.

Uma solução opcional é que você pode combinar vários arquivos em uma biblioteca compartilhada:

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

assim, o vinculador tratará de tudo para você!

samuel.zzy220
fonte
1
Samuel, obrigado. Mas ao combinar em uma biblioteca compartilhada, todos os objetos devem ser compilados -fPIC.
osgx
0

Melhor ainda, você executa a vinculação parcial em cada biblioteca e eles fazem um arquivo dos dois arquivos objeto resultantes. Dessa forma, ele funciona como bibliotecas compartilhadas

Você faz ligação parcial com

gcc -r --nostdlib

então, em vez de fazer o arquivo intermediário ou depois de extraí-lo, execute

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

então

ar -cr $LIBNAME_JOINED.a $LIBNAME_A.o $LIBNAME_B.o
Allan Jensen
fonte
Não é realmente responder a perguntas feitas - como ele pediu bibliotecas. Muitas vezes você nem mesmo tem fontes para bibliotecas fornecidas, ou deseja mantê-las pré-construídas por outros motivos.
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

agora você tem duas versões do "macroblock-10.o"

lei bem
fonte
0
ar crsT libaz.a libabc.a libxyz.a

Aqui, você cria o arquivo de arquivos e, em seguida, 'aplaina' (dilui) o resultado com a bandeira T. Não tenho certeza de como funcionará com o mesmo nome de arquivos .o que podem estar contidos nele.

Evgeny Yashin
fonte