C:使用MinGW-w64进行静态/动态链接的正确方法

时间:2017-04-09 20:31:28

标签: windows gcc dynamic-linking mingw-w64

直观地:

  • MinGW-w64是GNU编译器工具(GCC等)的Windows端口。
  • Windows的预编译二进制文件是.dll(动态链接)/ .lib(静态链接)。
  • 但是,MinGW-w64使用GNU编译器工具,因此需要.so / .a二进制文件。

我发现了什么:

不幸的是,我无法找到MinGW& MinGW-w64在动态/静态链接库时说明了什么是对的,什么是错的。

根据我的经验,我始终能够动态链接到.dll。有一次,我能够静态链接到.lib(使用-static标志)。

问题:

在使用MinGW-w64 GCC工具链进行编译时,.dll / .a二进制文件是否适合动态和静态地链接库?换句话说,为MSVC生成的动态库和为GCC生成的静态库?

1 个答案:

答案 0 :(得分:6)

答案:

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

  • 直接链接到.dll以进行动态链接
  • 间接链接到.dll.a以进行动态链接(在编译时使用导入库)
  • 链接到.a以进行静态链接。

为什么MinGW / MinGW-w64的GCC链接器端口会查找.dll

简而言之,最好的答案是因为.dll是微软对其32位和64位操作系统上共享对象的回答。在Windows上,MinGW / MinGW-w64的端口使用Microsoft C运行时(msvcrt.dll[1],因此它遵循Windows操作系统链接器规则。

  

动态链接库(或DLL)是Microsoft在Microsoft Windows和OS / 2操作系统中实现的共享库概念。 - From Wikipedia

因此,要动态链接库,您将使用文件扩展名:

  1. .so用于Linux上的共享库,因为这是GCC binutils的链接器搜索的内容,
  2. .dll用于Windows上的共享库,因为这是GCC binutils链接器搜索的MinGW / MinGW-w64端口。
  3. GCC的MinGW端口用于共享库对象的扩展名明确列在源代码的cygming文件中。正如@ChronoKitsune评论的那样,特别是libgcc/config/i386/t-slibgcc-cygming中的SHLIB_EXT = .dllcygming文件(对于Cygwin和MinGW)对于MinGW,MinGW-w64以及Cygwin的32位和64位版本都是通用的。因此,对于Windows的GCC binutils的所有端口都是如此。

    为什么MinGW / MinGW-w64链接器会处理.lib呢?

    原则上,GCC binutils的链接器不会将.lib识别为静态库。但是,链接器可能足够智能,可以链接.dll进行.lib导入(在.lib实际上是导入库的情况下)。例如,在库具有动态链接的依赖项的情况下,库将动态链接(和flags to "force" static linking will be ignored)。

    在这种情况下,我认为链接器不会抛出任何错误,看起来似乎.lib实际上已成功链接。

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

    在Windows上,.lib可以是两个库中的一个:

    1. 编译器从.dll生成的 import 库,其中包含编译期间符号解析所需的所有定义(但是,功能实现被省略)[2]
      1. 如果您尝试使用MinGW / MinGW-w64的GCC binutils端口为xxxx.dll生成导入库,它将生成libxxxx.dll.a。扩展文件扩展名对于区分导入库和完全定义的静态库非常有用。使用MSVC进行编译时,此distinction isn't apparent in the extension
    2. 完全定义的静态库
    3. .lib用于双重目的,因为@ChronoKitsune评论说,MSVC链接器不直接链接.dll。相反,在编译时需要导入库来解析符号定义,因此在运行时之前不会加载.dll

        

      要链接的导入库(.LIB文件)。 (链接器在构建DLL时创建导入库。) - VS 2015 Documentation

      为什么MinGW / MinGW-w64的GCC链接器端口会查找.a

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

        

      静态库的扩展来自binutils附带的ar(存档)程序。您可以使用ar -t libxxx.a列出任何静态库中包含的目标文件。

      这类似于MSVC的lib命令,lib /list foo.lib如果.obj是静态库,则此命令将返回.lib文件列表。