2013-06-02 66 views
3

根據gcc ABI策略,gcc 4.4.7應該依賴於libstdC++ 6.0.13。據我瞭解,編譯器版本和的libstdC++版本深深地相互關聯的,不能進行互換,所以它來找我作爲一個驚喜地發現了以下事實:CentOS 5.8與gcc 4.4.7鏈接反對libstdC++ 6.0.8。這怎麼可能?

  • 的CentOS 5.8某種程度上設法有gcc44包,即反對6.0.8的鏈接,顯然是用默認系統(它是基於gcc-4.1.2)
  • 那libstdC++。so在編譯目錄(/ usr/lib/gcc/x86_64-redhat- linux6E/4.4.7,其中我期望找到一個libstdC++ - 6.0.13)不是鏈接到任何類型的共享對象,而是一個包含文本文件的文本文件INPUT (-lstdc++_nonshared /usr/lib64/libstdc++.so.6)

這是怎麼回事?

具體做法是:

  • 怎麼能他們提供了一個GCC 4.4.7,對舊版本的libstdC++聯繫?我認爲這是不可能的。
  • 什麼是stdC++ _非共享庫?
  • 我不知道.so文件可能包含該文本。誰來分析它(動態鏈接器我猜),它的規範和結果是什麼?
  • 這種魔法能走多遠?我可以在libstdC++ 6.0.3中使用gcc4.7嗎?什麼是兼容性的光譜
+0

編譯器依賴標準庫,通過生成對特定命名函數的調用,例如,當在獨立gcc環境中使用purr虛函數時,可能會產生對'__cxa_pure_virtual'的未定義引用,這幾乎是函數稱爲,每當一個非重載的純虛函數被調用時,也就是純函數的默認函數。 – Skeen

+0

對於memcpy等,編譯器有很多這樣的例外情況。這就是編譯器如何依賴標準庫。只要標準庫包含編譯器期望的所有函數,那麼在鏈接時就不會有未定義的引用,並且它將「有效」。因此很有可能,不建議混合編譯器和庫版本。 – Skeen

+0

至於stdC++ _noshared,我的猜測是,這是一個庫的靜態鏈接版本,這意味着所有需要的東西都將在編譯時被包含,而不是在運行時動態鏈接到動態鏈接器。 – Skeen

回答

9

什麼樣的魔術在這裏?

這主要是ELF符號版本控制的魔力。我已經看到了這個最好的參考就是How to Write Shared Libraries由烏利齊·德雷珀,特別是第3節

他們怎麼能提供GCC 4.4.7,對舊版本的libstdC++鏈接?我認爲這是不可能的。

libstdC++開發人員注意ABI兼容性。這使得查看兩個不同版本的libstdC++之間引入的新符號變得相當簡單。

查看libstdC++的ABI compatibility page,可以看到GCC 4.1的libstdC++具有GLIBCXX_3.4.8,並且GCC 4.4的庫存(FSF版本)具有GLIBCXX_3.4.13。然後可以查看libstdc++ version scripts以查看在這兩個版本之間添加了哪些符號。

查看符號版本的更經驗性的途徑是使用像readelf這樣的工具。例如。我的Ubuntu系統上readelf --dyn-syms --wide /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | c++filt這樣表示輸出(只是一對夫婦的選擇稍短的線):

223: 000000000006dbe0 2121 FUNC GLOBAL DEFAULT 12 std::ios_base::Init::Init()@@GLIBCXX_3.4 
... 
226: 00000000002ed920  1 OBJECT GLOBAL DEFAULT 27 std::[email protected]@GLIBCXX_3.4.11 

注意符號版本在符號名稱的末尾,在@@後。

什麼是stdC++ _非共享庫?

加入從上面的段落點,STDC++ _非共享是包含這將是股價的libstdC++。so.6.0.13但不是在的libstdC++。so.6.0.8符號靜態庫。

我不知道.so文件可能包含該文本。誰來分析它(動態鏈接器我猜),它的規範和結果是什麼?

常規鏈接器解析這個,而不是運行時鏈接程序。請參閱INPUT in a linker script的binutils文檔。因此,與這個特殊的libstdC++。so.6.0.13鏈接將導致鏈接器動態鏈接到libstdC++。so.6.0.8,並靜態鏈接到包含額外符號的庫。

這樣做的不足之處在於,以這種方式編譯的應用程序將比僅與包含所有必要符號的庫存libstdC++。so.6.0.13動態鏈接的應用程序相比稍微更臃腫。好處在於新標準庫中的功能可以用於舊系統的標準安裝,無需獨立軟件供應商需要發佈自己的libstdC++副本。

這種魔法能走多遠?我可以在libstdC++ 6.0.3中使用gcc4.7嗎?兼容性

現在的你知道神奇的是什麼譜是什麼,也許你可以明白,這個版本的GCC 4.4你僅僅是CentOS 5的(當然,原本的Red Hat 5)做了一個特殊版本。因此,可能你可以創建一個GCC 4.7,它將產生只需要libstdC++ 6.0.3的二進制文件,但它需要修補你的GCC樹以將正確的符號放入stdC++ _ nonshared.a中的工作量非常小。您至少可以查看gcc44 RPM的來源,以瞭解Red Hat如何在那裏做到這一點。

紅帽似乎繼續這種方法與他們的Red Hat Developer Toolset。在撰寫本文時,GCC 4.8.1是最新的編譯器,它可以爲EL5構建二進制文件,它仍然只需要在目標系統上安裝libstdC++。so.6.0.8。對於希望用C++ 11編寫的開發人員來說,這非常好,但需要能夠部署在EL5或EL6上。

相關問題