如何配置 Qt 以实现从 Linux 到 Windows 目标的交叉编译?
Posted
技术标签:
【中文标题】如何配置 Qt 以实现从 Linux 到 Windows 目标的交叉编译?【英文标题】:How do I configure Qt for cross-compilation from Linux to Windows target? 【发布时间】:2012-06-11 16:14:51 【问题描述】:我想使用 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。
问题:
当从 Linux 主机交叉编译像 Qt for Windows 之类的东西时,是否应该调用本机编译器曾经?也就是说,在交叉编译过程中,我们不应该只使用交叉编译器吗?当我指定 -xplatform
选项时,我不明白为什么 Qt 的配置脚本会尝试调用我系统的本机编译器。
如果我使用 mingw 交叉编译器,我什么时候需要处理 specs 文件? GCC 的规范文件对我来说仍然是一个谜,所以我想知道这里的一些背景是否会对我有所帮助。
一般来说,除了在我的 qmake.conf 中指定交叉编译器之外,我还需要考虑什么?
【问题讨论】:
我相信它需要一个本地构建的 qmake 来引导构建的其余部分。另见***.com/questions/1025687/…中的链接 好的,有道理。我现在刚刚发现了另一个问题,我似乎在混合原生和跨工具链。我的 pastebin 输出中的错误似乎是由于调用x86_64-w64-mingw32-as
而不是原生的。
我很少将 SO 问题标记为收藏,但这是一个独特而有趣的问题,答案很酷。
【参考方案1】:
在 Linux 上为 Windows 交叉编译软件的另一种方法是 Archlinux 上的 MinGW-w64 工具链。它易于使用和维护,并提供最新版本的编译器和许多库。我个人觉得它比 MXE 更容易,而且它似乎更快地采用新版本的库。
首先,您需要一台基于 arch 的机器(虚拟机或 docker 容器就足够了)。它不一定是 Arch Linux,衍生产品也可以。我使用 Manjaro Linux。 大多数 MinGW-w64 软件包在 Arch 官方存储库中不可用,但有 plenty in 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
这还将安装 MinGW-w64 工具链 (mingw-w64-gcc
) 和其他依赖项。
为 windows (x64) 交叉编译一个 Qt 项目就像这样简单:
x86_64-w64-mingw32-qmake-qt5
make
要部署您的程序,您需要从/usr/x86_64-w64-mingw32/bin/
复制corresponding dlls。例如,您通常需要将/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
一样容易工作。
这种方法对我来说非常有效,是最容易设置、维护和扩展的。
它也适用于持续集成服务。也有docker images 可用。
例如,假设我要构建 QNapi 字幕下载器 GUI。我可以分两步完成:
-
启动 docker 容器:
sudo docker run -it burningdaylight/mingw-arch:qt /bin/bash
-
克隆并编译 QNapi
git clone --recursive 'https://github.com/QNapi/qnapi.git'
cd qnapi/
x86_64-w64-mingw32-qmake-qt5
make
就是这样!在许多情况下,这将是那么容易。将您自己的库添加到包存储库 (AUR) 也很简单。您需要write a PKBUILD file,它尽可能直观,例如,请参阅mingw-w64-rapidjson。
【讨论】:
对于部署,您必须复制所有必需的 Qt DLL(或 doc.qt.io/qt-5/windows-deployment.html)。确保将/mingw64/share/qt5/plugins/platforms/qwindows.dll 复制到platforms/qwindows.dll 中。【参考方案2】:为了编译 Qt,必须运行它的 configure
脚本,用 -platform
指定主机平台(例如,-platform linux-g++-64
,如果你使用 g++ 编译器在 64 位 linux 上构建)和目标带有-xplatform
的平台(例如-xplatform win32-g++
,如果您要交叉编译到Windows)。
我还添加了这个标志:
-device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32-
它指定了我正在使用的工具链的前缀,它将在所有为 Windows 构建二进制文件的 makefile 中添加到“gcc”或“g++”的前面。
最后,您在构建icd 时可能会遇到问题,这显然是用于向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 也有这个问题,我也提到了它的解决方法。
【讨论】:
【参考方案3】:只需使用M cross environment (MXE)。它消除了整个过程的痛苦:
得到它:
$ git clone https://github.com/mxe/mxe.git
安装build dependencies
构建 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 存储库的 master 分支;它似乎得到了开发团队更多的喜爱。
输出为 32 位静态二进制文件,在 64 位 Windows 上运行良好。
【讨论】:
注意:这些说明适用于 Qt 4;对于 Qt 5,请参阅 ***.com/a/14170591 在执行$ cd mxe && make qt
之前,您应该安装要求。对于 Debian 系统,这意味着 sudo apt-get install autoconf automake autopoint bash bison bzip2 cmake flex gettext git g++ gperf intltool libffi-dev libtool libltdl-dev libssl-dev libxml-parser-perl make openssl patch perl pkg-config python ruby scons sed unzip wget xz-utils
。对于其他系统,请参阅mxe.cc/#requirements【参考方案4】:
(这是@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
【讨论】:
非常感谢您的更新。让直接参与该项目的人做出回应也很好。 这应该是对另一个答案的编辑/更新,而不是新答案。 @Hugo 编辑页面说: 如何编辑: ► 修正语法或拼写错误 ► 澄清意思而不改变它 ► 纠正小错误 ► 添加相关资源或链接 ► 永远尊重原作者 这不是其中任何一个。这是 Tshepang 答案的延伸。 我不明白这个答案,当我输入“make qt....”时,它只是响应“没有规则来制作目标 qt”。【参考方案5】:好的,我想我已经弄清楚了。
部分基于https://github.com/mxe/mxe/blob/master/src/qt.mk 和https://www.videolan.org/developers/vlc/contrib/src/qt4/rules.mak
似乎“最初”在您运行 configure(使用 -xtarget 等)时,它配置然后运行您的“主机”gcc 以构建本地二进制文件 ./bin/qmake
./configure -xplatform win32-g++ -device-option CROSS_COMPILE=$cross_prefix_here -nomake examples ...
然后你运行正常的“make”,它会为 mingw 构建它
make
make install
所以
是的
仅当您需要使用除 msvcrt.dll(其默认值)以外的其他内容时。虽然我从来没有使用过其他任何东西,所以我不确定。
https://***.com/a/18792925/32453 列出了一些配置参数。
【讨论】:
以上是关于如何配置 Qt 以实现从 Linux 到 Windows 目标的交叉编译?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 QT(C++)中的子进程联系父进程以执行类中的方法?
嵌入式Linux QT开发之如何实现获取磁盘空间大小的应用逻辑