2016-08-11 55 views
0

假設我有兩個編譯器,或者甚至是具有兩個不同選項集的單個編譯器。每個編譯器都會將一些C代碼編譯成一個對象,然後嘗試將這兩個.o文件與一個通用鏈接器進行鏈接。這會成功嗎?鏈接來自不同C編譯器的目標文件

我最初的想法是:並非總是如此。如果編譯器使用相同的目標文件格式並具有兼容的選項,那麼它會成功。但是,如果編譯器有衝突的選項,或者(而且這很容易)使用兩種不同的目標文件格式,它將無法正常工作。

有沒有人有更多的見解呢?目標文件需要遵守什麼標準才能獲得這種工作的信心?

+2

大多數不是Windows的平臺將這些東西標準化。 – fuz

+1

相關:[在Solaris上,使用gcc編譯的庫可以使用與使用cc生成的庫相同的方式使用](http://stackoverflow.com/questions/38260829/on-solaris-are-libraries-compiled-with-gcc-可用同一種方式爲庫存基因) –

+1

我想你說過你自己。我相信如果目標文件具有相同的[ABI](https://en.wikipedia.org/wiki/Application_binary_interface),那麼它們將會很好地一起玩,但我沒有任何關於你在說什麼的直接經驗,所以可能會有一些其他的怪癖。 – yano

回答

1

* nix操作系統的絕大多數版本都有明確的定義和開放的ABI,並且大多使用ELF目標文件格式,所以它對於* nix根本不是問題。

Windows並不嚴格定義,不同的編譯器在某些調用約定中可能會有所不同(例如,某些編譯器可能不支持__fastcall,或者可能有不同的行爲,請參閱https://en.wikipedia.org/wiki/X86_calling_conventions)。但是主要的調用約定(__stdcall,_cdecl等)足夠標準以確保由另一個編譯器的編譯器編譯的函數的成功調用,否則程序根本無法工作,因爲與Linux中的每個系統調用都不同通過你需要成功調用的DLL的函數。

另一個問題是目標文件沒有標準的通用格式。儘管大多數工具(MS,Intel,GCC(MinGW),Clang)使用COFF格式,但有些可能使用OMF(Watcom)或ELF(TinyC)。

另一個問題是所謂的「名稱改變」。雖然它被引入來支持用相同的名稱重載C++函數,但它被C編譯器採用,以防止用不同調用約定定義的函數的鏈接。例如,函數int _cdecl fun(void);將獲得編譯名_fun,而int __stdcall fun(void);將獲得名稱_fun @ 0。更多關於名稱混合的信息,請看這裏:https://en.wikipedia.org/wiki/Name_mangling

最後,對於某些編譯器,默認行爲可能會有所不同,所以是的,選項可能會阻止成功鏈接由不同編譯器或甚至由相同編譯器生成的目標文件。例如,TinyC使用默認約定_cdecl,而CLang使用__stdcall。使用默認選項的TinyC可能不會生成可能與其他鏈接的代碼,因爲它不會通過下劃線標記預先命名。爲了使其交叉鏈接,它需要-fleading-下劃線選項。

但是請記住上面所說的代碼可能會成功混合。例如,我成功地將由Visual Studio,Intel Parallel Studio,GCC(MinGW),Clang,TinyC,NASM生成的代碼鏈接在一起。

相關問題