2011-01-24 12 views
5

Il mio progetto consiste in un paio di librerie statiche, che sono collegate insieme in un passaggio finale. Ora ho il problema, che il link order of the library is important (altrimenti ottengo un errore del linker di un simbolo non definito). A volte mi imbatto nel problema, che devo riordinare le librerie collegate (-lcommon -lsetup -lcontrol etc). Al momento è una stupida prova ed errore: riordinare, compilare, controllare l'errore, riordinare, compilare e così via.Come determinare le dipendenze tra biblioteche?

Così ho scritto un piccolo programma per mostrarmi le interdipendenze tra le librerie e mi ha generato l'ordine delle librerie da collegare. Legge nei simboli definiti ('T', 'B', ecc.) E indefiniti ('U') da nm e rimuove lo weak symbols ('w', 'W', 'v' e 'V') dal ' elenco di simboli non definiti '. Ora determina per ogni simbolo indefinito la libreria che lo risolve.

Ma il mio programma mostra dipendenze circolari ... qual è il mio errore?

Se esistono davvero, non potrei collegarmi affatto ... quindi cosa mi è mancato, analizzando l'uscita nm? O sta analizzando l'output nm non nel modo, per ottenere queste dipendenze?

libcommon.a: 
     U _ZN15HardwareUnit23GetHardwareSerialNumberEv 
libhardware.a: 
00000484 T _ZN15HardwareUnit23GetHardwareSerialNumberEv 
libsecurityaccess.a: 
     U _ZN15HardwareUnit23GetHardwareSerialNumberEv 
--- 
libhardware.a: 
     U _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString 
libsecurityaccess.a: 
00004020 T _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString 
     U _ZN21ApplicationProfile26GetApplicationSettingsPathERK7QString 

risposta

6

Un'altra opzione per collegare librerie con dipendenze circolari consiste nell'utilizzare un'opzione di linker speciale per questo. Man ld:

-(archives -) 
    --start-group archives --end-group 
     The archives should be a list of archive files. They may be either 
     explicit file names, or -l options. 

     The specified archives are searched repeatedly until no new 
     undefined references are created. Normally, an archive is searched 
     only once in the order that it is specified on the command line. 
     If a symbol in that archive is needed to resolve an undefined 
     symbol referred to by an object in an archive that appears later on 
     the command line, the linker would not be able to resolve that 
     reference. By grouping the archives, they all be searched 
     repeatedly until all possible references are resolved. 

     Using this option has a significant performance cost. It is best 
     to use it only when there are unavoidable circular references 
     between two or more archives. 

È sempre più pulito eliminare le dipendenze circolari.

+0

C'è un modo per determinare quali "dipendenze circolari" interromperanno la compilazione e quali no? – Charly

+0

Il linker ti dice i nomi dei simboli che non è riuscito a risolvere. –

+0

Sì, questo è il modo in cui lo sto facendo ora (quando non si utilizza l'opzione 'gruppo' - che funziona alla grande, THX !!). Compilo, riordina la lista della biblioteca e corro nel successivo errore del linker. Se sarei in grado di calcolare anticipatamente le dipendenze, creerò l'ordine della libreria prima della compilazione e non dovrò farlo tramite tentativi ed errori. (Al momento ci sono circa 20 librerie e ognuna ha dipendenze da altri moduli) – Charly

2

Se avete veramente una catena dipendenza circolare di librerie statiche (e questo non è chiaro dal vostro incolla; si mostrano solo una dipendenza non circolare), ci sono due opzioni:

  1. Rimuovere la dipendenza circolare in qualche modo; per esempio, puoi assicurarti che libcommon non faccia riferimento a simboli in libpthardware.
  2. Estrarre i singoli file .o dalla libreria .a e collegarli direttamente. Quindi l'ordine di collegamento non ha più importanza.

Nel caso di 2., potrebbe essere utile utilizzare il collegamento parziale piuttosto che creare librerie statiche. Su sistemi che utilizzano GNU bintools, questo può essere fatto invocando qualcosa come:

ld -r -o libfoo.o foo.o bar.o 

L'effetto di questo è di combinare foo.o e bar.o in un unico file .o. L'ordine non ha importanza. È quindi sufficiente fare riferimento a libfoo.o come normale file oggetto nel passaggio del collegamento finale.

Nota che ciò può fare interfere with the linker's ability to discard unreferenced portions of the static library (normalmente questo viene fatto a livello di file .o all'interno di .a, credo). Se stai usando tutte o la maggior parte di queste librerie, probabilmente non è un problema. Tuttavia, se la memoria del codice è un problema, è consigliabile esaminare automatically discarding unused code at the function level. Se lo fai, passa --gc-sections e -s solo allo stadio di collegamento finale (ed evita di farlo se hai bisogno di eseguire il debug!). Inoltre, il collegamento statico con le librerie di sistema non sembra essere necessario con il moderno gcc.

+0

Grazie mille. Questo potrebbe risolvere il sintomo - ma alla fine sarei interessato alle dipendenze tra le librerie. Perché l'output nm mi mostra una dipendenza circolare, ma il collegamento ha avuto successo ?? – Charly

+0

Non sono sicuro - nella mia sperimentazione, ho trovato che determinati ordini di librerie con una dipendenza circolare sono collegati correttamente, ma non sono sicuro del perché.Ho letto la tua domanda chiedendo come affrontare la situazione, ma se sei più interessato a sapere perché è successo, ti suggerirei di costruire un caso di test minimale (dovrebbe essere abbastanza banale) e di presentare una domanda chiedendo esplicitamente perché ha successo . – bdonlan

Problemi correlati