如何配置 Qt 以便从 Linux 到 Windows 目标进行交叉编译



我想使用 Linux x86_64 主机交叉编译 Windows x86_64 目标的 Qt 库(最终是我的应用程序)。我觉得我很接近,但我可能对这个过程的某些部分有根本的误解。

我首先在我的 Fedora 机器上安装了所有的 mingw 软件包,然后修改了 win32-g++ qmake.conf 文件以适应我的环境。但是,我似乎陷入了一些看似明显的Qt配置选项:-platform-xplatform。Qt文档说-platform应该是主机架构(你正在编译的地方),-xplatform应该是你想要部署的目标平台。就我而言,我设置了-platform linux-g++-64-xplatform linux-win32-g++其中 linux-win32-g++ 是我修改后的 win32-g++ 配置。

我的问题是,在使用这些选项执行配置后,我看到它调用了系统的编译器而不是交叉编译器(x86_64-w64-mingw32-gcc)。如果我省略-xplatform选项并将-platform设置为我的目标规范 (linux-win32-g++),它会调用交叉编译器,但在发现一些与 Unix 相关的函数未定义时出错。

这是我最新尝试的一些输出:http://pastebin.com/QCpKSNev。

问题:

  1. 当从Linux主机交叉编译像Qt for Windows这样的东西时,是否应该调用本机编译器?也就是说,在交叉编译过程中,我们不应该使用交叉编译器吗?我不明白为什么Qt的配置脚本在我指定-xplatform选项时尝试调用我的系统的本机编译器。

  2. 如果我使用的是 mingw 交叉编译器,我什么时候需要处理规范文件?GCC 的规范文件对我来说仍然是一个谜,所以我想知道这里的一些背景是否会帮助我。

  3. 一般来说,除了在我的qmake.conf中指定交叉编译器之外,我还需要考虑什么?

只需使用 M 交叉环境 (MXE)。它消除了整个过程的痛苦:

  • 得到它:

    $ git clone https://github.com/mxe/mxe.git
    
  • 安装生成依赖项

  • 构建Qt for Windows,其依赖项和交叉构建工具;在具有良好互联网接入的快速机器上,这将需要大约一个小时;下载量约为500MB:

    $ cd mxe && make qt
    
  • 转到应用的目录,并将跨构建工具添加到 PATH 环境变量:

    $ export PATH=<mxe root>/usr/bin:$PATH
    
  • 运行Qt Makefile生成器工具,然后构建:

    $ <mxe root>/usr/i686-pc-mingw32/qt/bin/qmake && make
    
  • 您应该在 ./release 目录中找到二进制文件:

    $ wine release/foo.exe
    

一些注意事项

  • 使用MXE存储库的主分支;它似乎得到了开发团队的更多喜爱。

  • 输出是一个 32 位静态二进制文件,在 64 位 Windows 上可以很好地工作。

(这是@Tshepang答案的更新,因为MXE在他的回答后已经发展了)

构建Qt

您可以使用MXE_TARGETS来控制目标机器和工具链(32位或64位),而不是使用make qt来构建Qt。MXE 开始使用 .static.shared 作为目标名称的一部分,以显示要构建的库类型。

# The following is the same as `make qt`, see explanation on default settings after the code block.
make qt MXE_TARGETS=i686-w64-mingw32.static   # MinGW-w64, 32-bit, static libs
# Other targets you can use:
make qt MXE_TARGETS=x86_64-w64-mingw32.static # MinGW-w64, 64-bit, static libs
make qt MXE_TARGETS=i686-w64-mingw32.shared   # MinGW-w64, 32-bit, shared libs
# You can even specify two targets, and they are built in one run:
# (And that's why it is MXE_TARGET**S**, not MXE_TARGET ;)
# MinGW-w64, both 32- and 64-bit, static libs
make qt MXE_TARGETS='i686-w64-mingw32.static x86_64-w64-mingw32.static'

在@Tshepang最初的回答中,他没有指定MXE_TARGETS,而是使用默认值。在他写答案的时候,默认是i686-pc-mingw32,现在是i686-w64-mingw32.static。如果将MXE_TARGETS显式设置为 i686-w64-mingw32 ,省略.static ,则会打印一条警告,因为此语法现已弃用。如果您尝试将目标设置为 i686-pc-mingw32 ,它将显示错误,因为 MXE 已删除对 MinGW.org(即 i686-pc-mingw32)的支持。

跑步qmake

当我们更改MXE_TARGETS时,<mxe root>/usr/i686-pc-mingw32/qt/bin/qmake命令将不再起作用。现在,您需要做的是:

<mxe root>/usr/<TARGET>/qt/bin/qmake
如果未

指定MXE_TARGETS ,请执行以下操作:

<mxe root>/usr/i686-w64-mingw32.static/qt/bin/qmake

更新:新的默认值现在i686-w64-mingw32.static

在Linux上交叉编译Windows软件的另一种方法是Archlinux上的MinGW-w64工具链。它易于使用和维护,并提供最新版本的编译器和许多库。我个人发现它比MXE更容易,而且它似乎更快地采用新版本的库。

首先,你需要一个基于 arch 的机器(虚拟机或 docker 容器就足够了)。它不一定是Arch Linux,衍生产品也可以。我用的是Manjaro Linux。大多数 MinGW-w64 软件包在官方 Arch 存储库中不可用,但 AUR 中有很多。Arch 的默认软件包管理器(Pacman)不支持直接从AUR安装,因此您需要安装和使用像yay或yaourt这样的AUR包装器。然后安装 MinGW-w64 版本的 Qt5 和 Boost 库非常简单:

yay -Sy mingw-w64-qt5-base mingw-w64-boost
#yaourt -Sy mingw-w64-qt5-base mingw-w64-qt5-boost #if you use yaourt

这也将安装MinGW-w64工具链(mingw-w64-gcc)和其他依赖项。交叉编译Windows(x64)的Qt项目非常简单:

x86_64-w64-mingw32-qmake-qt5
make

要部署程序,您需要从 /usr/x86_64-w64-mingw32/bin/ 复制相应的 dll。例如,通常需要将/usr/x86_64-w64-mingw32/lib/qt/plugins/platforms/qwindows.dll复制到 program.exe_dir/platforms/qwindows.dll

要获得 32 位版本,您只需要使用 i686-w64-mingw32-qmake-qt5 即可。基于 Cmake 的项目与 x86_64-w64-mingw32-cmake 一样容易。这种方法对我来说非常有效,是最容易设置、维护和扩展的。它也适用于持续集成服务。也有可用的码头工人映像。

例如,假设我想构建QNapi字幕下载器GUI。我可以通过两个步骤完成:

  1. 启动 docker 容器:
sudo docker run -it burningdaylight/mingw-arch:qt /bin/bash
  1. 克隆并编译 QNapi
git clone --recursive 'https://github.com/QNapi/qnapi.git' 
cd qnapi/ 
x86_64-w64-mingw32-qmake-qt5
make

就是这样!在许多情况下,这将是那么容易。将您自己的库添加到包存储库 (AUR) 也很简单。你需要编写一个PKBUILD文件,它尽可能直观,例如,参见mingw-w64-rapidjson。

好的,

我想我已经弄清楚了。

部分基于 https://github.com/mxe/mxe/blob/master/src/qt.mk 和 https://www.videolan.org/developers/vlc/contrib/src/qt4/rules.mak

似乎"最初"当您运行配置(使用 -xtarget 等)时,它会配置然后运行您的"主机"gcc 来构建本地二进制文件 ./bin/qmake

 ./configure -xplatform win32-g++ -device-option CROSS_COMPILE=$cross_prefix_here -nomake examples ...

然后你运行正常的"make",它为mingw构建它

  make
  make install

所以

  1. 是的

  2. 仅当您需要使用 msvcrt 以外的其他内容时.dll(其默认值)。 虽然我从未使用过其他任何东西,所以我不确定。

  3. https://stackoverflow.com/a/18792925/32453 列出了一些配置参数。

为了编译Qt,必须运行它的configure脚本,用-platform 指定主机平台(例如 -platform linux-g++-64如果您使用 g++ 编译器在 64 位 Linux 上构建)和目标-xplatform平台(例如 -xplatform win32-g++ 如果你要交叉编译到窗口)。

我还添加了此标志: -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32-它指定了我正在使用的工具链的前缀,它将在所有为 Windows 构建二进制文件的生成文件中以"gcc"或"g++"为前缀。

最后,在构建idc时可能会遇到问题,这显然是用来向Qt添加ActiveX支持的东西。您可以通过将标志-skip qtactiveqt传递给配置脚本来避免这种情况。我从这个错误报告中得到了这个:https://bugreports.qt.io/browse/QTBUG-38223

这是我使用过的整个配置命令:

    cd qt_source_directory
    mkdir my_build
    cd my_build
    ../configure 
      -release 
      -opensource 
      -no-compile-examples 
      -platform linux-g++-64 
      -xplatform win32-g++ 
      -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- 
      -skip qtactiveqt 
      -v

至于你的问题:

1 - 是的。将调用本机编译器以构建构建过程中所需的一些工具。也许像qconfig或qmake这样的东西,但我不完全确定究竟是哪些工具。

2 - 对不起。我不知道编译器上下文中的规范文件是什么=/。但据我所知,你不必处理这个问题。

3 - 您可以在配置命令行中指定交叉编译器前缀,而不是在 qmake.conf 文件中执行此操作,如上所述。idc 也存在这个问题,我也提到了它的解决方法。

最新更新