2009-03-20 18 views
13

Supponiamo che io ho tre C librerie statiche dire libColor.a che dipende * libRGB. * A, che a sua volta dipende libPixel.a. La biblioteca libColor.a è detto di dipendere da biblioteca libRGB.a poiché ci sono alcuni riferimenti a libColor.a ad alcuni dei simboli definiti in libRGB.a. Come combinare tutte le librerie precedenti con un nuovo libNewColor.a che è indipendente?Combinando librerie statiche

Indipendente significa che la nuova libreria deve avere tutti i simboli definiti. Quindi durante il collegamento, devo semplicemente fornire -lNewColor. Le dimensioni della nuova biblioteca dovrebbe essere minimo vale a dire che non deve contenere i simboli in libRGB.a che non viene utilizzato da libColor.a ecc ho provato la mia fortuna utilizzando varie opzioni in ar di comando (utilizzato per creare e aggiornare librerie/archivi statici).

+0

è possibile, in alternativa guardare http: // StackOverflow. it/questions/8170450/combine-static-libraries/8170851 # 8170851 e usa libt ool – Bruce

+0

Nota che il passaggio di minimizzazione non è davvero necessario. Con le librerie statiche, il linker prenderà solo i file oggetto di cui ha bisogno, a differenza delle librerie condivise che includono tutto. Ci sono ragioni e vantaggi per ciascun approccio; sono solo diversi. E davvero non devi preoccuparti mentre lavori con le librerie statiche. –

risposta

11

1/Estrarre TUTTI i file oggetto da ciascuna libreria (utilizzando ar) e provare a compilare il codice senza le librerie o i file oggetto. Probabilmente otterrai un carico assoluto di simboli non definiti. Se non si ottengono simboli non definiti, andare al passaggio 5.

2/Prendere il primo e scoprire quale file oggetto soddisfa quel simbolo (utilizzando nm).

3/Annotare il file oggetto quindi compilare il codice, incluso il nuovo file oggetto. Si otterrà un nuovo elenco di simboli non definiti o, se non c'è nessuno, passare al punto 5.

4/Andare al punto 2.

5/Unire tutti i file oggetto nella vostra lista (se presente) in una singola libreria (sempre con ar).

Bang! Ecco qua. Prova a collegare il tuo codice senza nessuno degli oggetti, ma con la nuova libreria.

Questa intera cosa può essere automatizzata in modo relativamente semplice con uno script di shell.

+2

Unnecessariamente complicato, puoi semplicemente estrarre tutti i file .o in un grande .a, come quando alla fine è collegato a un eseguibile, il linker eliminerà comunque quelli inutilizzati – MarkR

+2

@MarkR, @AIB voleva la dimensione della * libreria * essere minimo, non la dimensione dell'eseguibile. – paxdiablo

+0

Accettandolo, anche se mi piacerebbe un oneliner che lo faccia. Come passare alcune opzioni a ld per collegare solo i simboli necessari ecc ... – AIB

5

Una libreria statica non è molto più di un archivio di alcuni file oggetto (.o). Quello che puoi fare è estrarre tutti gli oggetti nelle due librerie (usando "ar x") e quindi usare "ar" per collegarli insieme in una nuova libreria.

15

Una caratteristica poco usata della archiviatore GNU è lo script di archivio, è un'interfaccia semplice ma potente, e può fare esattamente quello che vuoi, per esempio se il seguente script si chiama script.ar:

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

allora si potrebbe invocare ar come segue:

ar -M < script.ar 

e si otterrebbe libNewColor.a che contiene tutti i file .o da libColor.a libRGB.a e libPixel.a.

Inoltre, è possibile aggiungere anche regolare.o file, nonché con il comando ADDMOD:

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

Inoltre è super facile da generare questi script in Makefiles, così io di solito creare una regola di makefile un po 'generico per la creazione di archivi che genera in realtà la sceneggiatura e invoca ar sulla script. Qualcosa di simile a questo:

$(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) 

Anche se, ora che lo guardo mi immagino che non funziona se $ (oggetti) è vuota (cioè se si desidera solo di combinare gli archivi senza l'aggiunta di file oggetto in più), ma lo farò lasciarlo come esercizio per il lettore per risolvere tale questione, se necessario ...: D

Ecco la documentazione per questa funzione:

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

+0

Questo è fantastico! Tranne che tutti i percorsi/librerie che hanno un + nel nome interrompono lo script. Per esempio openssl ha libncurses ++. A – Gregory

+0

Neat! È molto più semplice della decompressione e del repacking dei file oggetto. – Thomas

+0

Si noti che per qualche motivo -D non funziona in combinazione con -M. Quindi, se vuoi ottenere risultati deterministici, hai ancora bisogno del percorso estratto-poi-archivio. –