KOLANICH
KOLANICH

Reputation: 3072

How to crosscompile applications on Ubuntu to Windows

I have been developing an app built upon Qt 5 on Ubuntu in Qt Creator. The project format used is CMake. It's time to cross-compile the stuff into a binary which can be run on Windows. So I have

  1. installed clang and mingw-w64
  2. created a CMake toolchain file pointing to the right tools (the ones from the installed MiGW toolchain) and set the target triple to x86_64-w64-mingw32 (this triple is used because it corresponds to the path where the gcc toolchain is installed).
  3. downloaded packages beginning from mingw64-qt from https://dl.fedoraproject.org/pub/fedora/linux/development/30/Everything/x86_64/os/Packages/m/ , unpacked them, merged the unpacked dirs, removed anything unneeded, fixed the CMake scripts to make them correspond to the paths in the system (there are some hardcoded paths in the scripts).
  4. added the paths to the needed dirs of the unpacked Qt into the toolchain file, to make the autodiscovery work
  5. Tried to build.

When I tried to build, some files (6) of my project have compiled fine, but 4 have caused nasty compilation errors:

/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

OK, I thought, maybe MinGW-w64 in Ubuntu repos is rotten? In fact it is, it is 6.0 in Ubuntu repos, but on MinGW-w64 website 8.1 is available.

OK. I have uninstalled the package, downloaded 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 , unpacked it, set the toolchain file to use clang and clang++ as compilers and llvm binutils, set the sysroot pointing to the unpacked dir, tried to rebuild ... and got the same errors (but in the new sysroot).

Well, I have tried to build something simplier in terms of dependencies and what is known to be buildable by g++ - ninja.

The same result. I have tried then MinGW-w64 toolchain (the Windows version) run in wine. The same result. Damn.

A simple hello world app builds and works fine in all cases.

How to cross-build an app more complex than a hello world for Windows using MinGW-w64 stdlib?

Also I wonder how to setup Qt Creator to use this toolchain correctly.

Upvotes: 2

Views: 4177

Answers (3)

Melroy van den Berg
Melroy van den Berg

Reputation: 3156

You can use MXE as mentioned earlier. For Debian/Ubuntu users you can add the repo to APT via:

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

After which you should be able to install any packages (libs) you may need for cross-compiling. An example for GTK3 (for Windows 64-bit): sudo apt install mxe-x86-64-w64-mingw32.static-gtk3

For Qt5 you just need to install: sudo apt install mxe-x86-64-w64-mingw32.static-qt5

You do need to update your PATH (so edit your ~/.bashrc file), add to the bottom:

export PATH="/usr/lib/mxe/usr/bin:$PATH"

Now you can start cross-compiling! I'm trying the wrapper script provided by MXE for CMake: x86_64-w64-mingw32.static-cmake

I hope this helps somebody!

Upvotes: 0

KOLANICH
KOLANICH

Reputation: 3072

It was the bug in the stdlib headers shipped with the toolchains. It was the conflict between C and C++ headers. I still have no idea why this bug doesn't fire when the toolchain is invoked on Windows, but I have solved the issue by introducing a macrodef guarding the problematic types definitions. A dirty hack it is: a better solution is to move them into an own header, guard it with #pragma once and include it where it is needed.

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


Upvotes: 1

Nikos C.
Nikos C.

Reputation: 51832

I use https://mxe.cc to cross-compile my Qt applications to Windows. You can set it up in your home directory. After you tell it to fetch and compile the dependencies you need (like qtbase, cmake, etc.) you can compile your application with:

i686-w64-mingw32.static-cmake path_to_your_project
make

For a qmake project, you'd use i686-w64-mingw32.static-qmake instead.

Upvotes: 3

Related Questions