2011-04-12 39 views
2

我知道MINGW-g ++編譯較大的可執行文件是因爲它靜態地鏈接了很多東西。另一方面,MSVC++與VCRedist包中的DLL動態鏈接,這就是爲什麼它產生更小的可執行文件的原因。是否可以使用MINGW g ++生成小型可執行文件?

但是,是否有可能使用g ++以類似的方式在Windows上編譯?不一定是MINGW-g ++,但是我可以使用Qt Creator(我沒有添加Qt作爲標籤,因爲它與問題無關)。

回答

6

MinGW完全能夠動態鏈接到msvcrt運行時。你沒有擺脫這種方式唯一的混亂是GCC/MinGW啓動代碼,這不是很大。一個小型的C++測試程序(簡單的iostream hello世界程序,注意:我得到了與普通C printf版本相同的結果)。

#include <iostream> 

using namespace std; 

int main() 
{ 
cout << "Hello World!" << endl; 
return 0; 
} 

COMMANDLINES:

g++ main.cpp -MD -Os -s -o test.exe 
cl /MD /Os main.cpp /link /out:test2.exe 

可執行文件大小:

GCC:13KB

MSVC:6KB

這雖然是雙,所有必要的啓動代碼賬戶對於大的差異;對於較大的程序,差異可以忽略不計。

+0

是否使-MD開關與VC運行時鏈接? – 2011-04-12 12:28:33

+2

MinGW始終鏈接到VC運行時(C:\ Windows \ System32中的msvcrt.dll)。 '-MD'與MSVC的'/ MD'完全相同。我認爲你誤解了MinGW的功能:它像Visual Studio編譯器一樣構建本地可執行文件,但使用GNU工具鏈。因此,兩者之間不存在一小部分代碼,但所有這些都始終隱藏在用戶之外。此外,C++ ABI有點不同(和G ++的libstdC++,而不是MS的G ++鏈接相比,C庫在兩種情況下都是相同的),但是總結了差異。 – rubenvb 2011-04-12 13:47:04

+0

你試過剝離二進制文件嗎? – matejk 2011-04-12 22:06:08

1

您可以使用cygwin(www.cygwin.com)。他們使用非常像MSVCRT的運行時DLL。然後你的程序依賴於cygwin運行時,當然(類比重言式,對不起)。

2

爲了使用靜態鏈接對VC++和MinGW進行公平的比較,我建議在上面的命令行語法中刪除編譯器開關/ MD。這將導致Visual C++編譯器與靜態庫靜態鏈接,但Visual C++編譯器將生成比MinGW靜態編譯的可執行文件小得多的可執行文件。

因爲Visual C++編譯器使用的鏈接器有一個稱爲功能級鏈接的功能,所以鏈接器只根據代碼中使用的函數鏈接必要的庫。任何未引用或未使用的函數都不會鏈接到生成的最終可執行文件,從而導致更小的靜態鏈接二進制文件。

再回到上面的例子中使用Visual C++編譯器,這個時候,使用靜態鏈接,命令行語法是:/out:test2.exe

CL /輸出的main.cpp /鏈路

您可以在這裏注意到我已經刪除了/ MD開關,以便編譯器將使用靜態鏈接而不是動態鏈接。

現在,爲了使更小的靜態鏈接的可執行文件,我建議在命令行語法:

CL /牛年的main.cpp /鏈接/ FILEALIGN:512/OPT:REF/OPT:ICF /增量:NO /out:test2.exe

如果您檢查生成的二進制文件,您會發現它更小,這又是一個靜態鏈接的可執行文件。

事實上,我從這個網站上的討論,這個想法在http://www.catch22.net/tuts/minexe

大多數的Pascal編譯器,包括德爾福也有相同的連接特性,它被稱爲智能鏈接,但所產生的靜態鏈接的可執行文件小得多的那些由Visual C++編譯器生成。

MinGW使用的鏈接器非常愚蠢,它膨脹並不知道,因此它鏈接了許多靜態庫,包括那些包含函數或例程的源代碼中未使用的函數或例程,導致非常臃腫的靜態鏈接二進制文件。

我會建議轉儲MinGW並改用Visual C++編譯器。即使MinGW的開發者似乎也不關心使用靜態鏈接來減少代碼膨脹。

+0

MinGW中是否有鏈接器的替代品?我想留在g ++中,因爲我開發的大多數應用程序都是交叉編譯到Linux和Windows。如果我在這兩個平臺上使用g ++,它是相對無痛的。 – 2011-10-26 13:59:10

+0

對於替代品,我試圖在此時搜索谷歌,現在,我還沒有找到任何合適的答案。既然你真的想在沒有任何代碼膨脹的情況下繼續使用g ++,我建議你爲這個編譯器使用動態鏈接,並且在你的應用程序中包含必要的DLL或庫,如果你希望將它部署到其他機器上,以避免依賴問題Windows環境中的DLL地獄。 – NEL 2011-10-26 14:26:02

+0

如果您將在Linux中開發您的應用程序,那麼隨附的gcc和g ++編譯器會默認使用動態鏈接,並且據我所知,大多數Linux發行版爲您開發的應用程序提供了所有必需的運行時庫,因此,如果您想要將其部署到使用Linux的其他計算機上,則無需擔心必須將運行時庫包含在應用程序中。 – NEL 2011-10-26 14:33:23

相關問題