使用MSYS2编译C++ Windows exe独立文件

问题描述 投票:0回答:3

我最近开始使用Msys2安装gcc编译器来为Windows制作一些exe。它工作得很好,但是将我的 exe 传递给我的兄弟时出现了问题。他的笔记本电脑没有安装 msys2,当他尝试运行我的 exe 时,会发生一些错误。似乎使用我的 exe 需要几个 dll 文件(如 msys-2.0.dll)。

我发现 msys2 使用这些文件来“伪造”机器上的操作系统,假装它是 POSIX 操作系统。有没有办法用 msys2 为 Windows 编译独立的 exe?我希望我的兄弟能够在不安装 msys 或其他程序的情况下使用我的 exe。

以下是所有详细信息,以便更好地了解我的情况:

  1. g++ HelloWord.cpp -o Helloword
    是我用来编译的行
  2. C:\msys64\mingw64\bin
    这是g++存储的路径
  3. 双击生成的 exe 文件后,我从 Windows 收到的所有确切错误消息。请注意,这些消息不会出现在 CMD 上,而是出现在经典的 Windows 错误弹出窗口中:
  • 程序无法启动,因为您的计算机缺少 msys-2.0.dll。 尝试重新安装程序来解决此问题。
  • 程序无法启动,因为您的计算机缺少 libstdc++-6.dll。 尝试重新安装程序来解决此问题。
  • 程序无法启动,因为您的计算机缺少 libgcc_s_seh-1.dll。 尝试重新安装程序来解决此问题。

已修复: 我仅使用 g++ 参数

-static
解决了该问题。是不是太过分了?

c++ compilation msys2
3个回答
4
投票

我的MinGW版本有点旧...

C:\example>where g++
  C:\misc\mingw810_64\bin\g++.exe

C:\example>g++ --version
g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

但同样的想法:

C:\example>cat > compile_me.cpp
#include <iostream>
int main () { std::cout << "hi" << std::endl; }
^Z

C:\example>g++ compile_me.cpp -o compiled.exe

C:\example>compiled.exe
hi

C:\example>dumpbin /dependents compiled.exe

  ...

  Image has the following dependencies:

    KERNEL32.dll
    msvcrt.dll
    libstdc++-6.dll
  
  ...

在这种情况下(动态链接的 stdlib),您可以使用可执行文件部署 libstdc++6.dll,将其安装到与 exe 相同的路径(另外两个通常存在于 Windows 系统路径中)。

如果您想删除该依赖项,请使用

-static
:

C:\example>g++ compile_me.cpp -o compiled.exe -static

C:\example>compiled.exe
hi

C:\example>dumpbin /dependents compiled.exe

  ...

  Image has the following dependencies:

    KERNEL32.dll
    msvcrt.dll

  ...

单独部署 .exe 应该没问题。

文件大小会更大,但现在这不是什么大问题。另外,您的 MinGW / MSYS 安装可能会附带条带:

C:\example>dir compiled.exe
 Volume in drive C is Windows
 Volume Serial Number is D2BA-C6F0

 Directory of C:\example

09/24/2022  06:49 PM         2,389,120 compiled.exe
               1 File(s)      2,389,120 bytes
               0 Dir(s)  135,945,314,304 bytes free

C:\example>strip compiled.exe

C:\example>dir compiled.exe
 Volume in drive C is Windows
 Volume Serial Number is D2BA-C6F0

 Directory of C:\example

09/24/2022  07:03 PM           838,656 compiled.exe
               1 File(s)        838,656 bytes
               0 Dir(s)  135,944,765,440 bytes free

C:\example>compiled.exe
hi

如果您的特定可执行文件最终依赖于其他动态库,并且供应商选择不提供静态链接的替代方案,那么您必须使用 exe 来部署它们。通常很容易将所有内容放入 zip 文件中或使用您最喜欢的可编写脚本的安装程序。

(注意:dumpbin 随 Visual Studio 一起提供;并且可以在 vs 安装路径中 VC\Tools 中的某些适当的子目录中找到)。


4
投票

OP 已经解决了他们的问题,但对于发现此问题的其他人来说:

  1. 确保通过单击
    mingw64.exe
    或等效快捷方式启动 MSYS2。
  2. 运行
    which g++
    以确保您正在使用
    /mingw64/bin/g++
    。 如果显示其他
    g++
    ,则运行
    pacman -S mingw-w64-x86_64-toolchain
    安装工具链。
  3. 使用
    g++
    编译代码并使用
    -static
    选项。
  4. 运行
    ntldd yourprogram.exe
    检查您的程序正在使用哪些 DLL,并确保它们是 Windows 的一部分,而不是 MSYS2 的一部分。

编辑:如今,使用 MSYS2 的 UCRT64 环境而不是 MINGW64 可能更有意义。 不过我还没试过。 如果您想支持真正旧的 32 位 Windows 机器,请使用 MINGW32。


1
投票

MSYS2 编译本机 PE32 可执行文件。它不依赖于任何神奇的 msys 环境或静态链接。

为自己准备一个依赖项遍历器,看看您的应用程序需要运行哪些 DLL。任何不在 Windows 子目录中的内容都应该是您重点关注的地方。另请确保您的应用程序不需要任何特殊的 Microsoft 可再发行依赖项。

最终,您应该为应用程序创建一个安装程序来处理依赖项。我个人喜欢 Inno 设置,但还有很多其他设置也很受欢迎。

© www.soinside.com 2019 - 2024. All rights reserved.