2011-12-27 67 views
12

我試圖鏈接使用GCC一個C++模塊,基本上是這樣的:GCC鏈接順序改變了嗎?

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

請注意,我用-lstdc++在C++模塊鏈接,這樣我就可以使用gcc而不是g++。問題是,我得到的錯誤:

undefined reference to `operator new(unsigned long)' 

(假設world.cpp包含至少一個呼叫new

如果我把-lstdc++在連接線的末端此錯誤是固定的,像這樣:

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

我知道這個問題在這裏已經被問過很多次了,但是我有一個特殊的要求。我不是直接調用GCC。我正在使用不同的編程語言(Mercury)的構建系統,它以我的名義調用GCC,並且我無法輕鬆修改它調用GCC的方式(儘管我可以使用LDFLAGS環境變量指定其他庫)。所以,我有兩個附加條件:

  • 我不能用g++鏈接(只gcc) - 這就是爲什麼我做了-lstdc++伎倆以上,而不是簡單地用g++連接)。
  • 我不認爲我可以控制鏈接器命令的順序 - 水星將把任何庫中的.o文件放在命令行

我理解的根本原因的順序很重要,但什麼是莫名其妙我現在爲什麼這樣做休息?我剛更新到Ubuntu 11.10/GCC 4.6.1。我已經使用上述技術成功地編譯了這個程序多年(首先將-lstdc++放入)。現在只有這個錯誤出現了。一個與我的OpenGL無關的程序,使用-lgl,當我升級時我的程序也崩潰了,我必須將-lgl移動到命令行的末尾。我可能會發現我的幾十個程序不再編譯。爲什麼這個改變?我的新系統有什麼問題,或者是現在的方式?請注意,這些是普通的共享庫,不是靜態鏈接的。

有沒有什麼我可以做GCC回到舊的方式,圖書館的順序並不重要?有沒有其他方法可以說服GCC正確鏈接libstdc++,而不必在命令行上的.o文件之後移動它?

回答

12

如果Mercury在庫之後放置目標文件,水星就會壞掉。庫之後屬於對象文件 - 始終。您有時可能會違背相反的順序,但不可靠。 (靜態庫必須在引用靜態庫中的符號的目標文件之後,有時,即使沒有使用任何符號,鏈接器也會記錄由共享庫定義的符號;有時,鏈接器僅會記錄共享庫符號如果共享庫至少提供一個符號)。

+3

所以基本上這個「迴歸」就是對於我整個開發生涯來說,我一直依賴於它「意外工作」而現在已停止工作的事實?看起來像一個非常重大的變化 - 我已經在目標文件之前在十年的較好時間內部署庫,因爲我不知道這是一個問題:(感謝您的建議。看起來問題不是Mercury在庫之後放置對象,而是在我的LDFLAGS命令中存在更復雜的依賴關係。我正在取得進展,所以我會給你打個招呼。謝謝。 – mgiuca 2011-12-27 02:41:23

+1

未經證實的假設:'ld'可能會影響到你。目標可能是避免加載未使用的共享庫。如果你使用靜態庫,你只會得到你需要的東西。過去的情況是,如果您在鏈接行上列出了共享庫,它將在運行時加載,即使庫沒有提供任何符號。只有在滿足至少一個符號的情況下加載庫才能減少程序的啓動時間。但這也意味着,如果掃描庫時唯一出現的符號是'main()',那麼庫將不會被加載。 – 2011-12-27 02:55:03

+0

在[NEWS](http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/src/ld/NEWS?)上查看'ld'版本2.20的'--as-needed'的註釋? rev = 1.121&content-type = text/plain&cvsroot = src&only_with_tag = binutils-binutils-2_22)文件。另請參閱[手冊](http://sourceware.org/binutils/docs-2.22/ld/Options.html#Options)以及'--copy-dt-needed-entries'和'--no-copy- dt-needed-entries'選項。我相信,先前的未證實的假設至少在某種程度上得到了證實。 – 2011-12-27 03:17:11