2011-12-27 9 views
12

Sto cercando di collegare un modulo C++ utilizzando GCC, in sostanza, in questo modo:L'ordine del collegamento GCC è cambiato?

gcc -c hello.c 
g++ -c world.cpp 
gcc -ohello -lstdc++ hello.o world.o 

Nota che uso -lstdc++ di collegare il modulo C++, in modo che posso usare al posto di gccg++. Il problema è che sto ottenendo l'errore:

undefined reference to `operator new(unsigned long)' 

(Supponendo che world.cpp contiene almeno una chiamata al new.)

Questo errore è stato risolto se metto -lstdc++ alla fine della linea di linker , in questo modo:

gcc -ohello hello.o world.o -lstdc++ 

sono consapevole che questa domanda è stato chiesto molte volte qui, ma ho un requisito speciale. Non sto chiamando direttamente GCC. Sto usando un sistema di compilazione per un linguaggio di programmazione diverso (Mercury) che chiama GCC per mio conto e non posso modificare facilmente il modo in cui chiama GCC (anche se posso specificare librerie aggiuntive usando la variabile di ambiente LDFLAGS). Così ho due ulteriori requisiti:

  • non è possibile usare g++ di collegare (solo gcc) - è per questo che sto facendo la -lstdc++ trucco sopra piuttosto che semplicemente il collegamento con g++).
  • Non penso di poter controllare l'ordine dei comandi del linker - Mercury metterà i file .o nella riga di comando dopo le di qualsiasi libreria.

Capisco la ragione fondamentale per cui l'ordine è importante, ma quello che mi è sconcertante è il motivo per cui è nata questa pausa ora? Ho appena aggiornato a Ubuntu 11.10/GCC 4.6.1. Ho compilato con successo questo programma per anni usando esattamente la tecnica di cui sopra (mettendo prima -lstdc++). Solo ora arriva questo errore. Un programma estraneo ai miei collegamenti con OpenGL usando -lgl e che si è rotto anche quando ho aggiornato e ho dovuto spostare -lgl alla fine della riga di comando. Probabilmente scoprirò che dozzine dei miei programmi non sono più compilabili. Perché questo cambiamento? C'è qualcosa di sbagliato nel mio nuovo sistema o è così com'è ora? Si noti che queste sono ordinarie librerie condivise, non collegate staticamente.

C'è qualcosa che posso fare per far tornare GCC alla vecchia maniera, dove l'ordine delle librerie non ha importanza? C'è un altro modo in cui posso convincere GCC a collegare correttamente libstdc++ senza spostarlo dopo i file .o sulla riga di comando?

risposta

12

Se Mercury mette i file oggetto dopo le librerie, Mercurio è rotto. Le librerie appartengono ai file oggetto - sempre. A volte potresti farla franca con l'ordine inverso, ma non in modo affidabile. (Le librerie statiche devono andare dopo i file oggetto che fanno riferimento ai simboli nella libreria statica.A volte, un linker noterà i simboli definiti da una libreria condivisa anche quando non viene utilizzato nessuno dei simboli, a volte il linker noterà solo i simboli della libreria condivisa se la libreria condivisa fornisce almeno un simbolo.)

+3

Quindi in sostanza questa "regressione" è solo che per tutta la mia carriera di sviluppo, ho fatto affidamento sul fatto che "ha funzionato accidentalmente" e ora ha smesso di funzionare? Sembra un cambiamento piuttosto importante - ho messo le librerie prima di file oggetto per la maggior parte di un decennio ora perché non avevo idea che questo fosse un problema :(Grazie per il consiglio.Sembra che Mercury non abbia messo gli oggetti dopo le librerie, ma che ci siano delle dipendenze più complesse all'interno del mio comando LDFLAGS. Sto facendo progressi, quindi ti darò un segno di spunta. Grazie. – mgiuca

+1

Ipotesi non dimostrata: potrebbe esserci stato un cambiamento in 'ld' che influisce su di te. L'obiettivo potrebbe essere evitare di caricare librerie condivise non utilizzate. Se si utilizzano librerie statiche, si ottiene solo il materiale necessario. In passato, se si elencava una libreria condivisa sulla linea di collegamento, questa veniva caricata in fase di esecuzione, anche se la libreria non forniva alcun simbolo. Il caricamento della libreria solo se soddisfa almeno un simbolo può ridurre il tempo di avvio del programma. Ma significa anche che se l'unico simbolo in sospeso quando viene scansionata la libreria è 'main()', la libreria non verrà caricata. –

+0

Vedere commenti su '--as-needed' per la versione 2.20 di' ld' nelle [NEWS] (http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/src/ld/NEWS? rev = 1.121 & content-type = testo/plain & cvsroot = src & only_with_tag = binutils-binutils-2_22) file. Vedi anche [manual] (http://sourceware.org/binutils/docs-2.22/ld/Options.html#Options) e '--copy-dt-needed-entries' e' --no-copy- opzioni dt-needed-entries'. La precedente ipotesi _unproven_ è almeno in parte provata, credo. –

Problemi correlati