2017-04-09 43 views
2

直觀:C:正確的方式來靜態/動態鏈接使用MinGW-W64

  • 的MinGW-W64是GNU編譯器工具(GCC等)的Windows端口。
  • 對Windows預編譯的二進制文件是.dll(動態鏈接)/ .lib(靜態鏈接)。
  • 然而,MinGW的-W64使用GNU編譯工具,它會按照所需.so/.a二進制文件。

我找到了什麼:

不幸的是,我無法找到的MinGW &的MinGW-W64,說什麼是對,什麼是錯了,當動態/靜態鏈接庫明確的文檔。

根據我的經驗,我一直能夠動態鏈接到.dll秒。有一次,我能夠靜態鏈接到一個.lib(使用-static標誌)。

問:

是否合適.dll/.a二進制動態和靜態鏈接庫與MinGW的-W64 GCC工具鏈編譯時?換句話說,爲MSC生成的動態庫和爲GCC生成的靜態庫?

+0

這是令人驚訝的是它的工作,給予[這個郵件列表的問題(https://sourceforge.net/p/mingw-w64/wiki2/Answer%2064%20bit%20MSVC-generated%20x64%20.lib/) 。此外,對於MinGW目標上的GCC,您有.a的存檔庫(如Linux)和.dll的動態庫(如Windows)。 –

+0

[/ dll文件的來源以及鏈接器如何使用它們(使用瀏覽器的查找文本功能查找_direct linking_)](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/ Using_ld_the_GNU_Linker/win32.html) –

+0

儘管命名,MinGW-w64默認編譯爲32位。 (您可以在安裝程序中手動選擇它的64位版本。)根據我的經驗,MinGW-w64或多或少像MinGW一樣工作。 – HolyBlackCat

回答

2

的答案:

GCC's linker ld can

的MinGW/MinGW的-W64的端口:

  • 直接鏈接到.dll S代表的動態鏈接
  • 間接鏈接到.dll.a S表示動態鏈接(使用導入在編譯庫)
  • 鏈接.a S表示靜態鏈接。

爲什麼GCC的鏈接查找.dll的MinGW的/ MinGW的-W64的端口?

總之,最好的答案是因爲這是.dll是微軟對32位和64位操作系統上的共享對象的回答。在Windows上,MinGW/MinGW-w64的端口使用Microsoft C運行時(msvcrt.dll[1],因此它遵從Windows操作系統鏈接器規則。

動態鏈接庫(或DLL)是Microsoft在Microsoft Windows和OS/2操作系統中共享庫概念的實現。 - From Wikipedia

因此,動態鏈接庫文件,將使用文件擴展名:

  1. .so對Linux共享庫,因爲這是海灣合作委員會的binutils'連接器搜索,
  2. .dll用於Windows上的共享庫,因爲這是GCC binutils鏈接程序的MinGW/MinGW-w64端口搜索的內容。

GCC的MinGW端口用於共享庫對象的擴展名明確列在源代碼中的cygming文件中。正如@ChronoKitsune所評論的那樣:SHLIB_EXT = .dlllibgcc/config/i386/t-slibgcc-cygming。對於MinGW,MinGW-w64以及Cygwin的32位和64位版本,cygming文件(用於Cygwin和MinGW)是很常見的。因此,GCC binutils到Windows的所有端口都是如此。

爲什麼MinGW/MinGW-w64連接器會處理.lib呢?

原則上,GCC binutils的鏈接程序不會將.lib識別爲靜態庫。但是,鏈接器可能足夠聰明,可以鏈接到.dll,即.lib導入(在.lib實際上是導入庫的情況下)。例如,如果庫具有動態鏈接的依賴關係,則庫將動態鏈接(和flags to "force" static linking will be ignored)。

在這種情況下,我會想象鏈接器不會拋出任何錯誤,它會顯示好像.lib實際上鍊接成功。

導入庫如何工作? (贈品)

在Windows上,.lib可以是兩個庫之一:

  1. 編譯期間通過與符號解析所有需要定義一個.dll編譯器生成的進口庫(然而,功能實現都離開了)[2]
    1. 如果試圖生成與海灣合作委員會的binutils MinGW的/ MinGW的-W64的端口xxxx.dll導入庫,它會產生一個libxxxx.dll.a。擴展文件擴展名對於區分從完全定義的靜態庫到庫的區別導入庫是有用的。當MSVC編譯,這distinction isn't apparent in the extension
  2. 一個完全自定義的靜態庫

.lib發球雙重目的,因爲作爲@ChronoKitsune評論,MSVC的鏈接器並不直接針對.dll s的鏈路。相反,導入庫需要在編譯解決符號定義,從而使.dll不加載,直到運行時:

導入庫(.lib文件)與鏈接。 (鏈接器創建時,DLL是建立在導入庫。) - VS 2015 Documentation

爲什麼GCC的鏈接查找.a的MinGW的/ MinGW的-W64的端口?

這很簡單 - 端口使用是在* -nix系統中使用的ar歸檔工具,因爲@ChronoKitsune評論:

擴展對於靜態庫,來自ar(存檔)程序包含在binutils中。您可以使用ar -t libxxx.a列出任何靜態庫中包含的對象文件。

這是類似於MSVC的lib命令,lib /list foo.lib此命令將返回內如果.lib是一個靜態庫的.obj文件列表。