分发使用 MinGW g++ 编译的程序

Distribute a program compiled with MinGW g++

假设我使用 MinGW 64(g++ 编译器)创建并编译了一个简单的程序。 运行 这个程序在我的电脑上,并在 Process Explorer 中查找程序正在使用的 DLL 文件,我发现(以及许多其他):

libgcc_s_seh-1.dll
libstdc++6.dll
libwinpthread-1.dll

我的 MinGW 安装文件夹下只有这些。使用的其余 DLL 文件位于 C:\Windows.

问题一:

MinGW DLL 文件是 MinGW C++ 运行时间库(可以这么说)吗?它们的用途是否与例如 msvcrXXX.dll(XXX = Microsoft 运行 时间库的版本)相同。

问题二:

如果我想 运行 在另一台没有安装 MinGW 的计算机上安装应用程序,包含上面列出的那些 DLL 文件(即将它们放在与我的可执行文件相同的文件夹中)是否足够在另一台计算机上安装 运行(我们假设另一台计算机也是 64 位 Windows 机器)。如果是,这是否意味着我们基本上将 MinGW C++ 运行time 与我们的可执行文件一起发布。如果不是,为什么?

libstdc++6.dll 就是你说的C++标准库。

libwinpthread-1.dll 用于 C++11 线程支持。 MinGW-W64 有两种可能的线程变体:要么使用像 CreateThread 这样的本机 Windows 函数,但是那时像 std::thread 这样的 C++11 东西将不可用;或包含此库并使用 C++11 类(也)。
请注意,要切换线程模型,您需要重新安装 MinGW。仅删除 DLL 而不使用 C++11 的东西是行不通的,尽管如此,您当前的安装仍需要 DLL。

libgcc_s_seh-1.dll 是关于 C++ 异常处理的。

是的,交付 DLL 也应该足够了
(或使用静态链接并仅提供您的程序文件)。

分发编译软件有几个主要挑战:

  1. 为所有目标处理器编译代码(请记住,在编译代码时,您需要为每种类型的指令集架构生成单独的downloads/distributions)。

  2. 确保构建可重现、一致,并且可以轻松地与特定版本的代码(以及依赖项的版本)相关联。

  3. 确保构建输出是自包含的,并在其中包含它的所有依赖项(这样它就不会依赖于恰好存在于您的系统上的任何其他安装)。

  4. 确保定期构建和分发代码,自动分发更新,以便在出现安全问题时推出新的修补版本。

为了方便和扩大覆盖范围,不熟练的用户最好有一个他们可以安装的预构建版本。但是,我建议首先共享源代码。

这些要求中的大多数都相当不容易满足,并且通常不仅需要自动化构建过程,还需要自动化应该在其中进行构建的 VM 的实例化/配置。但是,有些开源项目可以提供帮助...例如,查看 Gitian.

就要点 #3 而言,这里的关键是使用静态链接...虽然这确实会使您分发的二进制文件更大(因为它的依赖项现在已包含在输出中),但它也使您的二进制文件与系统上的库版本隔离(避免 "dependency hell")。

第 4 点非常棘手,但值得庆幸的是,这里也有开源工具可以提供帮助,例如 cloudup,它提供了一种向应用程序分发添加自动更新功能的方法。

对于您不确定需要包含哪些 DLL 文件来分发您的应用程序的复杂项目,我制作了一个方便的花花公子 Bash 脚本(用于 MSYS2 shell),它可以告诉您确切的 DLL您需要包含的文件。它依赖于 Dependency Walker 二进制文件。

#!/usr/bin/sh

depends_bin="depends.exe"
target="./build/main.exe" # Or wherever your binary is
temp_file=$(mktemp)
output="dll_list.txt"

MSYS2_ARG_CONV_EXCL="*" `cygpath -w $depends_bin` /c /oc:`cygpath -w $temp_file` `cygpath -w $target`
cat $temp_file | cut -d , -f 2 | grep mingw32 > $output

rm $temp_file

请注意,此脚本需要稍微修改才能用于常规 MSYS(特别是 MSYS2_ARG_CONV_EXCL 和 cygpath 指令)。此脚本还假定您的 MinGW DLL 文件位于包含 MinGW 的路径中。

您甚至可以使用此脚本自动将有问题的 DLL 文件复制到您的构建目录中,作为自动部署系统的一部分。

您可能希望将选项 -static-libgcc-static-libstdc++ 静态添加到 link C 和 C++ 标准库,从而无需携带这些文件的任何单独副本。

我使用 ntldd 来获取依赖项列表。 https://github.com/LRN/ntldd 我正在使用 msys2,所以我只是用 pacman 安装了它。使用它,然后复制所有需要的依赖项