C:使用 MinGW-w64 静态/动态 Link 的正确方法

C: Correct Way to Statically / Dynamically Link with MinGW-w64

直观上:

我发现了什么:

不幸的是,我无法从 MinGW 和 MinGW-w64 中找到明确的文档来说明 dynamically/statically linking 库时什么是对的,什么是错的。

根据我的经验,我总是能够动态地 link 到 .dlls。曾经,我能够静态地 link 到 .lib(使用 -static 标志)。

问题:

使用 MinGW-w64 GCC 工具链编译时,.dll / .a 二进制文件是否适合动态和静态 link 库?也就是说,为MSVC生成动态库,为GCC生成静态库?

答案:

MinGW / MinGW-w64 的 GCC's linker ld can 端口:

  • 直接link到.dlls动态linking
  • 间接 link 到 .dll.as 动态 linking(在编译时使用导入库)
  • link 到 .as 静态 linking.

为什么 MinGW / MinGW-w64 的 GCC link 端口要查找 .dll

简而言之,最佳答案是因为 .dll 是 Microsoft 对其 32 位和 64 位操作系统上的共享对象的回答。在Windows上,MinGW / MinGW-w64的port使用Microsoft C运行time(msvcrt.dll)[1],所以服从WindowsOSlinker 规则。

Dynamic-link library (or DLL) is Microsoft's implementation of the shared library concept in the Microsoft Windows and OS/2 operating systems. -- From Wikipedia

因此,对于动态 link 库,您将使用文件扩展名:

  1. .so 用于 Linux 上的共享库,因为这是 GCC binutils 的 linker 搜索的内容,
  2. .dll 用于 Windows 上的共享库,因为这是 GCC binutils 的 MinGW / MinGW-w64 端口 linker 搜索的内容。

GCC 的 MinGW 端口用于共享库对象的扩展在源代码的 cygming 文件中明确列出。正如@ChronoKitsune 评论的那样,具体来说:libgcc/config/i386/t-slibgcc-cygming 中的 SHLIB_EXT = .dllcygming 文件(用于 Cygwin 和 MinGW)对于 MinGW、MinGW-w64 以及 32 位和 64 位版本的 Cygwin 都是通用的。因此,对于 Windows.

的 GCC binutils 的所有端口都是如此

为什么 MinGW / MinGW-w64 linker 处理 .lib 那么?

原则上,GCC binutils 的 linker 不会将 .lib 识别为静态库。但是,linker 可能足够聪明,可以 link 对抗 .lib 导入的 .dll(如果 .lib 实际上是导入库)。例如,如果库具有动态 linked 的依赖项,则该库将被动态 linked(和 flags to "force" static linking will be ignored)。

在这种情况下,我想 linker 不会抛出任何错误,而且看起来 .lib 实际上 linked 成功了。

导入库如何工作? (赠品)

在 Windows 上,.lib 可以是以下两个库之一:

  1. 编译器从 .dll 生成的 import 库,其中包含编译期间符号解析所需的所有定义(但是,函数实现被忽略)[2]
    1. 如果您尝试使用 MinGW/MinGW-w64 的 GCC binutils 端口为 xxxx.dll 生成导入库,它将生成 libxxxx.dll.a。扩展文件扩展名对于区分 import 库和完全定义的 static 库很有用。使用 MSVC 编译时,此 distinction isn't apparent in the extension
  2. 一个完全定义的静态库

.libs 有双重用途,因为正如@ChronoKitsune 评论的那样,MSVC linker 不直接 link 反对 .dlls。相反,需要一个导入库来在编译时解析符号定义,这样 .dll 直到 运行-time:

才会加载

An import library (.LIB files) to link with. (The linker creates the import library when the DLL is built.) -- VS 2015 Documentation

为什么 MinGW/MinGW-w64 的 GCC linker 端口寻找 .a

这很简单——端口利用了在 *-nix 系统上使用的 ar 归档实用程序,正如@ChronoKitsune 评论的那样:

The extension for static libraries comes from the ar (archive) program included with binutils. You can use ar -t libxxx.a to list the object files contained within any static library.

这类似于 MSVC 的 lib 命令,lib /list foo.lib 此命令将 return 如果 .lib.obj 文件列表一个静态库。