如何交叉编译 Ubuntu 到 Windows 上的应用程序
How to crosscompile applications on Ubuntu to Windows
我一直在 Qt Creator Ubuntu 上开发基于 Qt 5 的应用程序。使用的项目格式是CMake。是时候将这些东西交叉编译成二进制文件了,可以是 运行 on Windows。所以我有
- 已安装 clang 和 mingw-w64
- 创建了一个指向正确工具(来自已安装的 MiGW 工具链的工具)的 CMake 工具链文件并将目标三元组设置为
x86_64-w64-mingw32
(使用此三元组是因为它对应于 gcc 工具链所在的路径已安装)。
- 从https://dl.fedoraproject.org/pub/fedora/linux/development/30/Everything/x86_64/os/Packages/m/下载了
mingw64-qt
开始的包,解压,合并解压后的目录,删除不需要的东西,修复CMake脚本,使它们与系统中的路径相对应(有脚本中的一些硬编码路径)。
- 将解压 Qt 所需目录的路径添加到工具链文件中,以使自动发现工作
- 尝试构建。
当我尝试构建时,我项目的某些文件 (6) 编译正常,但有 4 个文件导致严重的编译错误:
/usr/share/mingw-w64/include/rpcndr.h:64:11: error: reference to ‘byte’ is ambiguous
/usr/share/mingw-w64/include/objidlbase.h:2067:5: error: ‘byte’ has not been declared
好吧,我想,也许 Ubuntu 存储库中的 MinGW-w64 已经烂了?事实上,它在 Ubuntu repos 中是 6.0,但在 MinGW-w64 网站上可用 8.1。
好的。我已经卸载了软件包,下载 https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/8.1.0/threads-posix/seh/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z
,解压它,将工具链文件设置为使用 clang 和 clang++ 作为编译器和 llvm binutils,将 sysroot 设置为指向解压后的目录,尝试重建...并得到相同的错误(但在新的 sysroot 中)。
好吧,我已经尝试构建一些在依赖关系方面更简单的东西,以及已知可以由 g++ - ninja 构建的东西。
同样的结果。然后我在 wine 中尝试了 MinGW-w64 工具链(Windows 版本)运行。同样的结果。妈的
一个简单的 hello world 应用程序在所有情况下都能正常构建和运行。
如何使用 MinGW-w64 标准库为 Windows 交叉构建比 hello world 更复杂的应用程序?
我还想知道如何设置 Qt Creator 以正确使用此工具链。
我使用 https://mxe.cc 将我的 Qt 应用程序交叉编译为 Windows。您可以在您的主目录中设置它。在您告诉它获取并编译您需要的依赖项(如 qtbase、cmake 等)后,您可以使用以下命令编译您的应用程序:
i686-w64-mingw32.static-cmake path_to_your_project
make
对于 qmake 项目,您可以使用 i686-w64-mingw32.static-qmake
。
这是工具链附带的标准库 header 中的错误。这是 C 和 C++ header 之间的冲突。我仍然不知道为什么在 Windows 上调用工具链时这个错误不会触发,但我已经通过引入一个 macrodef 来保护有问题的类型定义来解决这个问题。这是一个肮脏的 hack:更好的解决方案是将它们移动到自己的 header 中,用 #pragma once
保护它并将它包含在需要的地方。
From: KOLANICH
Date: Thu, 11 Apr 2019 20:06:23 +0300
Subject: Fixed the bug with conflict between C and C++ definitions of byte.
---
lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional | 3 ++-
x86_64-w64-mingw32/include/rpcndr.h | 6 ++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional b/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional
index 2b46ba8..6b4e027 100644
--- a/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional
+++ b/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional
@@ -893,7 +893,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201703L
// Declare std::byte (full definition is in <cstddef>).
enum class byte : unsigned char;
-
+ #define _BYTE_DEFINED_AdTydTeKkpRvvDuzZisXJMGxPRSHkr
+
template<>
struct __is_byte_like<byte, equal_to<byte>>
: true_type { };
diff --git a/x86_64-w64-mingw32/include/rpcndr.h b/x86_64-w64-mingw32/include/rpcndr.h
index 52de4ad..a490aa4 100644
--- a/x86_64-w64-mingw32/include/rpcndr.h
+++ b/x86_64-w64-mingw32/include/rpcndr.h
@@ -60,7 +60,13 @@ extern "C" {
#ifdef RC_INVOKED
#define small char
#endif
+
+#ifndef _BYTE_DEFINED_AdTydTeKkpRvvDuzZisXJMGxPRSHkr
typedef unsigned char byte;
+ #define _BYTE_DEFINED_AdTydTeKkpRvvDuzZisXJMGxPRSHkr
+#else:
+ typedef std::byte byte;
+#endif
typedef byte cs_byte;
typedef unsigned char boolean;
--
2.20.1
您可以使用前面提到的MXE。对于 Debian/Ubuntu 用户,您可以通过以下方式将 repo 添加到 APT:
sudo apt-key adv \
--keyserver keyserver.ubuntu.com \
--recv-keys 86B72ED9 && \
sudo add-apt-repository \
"deb [arch=amd64] https://pkg.mxe.cc/repos/apt `lsb_release -sc` main" && \
sudo apt-get update
之后您应该能够安装交叉编译可能需要的任何包(库)。 GTK3 的示例(对于 Windows 64 位):
sudo apt install mxe-x86-64-w64-mingw32.static-gtk3
对于Qt5你只需要安装:sudo apt install mxe-x86-64-w64-mingw32.static-qt5
你确实需要更新你的 PATH(所以编辑你的 ~/.bashrc 文件),添加到底部:
export PATH="/usr/lib/mxe/usr/bin:$PATH"
现在可以开始交叉编译了!我正在尝试 MXE 为 CMake 提供的包装器脚本:x86_64-w64-mingw32.static-cmake
希望对大家有所帮助!
我一直在 Qt Creator Ubuntu 上开发基于 Qt 5 的应用程序。使用的项目格式是CMake。是时候将这些东西交叉编译成二进制文件了,可以是 运行 on Windows。所以我有
- 已安装 clang 和 mingw-w64
- 创建了一个指向正确工具(来自已安装的 MiGW 工具链的工具)的 CMake 工具链文件并将目标三元组设置为
x86_64-w64-mingw32
(使用此三元组是因为它对应于 gcc 工具链所在的路径已安装)。 - 从https://dl.fedoraproject.org/pub/fedora/linux/development/30/Everything/x86_64/os/Packages/m/下载了
mingw64-qt
开始的包,解压,合并解压后的目录,删除不需要的东西,修复CMake脚本,使它们与系统中的路径相对应(有脚本中的一些硬编码路径)。 - 将解压 Qt 所需目录的路径添加到工具链文件中,以使自动发现工作
- 尝试构建。
当我尝试构建时,我项目的某些文件 (6) 编译正常,但有 4 个文件导致严重的编译错误:
/usr/share/mingw-w64/include/rpcndr.h:64:11: error: reference to ‘byte’ is ambiguous
/usr/share/mingw-w64/include/objidlbase.h:2067:5: error: ‘byte’ has not been declared
好吧,我想,也许 Ubuntu 存储库中的 MinGW-w64 已经烂了?事实上,它在 Ubuntu repos 中是 6.0,但在 MinGW-w64 网站上可用 8.1。
好的。我已经卸载了软件包,下载 https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/8.1.0/threads-posix/seh/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z ,解压它,将工具链文件设置为使用 clang 和 clang++ 作为编译器和 llvm binutils,将 sysroot 设置为指向解压后的目录,尝试重建...并得到相同的错误(但在新的 sysroot 中)。
好吧,我已经尝试构建一些在依赖关系方面更简单的东西,以及已知可以由 g++ - ninja 构建的东西。
同样的结果。然后我在 wine 中尝试了 MinGW-w64 工具链(Windows 版本)运行。同样的结果。妈的
一个简单的 hello world 应用程序在所有情况下都能正常构建和运行。
如何使用 MinGW-w64 标准库为 Windows 交叉构建比 hello world 更复杂的应用程序?
我还想知道如何设置 Qt Creator 以正确使用此工具链。
我使用 https://mxe.cc 将我的 Qt 应用程序交叉编译为 Windows。您可以在您的主目录中设置它。在您告诉它获取并编译您需要的依赖项(如 qtbase、cmake 等)后,您可以使用以下命令编译您的应用程序:
i686-w64-mingw32.static-cmake path_to_your_project
make
对于 qmake 项目,您可以使用 i686-w64-mingw32.static-qmake
。
这是工具链附带的标准库 header 中的错误。这是 C 和 C++ header 之间的冲突。我仍然不知道为什么在 Windows 上调用工具链时这个错误不会触发,但我已经通过引入一个 macrodef 来保护有问题的类型定义来解决这个问题。这是一个肮脏的 hack:更好的解决方案是将它们移动到自己的 header 中,用 #pragma once
保护它并将它包含在需要的地方。
From: KOLANICH
Date: Thu, 11 Apr 2019 20:06:23 +0300
Subject: Fixed the bug with conflict between C and C++ definitions of byte.
---
lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional | 3 ++-
x86_64-w64-mingw32/include/rpcndr.h | 6 ++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional b/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional
index 2b46ba8..6b4e027 100644
--- a/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional
+++ b/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional
@@ -893,7 +893,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201703L
// Declare std::byte (full definition is in <cstddef>).
enum class byte : unsigned char;
-
+ #define _BYTE_DEFINED_AdTydTeKkpRvvDuzZisXJMGxPRSHkr
+
template<>
struct __is_byte_like<byte, equal_to<byte>>
: true_type { };
diff --git a/x86_64-w64-mingw32/include/rpcndr.h b/x86_64-w64-mingw32/include/rpcndr.h
index 52de4ad..a490aa4 100644
--- a/x86_64-w64-mingw32/include/rpcndr.h
+++ b/x86_64-w64-mingw32/include/rpcndr.h
@@ -60,7 +60,13 @@ extern "C" {
#ifdef RC_INVOKED
#define small char
#endif
+
+#ifndef _BYTE_DEFINED_AdTydTeKkpRvvDuzZisXJMGxPRSHkr
typedef unsigned char byte;
+ #define _BYTE_DEFINED_AdTydTeKkpRvvDuzZisXJMGxPRSHkr
+#else:
+ typedef std::byte byte;
+#endif
typedef byte cs_byte;
typedef unsigned char boolean;
--
2.20.1
您可以使用前面提到的MXE。对于 Debian/Ubuntu 用户,您可以通过以下方式将 repo 添加到 APT:
sudo apt-key adv \
--keyserver keyserver.ubuntu.com \
--recv-keys 86B72ED9 && \
sudo add-apt-repository \
"deb [arch=amd64] https://pkg.mxe.cc/repos/apt `lsb_release -sc` main" && \
sudo apt-get update
之后您应该能够安装交叉编译可能需要的任何包(库)。 GTK3 的示例(对于 Windows 64 位):
sudo apt install mxe-x86-64-w64-mingw32.static-gtk3
对于Qt5你只需要安装:sudo apt install mxe-x86-64-w64-mingw32.static-qt5
你确实需要更新你的 PATH(所以编辑你的 ~/.bashrc 文件),添加到底部:
export PATH="/usr/lib/mxe/usr/bin:$PATH"
现在可以开始交叉编译了!我正在尝试 MXE 为 CMake 提供的包装器脚本:x86_64-w64-mingw32.static-cmake
希望对大家有所帮助!