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
?
Hai provato con '-shared -z defs'? –
@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