MinGW、MinGW-W64和MSVC(VC++)在交叉编译中的区别

7
让我们这样说:我们将创建一个需要跨平台的库,并选择GCC作为编译器,在Linux上它的运行效果非常好,我们需要在Windows上编译它,而MinGW可以胜任这项工作。
MinGW试图实现一种本地方式在Windows上编译C++,但它不支持一些功能,比如mutexthreads
我们有MinGW-W64,它是MinGW的一个分支,支持这些功能,我想知道,应该使用哪一个?考虑到GCC是最常用的C++编译器之一。还是在Windows上使用MSVC(VC++),在Linux上使用GCC,并使用CMake来处理独立的编译器?
提前感谢您的帮助。

1
我更喜欢GCC mingw-w64,这样我就不需要另一台机器/操作系统,但我不知道大多数人是倾向于哪一种。 - Mooing Duck
1
很多因素将影响决策(答案可能是您必须为Windows生成多个库)。该库仅为DLL吗?它只会导出C可链接对象吗?用户是否希望或需要使用它与他们选择的编译器一起使用(无论是MSVC的几个版本还是MinGW)? - Michael Burr
1
分叉发生的原因往往千差万别,这是使用自由开源软件时必须要面对的问题,你需要自行选择如何处理。最重要的是先以实用为主。 - Hans Passant
4个回答

10

个人而言,我更喜欢基于MinGW的解决方案,可以在Linux上进行交叉编译,因为有很多平台无关的库在Windows上几乎不可能(或非常麻烦)构建。(例如那些使用./configure脚本设置其构建环境的库。)但是,即使在Linux上,交叉编译所有这些库及其依赖也是很烦人的,如果您必须自己进行./configuremake。这就是MXE的用武之地。

从评论中看来,您好像担心依赖项。当进行交叉编译时,如果您必须逐个交叉编译每个库,则在构建环境设置方面会很耗费成本。但是有MXE可用。它构建了一个交叉编译器和大量平台无关的库(如boost、QT和许多不太重要的库)。使用MXE,boost作为解决方案变得更加具有吸引力。我已经使用MXE构建了一个依赖于Qt、boost和libexiv2的项目,几乎没有遇到问题。

使用MXE编译Boost线程

首先安装mxe:

git clone -b master https://github.com/mxe/mxe.git

然后构建您想要的软件包(gccboost):

make gcc boost

C++11 threads with MXE

If you want to use C++11 threads with MXE, it is possible but requires a two-stage compilation of gcc.

Firstly, check out the master (development) branch of mxe (this is the normal way to install it):

git clone -b master https://github.com/mxe/mxe.git

然后无需修改即可构建gccwinpthreads:

make gcc winpthreads

现在,编辑 mxe/src/gcc.mk 文件。找到以 $(PKG)_DEPS := 开头的行,在该行末尾添加 winpthreads。然后查找 --enable-threads=win32 并将其替换为 --enable-threads=posix

现在,重新编译 gcc,享受 C++11 线程吧。

make gcc
注意: 默认配置支持使用WINAPI而不是POSIX PTHREADS的Win32线程。但GCC的libstdc++库,该库实现了std::threadstd::mutex,没有代码使用WINAPI线程,因此它们添加了一个预处理器块,当启用Win32线程时,从库中剥离std::threadstd::mutex。通过使用--enable-threads=posix和winpthreads库,而不是让GCC尝试在其库中与Win32进行接口,因为它并没有完全支持,我们让winpthreads充当胶水代码,为GCC提供正常的pthread接口,并使用WINAPI函数来实现pthread库。

最后说明

您可以通过向make命令添加-jmJOBS=n来加快这些编译速度。其中-jm,其中m是一个数字,表示同时构建m个包。JOBS=n,其中n是一个数字,表示使用n进程分别构建每个软件包。因此,实际上它们相乘,因此只选择mn,使得m*n 不超过您拥有的处理器核心数量。例如,如果您有8个内核,则m=3n=4就可以了。

引用

http://blog.worldofcoding.com/2014_05_01_archive.html#windows


实际上,在Windows中使用MSVC编译已编译可执行文件与手动逐行重写库代码进行编译相比,是否存在任何性能缺陷?我需要使用大量汇编优化和C内部函数的高性能代码。但是它无法在Windows上编译。这里有一个例子:https://github.com/quantcast/qfs/blob/master/src/cc/qcrs/prim.h - Brian Cannard
1
它可能是可交叉编译的,但我不知道如何交叉编译使用cmake的项目。只要您在编译器中使用正确的选项(例如-march),交叉编译的可执行文件与本地编译的一样好。您应该了解如何使用mxe交叉编译cmake项目,并可能在SO上提出新问题。 - Tyler
2021年有任何更新吗? - Sergey Kolesnik

7
如果您想要可移植性,可以使用标准的方式 - C++11的库。
如果无法使用C++11,则pthread可能是解决方法,尽管VC++无法编译它。
您不想同时使用这两个选项吗?那么,只需编写自己的线程抽象层。例如,您可以编写class Thread,如下所示。
class Thread
{
public:
   explicit Thread(int (*pf)(void *arg));
   void run(void *arg);
   int join();
   void detach();
   ...

然后,编写您想要支持的每个平台的实现。例如,
+src
|---thread.h
|--+win
|--|---thread.cpp
|--+linux
|--|---thread.cpp

在此之后,配置您的构建脚本以在Windows上编译win/thread.cpp,并在Linux上编译linux/thread.cpp

我不使用C++11的<thread>,因为MinGW不支持它,但感谢您的想法,很有趣,我会尝试一下。 - SH.0x90
不幸的是,它并没有(即使在4.8.1上也是如此)。 - SH.0x90
确切地说,这仅适用于MinGW-W64,并且正如我在问题中所说的那样,MinGW-W64是MinGW的一个分支,我想知道是否支持它并实现那些功能以使用MinGW-W64编译不会使事情变糟。 - SH.0x90
@SH.0x90 哦,我明白了...那么,如果你不使用VC++,我认为pthread是一个好的解决方案。 - ikh
2
这取决于编译gcc时启用的线程模型。默认情况下,mingw使用win32线程模型,该模型不受libstdc++(gcc的标准库)支持,因此std::thread被禁用。使用winpthreads和POSIX线程模型,它可以使用std::thread。即使对于gcc 4.9也是如此。有关更多信息,请参见我的答案。 - Tyler
显示剩余3条评论

1

你应该一定要使用Boost。它非常好用,可以完成所有的任务。

如果你不想使用Boost.Thread不支持的某些同步原语(例如std::async),请查看Boost库。当然,这是额外的依赖关系,但如果你不害怕这个,你将享受Boost的所有优势,如交叉编译。

了解Boost.Thread和C++11线程之间的差异在这里


Boost看起来很不错,但我真的不喜欢像你说的那样有额外的依赖关系,不过还是谢谢。 - SH.0x90

0

我认为这是一个相当通用的考虑因素列表,当你需要选择多平台工具或工具集时,其中很多你可能已经有了答案;

  • 工具支持,如果出现问题,您将从谁那里获得支持; 社区和供应商的实力如何?
  • 本地目标支持,工具对目标平台的理解程度如何?
  • 优化潜力?
  • 库支持(现在和中期未来)?
  • 平台SDK支持,如果需要?
  • 构建工具(虽然没有直接问到这里,但它们是否适用于两个平台; 大多数流行的工具都适用)。

我看到的一件事似乎并没有真正处理;

目标应用程序期望什么?

您提到正在构建一个库,那么将使用它的应用程序是什么,那个应用程序期望什么。

这里的限制是目标应用程序决定了系统最基本的方面,即用于构建它的工具。 应用程序将如何使用库;

  • 该应用程序需要哪些API以及何种类型的API?
  • 您想提供什么类型的API(C风格、C++类或组合)?
  • 它使用的运行时是什么,将是相同的还是会有冲突?

考虑到这些因素,以及可能的事实是目标应用程序仍然未知;尽可能保持灵活性。在这种情况下,努力与gccmingw-w64msvc保持兼容性。它们都提供广泛的C++11语言支持(确实,有些比其他人更多),并且通常受到其他流行库的支持(即使现在不需要这些其他库)。

我认为Hans Passant的评论...

先做有效的事情

... 真的适用于这里。

既然你提到了它,mingw-builds 可以为 mingw-w64 提供支持 thread等功能,使用Windows的 posix 构建,同时支持 64位32位


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接