2013-10-09 13 views
7

Ho un pezzo banale di codice C++ che sembra qualcosa di simile:Perché GNU ld risolve i simboli in modo diverso quando si collegano gli eseguibili e gli oggetti condivisi?

#include <boost/timer/timer.hpp> 

int main(void) { 
    boost::timer::auto_cpu_timer t; 
    return 0; 
} 

ho provato a compilare e collegarlo (con gcc 4.8.1 e GNU ld 2.23.52.20130828) come segue:

$ g++ -o test test.cc -lboost_timer 
/usr/bin/ld: /tmp/cc2jP1jv.o: undefined reference to symbol '_ZN5boost6system15system_categoryEv' 
/usr/lib/libboost_system.so.1.54.0: error adding symbols: DSO missing from command line 
collect2: error: ld returned 1 exit status 

Una soluzione è di menzionare esplicitamente -lboost_system sulla riga di comando, e questo funziona. Tuttavia, posso anche fare:

$ g++ -Wl,--copy-dt-needed-entries -o test test.cc -lboost_timer 

Secondo la documentazione ld "con le librerie dinamiche --copy-dt-necessario-voci menzionate nella riga di comando sarà ricorsivamente cercato, seguendo le loro tag DT_NEEDED ad altre biblioteche, per risolvere i simboli richiesti dal binario di output ", quindi tutto questo ha senso: ld sta cercando di capire da boost_timer che deve anche collegarsi a boost_system per risolvere tutti i simboli.

Tuttavia, mi sono reso conto che questo funziona anche:

$ g++ -fPIC -shared -o test test.cc -lboost_timer 

Ovviamente, ora ho generato un oggetto condiviso, piuttosto che un file eseguibile. A quanto pare, però, ld è stato in grado di capire che aveva bisogno di collegare l'oggetto condiviso contro boost_system:

$ ldd test | grep boost_system 
     libboost_system.so.1.54.0 => /usr/lib/libboost_system.so.1.54.0 (0x00007f385246e000) 

Quindi la mia domanda è questa: perché risoluzione simbolo diverso quando si costruisce un oggetto condiviso rispetto a un file eseguibile? In che modo è possibile capire che il mio oggetto condiviso dovrebbe essere collegato a boost_system senza la mia specifica --copy-dt-needed-entries?

+0

Hai provato con '-shared -z defs'? –

+0

@CharlesBailey L'aggiunta di '-z defs' alla build condivisa lo fa interrompere (' test.cc :(.testo + 0x85): riferimento non definito a 'boost :: system :: generic_category()' '). Guardando '-z defs' mi ha indicato anche' - [no-] allow-shlib-undefined' e questo potrebbe effettivamente spiegare cosa sta succedendo ... grazie per il puntatore! – user2862505

risposta

5

La risposta diretta alla mia domanda è nell'opzione --[no-]allow-shlib-undefined di ld, credo. Dalla pagina man:

Il comportamento predefinito è quello di segnalare errori per eventuali simboli indefiniti riferimento in librerie condivise se il linker viene utilizzato per creare un eseguibile, ma per consentire loro se il linker viene utilizzato per crea una libreria condivisa.

Pertanto, quando costruire con -shared, i simboli in boost_system sono indefinito, ma il comportamento predefinito di ld non è di prendersi cura. Esso può essere detto per la cura:

$ g++ -fPIC -shared -Wl,--no-allow-shlib-undefined -o test test.cc -lboost_timer 
/usr/bin/ld: /tmp/cc6j1de3.o: undefined reference to symbol '_ZN5boost6system15system_categoryEv' 
/usr/lib/libboost_system.so.1.54.0: error adding symbols: DSO missing from command line 
collect2: error: ld returned 1 exit status 

Allo stesso modo, siamo in grado di dire che non prendersi cura quando si costruisce un eseguibile:

$ g++ -Wl,--allow-shlib-undefined -o test test.cc -lboost_timer 
/tmp/ccUHoCIU.o: In function `__static_initialization_and_destruction_0(int, int)': 
test.cc:(.text+0x7a): undefined reference to `boost::system::generic_category()' 
test.cc:(.text+0x86): undefined reference to `boost::system::generic_category()' 
test.cc:(.text+0x92): undefined reference to `boost::system::system_category()' 
collect2: error: ld returned 1 exit status 

Ma la creazione di binario non riesce senza essere in grado di definire quei simboli.

Grazie a @CharlesBailey per avermi indicato nella giusta direzione!

0

Ci sono differenze nel comando collect2 che possono essere rilevanti. I diversi comandi vengono confrontati a http://imgur.com/eMr2tY2. Il lato destro crea la libreria condivisa (-fPic -shared), la sinistra è la normale compilazione.

+0

questa forse una domanda fuori tema. Ma la tua immagine diff sembra interessante. puoi per favore facci sapere dove hai trovato lo strumento diff? – earthdan

Problemi correlati