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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10934683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 06:42:19  来源:igfitidea点击:

How do I configure Qt for cross-compilation from Linux to Windows target?

linuxqtmingwcross-compiling

提问by Mr. Shickadance

I want to cross compile the Qt libraries (and eventually my application) for a Windows x86_64 target using a Linux x86_64 host machine. I feel like I am close, but I may have a fundamental misunderstanding of some parts of this process.

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

I began by installing all the mingw packages on my Fedora machine and then modifying the win32-g++qmake.conf file to fit my environment. However, I seem to be getting stuck with some seemingly obvious configure options for Qt: -platformand -xplatform. Qt documentation says that -platformshould be the host machine architecture (where you are compiling) and -xplatformshould be the target platform for which you wish to deploy. In my case, I set -platform linux-g++-64and -xplatform linux-win32-g++where linux-win32-g++ is my modified win32-g++ configuration.

我首先在我的 Fedora 机器上安装所有 mingw 包,然后修改win32-g++qmake.conf 文件以适应我的环境。但是,我似乎被一些看似明显的 Qt 配置选项卡住了:-platform-xplatform. Qt 文档说这-platform应该是主机架构(您正在编译的地方)并且-xplatform应该是您希望部署的目标平台。在我的情况下,我设置-platform linux-g++-64-xplatform linux-win32-g++其中的linux-Win32的克++是我的改性Win32的克++结构。

My problem is that, after executing configure with these options, I see that it invokes my system's compiler instead of the cross compiler (x86_64-w64-mingw32-gcc). If I omit the -xplatformoption and set -platformto my target spec (linux-win32-g++), it invokes the cross compiler but then errors when it finds some Unix related functions aren't defined.

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

Here is some output from my latest attempt: http://pastebin.com/QCpKSNev.

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

Questions:

问题:

  1. When cross-compiling something like Qt for Windows from a Linux host, should the native compiler everbe invoked? That is, during a cross compilation process, shouldn't we use onlythe cross compiler? I don't see why Qt's configure script tries to invoke my system's native compiler when I specify the -xplatformoption.

  2. If I'm using a mingw cross-compiler, when will I have to deal with a specs file? Spec files for GCC are still sort of a mystery to me, so I am wondering if some background here will help me.

  3. In general, beyond specifying a cross compiler in my qmake.conf, what else might I need to consider?

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

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

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

采纳答案by tshepang

Just use M cross environment (MXE). It takes the pain out of the whole process:

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

  • Get it:

    $ git clone https://github.com/mxe/mxe.git
    
  • Install build dependencies

  • Build Qt for Windows, its dependencies, and the cross-build tools; this will take about an hour on a fast machine with decent internet access; the download is about 500MB:

    $ cd mxe && make qt
    
  • Go to the directory of your app and add the cross-build tools to the PATHenvironment variable:

    $ export PATH=<mxe root>/usr/bin:$PATH
    
  • Run the Qt Makefile generator tool then build:

    $ <mxe root>/usr/i686-pc-mingw32/qt/bin/qmake && make
    
  • You should find the binary in the ./release directory:

    $ wine release/foo.exe
    
  • 得到它:

    $ git clone https://github.com/mxe/mxe.git
    
  • 安装构建依赖

  • 为 Windows 构建 Qt、它的依赖项和交叉构建工具;在具有良好互联网访问权限的快速机器上,这将需要大约一个小时;下载大约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
    

Some notes:

一些注意事项

  • Use the master branch of the MXE repository; it appears to get a lot more love from the development team.

  • The output is a 32-bit static binary, which will work well on 64-bit Windows.

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

  • 输出是一个 32 位静态二进制文件,它将在 64 位 Windows 上运行良好。

回答by rogerdpack

Ok I think I've got it figured out.

好的,我想我已经弄清楚了。

Based in part on https://github.com/mxe/mxe/blob/master/src/qt.mkand https://www.videolan.org/developers/vlc/contrib/src/qt4/rules.mak

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

It appears that "initially" when you run configure (with -xtarget, etc.), it configures then runs your "hosts" gcc to build the local binary file ./bin/qmake

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

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

then you run normal "make" and it builds it for mingw

然后你运行正常的“make”并为mingw构建它

  make
  make install

so

所以

  1. yes

  2. only if you need to use something other than msvcrt.dll (its default). Though I have never used anything else so I don't know for certain.

  3. https://stackoverflow.com/a/18792925/32453lists some configure params.

  1. 是的

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

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

回答by Timothy Gu

(This is an update of @Tshepang's answer, as MXE has evolved since his answer)

(这是@Tshepang 答案的更新,因为 MXE 自他的回答以来已经发展)

Building Qt

构建 Qt

Rather than using make qtto build Qt, you can use MXE_TARGETSto control your target machine and toolchain (32- or 64-bit). MXE started using .staticand .sharedas a part of the target name to show which type of lib you want to build.

make qt您可以使用MXE_TARGETS来控制目标机器和工具链(32 位或 64 位),而不是用于构建 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'

In @Tshepang's original answer, he did not specify an MXE_TARGETS, and the default is used. At the time he wrote his answer, the default was i686-pc-mingw32, now it's i686-w64-mingw32.static. If you explicitly set MXE_TARGETSto i686-w64-mingw32, omitting .static, a warning is printed because this syntax is now deprecated. If you try to set the target to i686-pc-mingw32, it will show an error as MXE has removed support for MinGW.org (i.e. i686-pc-mingw32).

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

Running qmake

跑步 qmake

As we changed the MXE_TARGETS, the <mxe root>/usr/i686-pc-mingw32/qt/bin/qmakecommand will no longer work. Now, what you need to do is:

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

<mxe root>/usr/<TARGET>/qt/bin/qmake

If you didn't specify MXE_TARGETS, do this:

如果您没有指定MXE_TARGETS,请执行以下操作:

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

Update:The new default is now i686-w64-mingw32.static

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

回答by user986730

In order to compile Qt, one must run it's configurescript, specifying the host platform with -platform(e.g. -platform linux-g++-64if you're building on a 64-bit linux with the g++ compiler) and the target platform with -xplatform(e.g. -xplatform win32-g++if you're cross compiling to windows).

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

I've also added this flag: -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32-which specifies the prefix of the toolchain I'm using, which will get prepended to 'gcc' or 'g++' in all the makefiles that are building binaries for windows.

我还添加了这个标志: -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32-它指定了我正在使用的工具链的前缀,在为 Windows 构建二进制文件的所有 makefile 中,它将被附加到“gcc”或“g++”。

Finally, you might get problems while building icd, which apparently is something that is used to add ActiveX support to Qt. You can avoid that by passing the flag -skip qtactiveqtto the configure script. I've got this one out of this bug report: https://bugreports.qt.io/browse/QTBUG-38223

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

Here's the whole configure command I've used:

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

    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

As for yout questions:

至于你的问题:

1 - Yes. The native compiler will be called in order to build some tools that are needed in the build process. Maybe things like qconfig or qmake, but I'm not entirely sure which tools, exactly.

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

2 - Sorry. I have no idea what specs files are in the context of compilers =/ . But as far as I know, you wouldn't have to deal with that.

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

3 - You can specify the cross compiler prefix in the configure command line instead of doing it in the qmake.conf file, as mentioned above. And there's also that problem with idc, whose workaround I've mentioned as well.

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

回答by Mykola Dimura

Another way to cross-compile software for Windows on Linux is the mingw-w64 toolchain on Archlinux. It is easy to use and maintain, and it provides recent versions of the compiler and many libraries. I personally find it easier than MXE and it seems to adopt newer versions of libraries faster.

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

First you will need an arch-based machine (virtual machine or docker container will suffice). It does not have to be Arch Linux, derivatives will do as well. I used Manjaro Linux. Most of the mingw-w64 packages are not available at the official Arch repositories, but there is plenty in AUR. Default package manager for Arch (pacman) does not support installation directly from AUR, so you will need to install and use an AUR wrapper like yay or yaourt. Then installing mingw-w64 version of Qt5 and Boost libraries is as easy as:

首先,您需要一台基于 arch 的机器(虚拟机或 docker 容器就足够了)。它不一定是 Arch Linux,衍生产品也可以。我用的是 Manjaro Linux。大多数 mingw-w64 软件包在官方 Arch 存储库中不可用,但AUR 中很多。Arch (pacman) 的默认包管理器不支持直接从 AUR 安装,因此您需要安装和使用 AUR 包装器,如 yay 或 yaourt。然后安装 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

This will also install the mingw-w64 toolchain (mingw-w64-gcc) and other dependencies. Cross-compiling a Qt project for windows (x64) is then as simple as:

这还将安装 mingw-w64 工具链 ( mingw-w64-gcc) 和其他依赖项。为 Windows (x64) 交叉编译 Qt 项目就像这样简单:

x86_64-w64-mingw32-qmake-qt5
make

To deploy you program you will need to copy corresponding dlls from /usr/x86_64-w64-mingw32/bin/.

要部署您的程序,您需要从/usr/x86_64-w64-mingw32/bin/.

To get a 32bit version you simply need to use i686-w64-mingw32-qmake-qt5instead. Cmake-based projects work just as easy with x86_64-w64-mingw32-cmake. This approach worked extremely well for me, was the easiest to set-up, maintain and extend. It also goes well with continuous integration services. There are docker imagesavailable too.

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

For example, let's say I want to build QNapi subtitle downloader GUI. I could do it in two steps:

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

1) Start the docker container:

1)启动docker容器:

sudo docker run -it burningdaylight/docker-mingw-qt5 /bin/bash

2) Clone and compile QNapi

2)克隆并编译QNapi

git clone --recursive 'https://github.com/QNapi/qnapi.git'
cd qnapi/
x86_64-w64-mingw32-qmake-qt5
make

That's it! In many cases it will be that easy. Adding your own libraries to package repository (AUR) is also straightforward. You would need to write a PKBUILD file, which is as intuitive as it can get, see mingw-w64-rapidjson, for example.

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