Come unire due librerie statiche "ar" in una?


90

Ho librerie Linux 2 statiche, creato da ar cr, libabc.ae libxyz.a.
Voglio unirli in una libreria statica libaz.a.
Come posso fare questo.

Voglio creare una libreria statica unita, non dare entrambe le librerie al collegamento finale delle applicazioni.


7
Vedi anche: libtoollibtool -static -o new.a old1.a old2.a
-soluzione

2
funziona perfettamente, solo un piccolo dubbio se quelle librerie hanno file.o comune (ma le funzionalità sono diverse) funzionerà ancora?
bindingofisaac

libtool -static -o new.a old1.a old2.a non funziona su linux (centos 7)
disponibile il

Risposte:


60

Puoi estrarre l'oggetto da entrambi i .afile e creare il tuo .afile utilizzando i file estratti .o:

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o

63
Pericolo, Will Robinson! Funziona solo se i nomi dei membri in libabc.a e libxyz.a non si sovrappongono. Altrimenti ne sovrascrivi uno e andrà perso.
David dato il

6
Inoltre, libabc.apuò contenere oggetti con lo stesso nome (originati da directory diverse) - il riassemblaggio non funzionerà allora!
Igor R.

16
ar -cnon ha funzionato per me (Ubuntu 14.04). Ho ar: no operation specified. ar -qcInvece l' ho fatto e ha funzionato bene.
Max

ar t lib.a può essere utilizzato per visualizzare i file nella libreria senza estrarre effettivamente i file.
raj_gt1

come posso farlo in automake?
shuva

120

Ci sono almeno tre modi per farlo in modo nativo . Il primo e più portabile modo è usare libtool. Dopo aver costruito anche le altre librerie con libtool, puoi combinarle semplicemente aggiungendo le .la libs a una variabile libaz_la_LIBADD di automake, o direttamente da un Makefile con qualcosa come:

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

Gli altri due sono almeno disponibili quando si usa GNU ar. È possibile utilizzare uno script MRI (denominato ad esempio libaz.mri), come:

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

e quindi eseguire ar come:

ar -M <libaz.mri

Oppure puoi usare un archivio sottile (opzione -T), che consentirà di aggiungere altri archivi senza averli annidati all'interno, anche se lo svantaggio è che se vuoi distribuire la libreria statica, l'oggetto scollegato mancherà:

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

Tutti i metodi precedenti gestiscono con grazia i nomi dei membri sovrapposti dagli archivi originali.

Altrimenti, dovresti decomprimere in directory diverse e reimballare nuovamente, per evitare di sostituire i nomi dei membri sovrapposti:

mkdir abc; cd abc; ar -x ../libabc.a
mkdir xyz; cd xyz; ar -x ../libxyz.a
ar -qc libaz.a abc xyz

19
Per coloro che desiderano un archivio normale (non sottile), una cosa semplice che può essere fatta è creare un archivio sottile, quindi convertirlo in un archivio normale. Qualcosa come: ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M. Questo crea un thin temporaneo libaz.ae quindi converte l'archivio thin in uno normale (in modo da poterlo spostare / distribuire). Questo gestisce anche graziosamente quando i nomi della tua libreria hanno caratteri speciali (spaziati, più o virgole) (cioè ar cqT libbundle.a libfoo++.a 'libbar baz.a'). Ma +1 da parte mia!
Steli di mais

Qual è lo svantaggio del primo esempio di script MRI fornito?
jb

Bella risposta! È bello vedere alcune opzioni che non richiedono l'estrazione e l'archiviazione. Inoltre penso che l'idea di @Cornstalks sia buona. Forse dovrebbe essere aggiunto alla risposta?
Lampadina1

Ehi, quando provo a usare il comando per libtoolottengo questi errori: libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' Qualche idea su come risolverlo?
Lars Nielsen

@Guillem @Cornstalks Ottima risposta. E se l' --Wl,-whole-archiveopzione è richiesta nel comando di collegamento originale per più lib * .a e ho bisogno di combinare tutte le lib * .a in one.a. Quando si collega di nuovo, --Wl,-whole-archivenon funzionerà con one.a. Qual è il tuo suggerimento? stackoverflow.com/questions/56323197/...
thinkdeep

10

Se lo fai semplicemente come:

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

perderai alcuni file oggetto se ci sono membri con lo stesso nome sia in aa che in ba quindi, devi estrarre membri di archivi diversi in cartelle diverse:

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

inoltre, è possibile che ci siano più membri con lo stesso nome in un archivio (diciamo in aa), se esegui ar x aa , ne otterrai solo uno per quei membri con lo stesso nome.

L'unico modo per estrarre tutti i membri con lo stesso nome in un archivio è specificare il numero del membro tramite l'opzione '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
...

questo sarebbe un lavoro noioso, quindi dovrai scrivere una sceneggiatura più sofisticata per fare quel lavoro.

Una delle soluzioni opzionali è che puoi combinare più archivi in ​​una libreria condivisa:

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

in questo modo il linker gestirà tutte le cose per te!


1
Samuel, grazie. Ma nella combinazione in una libreria condivisa, tutti gli oggetti dovrebbero essere compilati con -fPIC.
osgx

0

Ancora meglio si esegue il collegamento parziale su ciascuna libreria e si crea un archivio dei due file oggetto risultanti. In questo modo funziona come farebbero le biblioteche condivise

Fai un collegamento parziale con

gcc -r --nostdlib

quindi o invece di creare l'archivio intermedio o dopo averlo riestratto, esegui

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

poi

ar -cr $LIBNAME_JOINED.a $LIBNAME_A.o $LIBNAME_B.o

Non sta davvero rispondendo alla domanda posta - come ha chiesto le biblioteche. Molte volte non si dispone nemmeno di fonti per le librerie fornite, o si desidera mantenerle precostruite per altri motivi.
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

ora hai due versioni di "macroblock-10.o"


0
ar crsT libaz.a libabc.a libxyz.a

Qui, crei un archivio di archivi e poi 'appiattisci' (assottigliamento) il risultato con il flag T. Non sono sicuro di come funzionerà con file .o con lo stesso nome che potrebbero essere contenuti all'interno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.