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.
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: -platform
and -xplatform
. Qt documentation says that -platform
should be the host machine architecture (where you are compiling) and -xplatform
should be the target platform for which you wish to deploy. In my case, I set -platform linux-g++-64
and -xplatform linux-win32-g++
where linux-win32-g++ is my modified win32-g++ configuration.
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 -xplatform
option and set -platform
to my target spec (linux-win32-g++), it invokes the cross compiler but then errors when it finds some Unix related functions aren't defined.
Here is some output from my latest attempt: http://pastebin.com/QCpKSNev.
Questions:
When cross-compiling something like Qt for Windows from a Linux host, should the native compiler ever be invoked? That is, during a cross compilation process, shouldn't we use only the cross compiler? I don't see why Qt's configure script tries to invoke my system's native compiler when I specify the
-xplatform
option.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.
In general, beyond specifying a cross compiler in my qmake.conf, what else might I need to consider?
Just use M cross environment (MXE). It takes the pain out of the whole process:
Get it:
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:
Go to the directory of your app and add the cross-build tools to the PATH environment variable:
Run the Qt Makefile generator tool then build:
You should find the binary in the ./release directory:
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.
(This is an update of @Tshepang's answer, as MXE has evolved since his answer)
Building Qt
Rather than using
make qt
to build Qt, you can useMXE_TARGETS
to control your target machine and toolchain (32- or 64-bit). MXE started using.static
and.shared
as a part of the target name to show which type of lib you want to build.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 wasi686-pc-mingw32
, now it'si686-w64-mingw32.static
. If you explicitly setMXE_TARGETS
toi686-w64-mingw32
, omitting.static
, a warning is printed because this syntax is now deprecated. If you try to set the target toi686-pc-mingw32
, it will show an error as MXE has removed support for MinGW.org (i.e. i686-pc-mingw32).Running
qmake
As we changed the
MXE_TARGETS
, the<mxe root>/usr/i686-pc-mingw32/qt/bin/qmake
command will no longer work. Now, what you need to do is:If you didn't specify
MXE_TARGETS
, do this:Update: The new default is now
i686-w64-mingw32.static
Ok I think I've got it figured out.
Based in part on https://github.com/mxe/mxe/blob/master/src/qt.mk and https://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
then you run normal "make" and it builds it for mingw
so
yes
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.
https://stackoverflow.com/a/18792925/32453 lists some configure params.
In order to compile Qt, one must run it's
configure
script, specifying the host platform with-platform
(e.g.-platform linux-g++-64
if 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).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.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 qtactiveqt
to the configure script. I've got this one out of this bug report: https://bugreports.qt.io/browse/QTBUG-38223Here's the whole configure command I've used:
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.
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.
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.
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.
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 pacaur or yaourt. Then installing mingw-w64 version of Qt5 and Boost libraries is as easy as:
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:To deploy you program you will need to copy corresponding dlls from
/usr/x86_64-w64-mingw32/bin/
.To get a 32bit version you simply need to use
i686-w64-mingw32-qmake-qt5
instead. Cmake-based projects work just as easy withx86_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 images available too.For example, let's say I want to build QNapi subtitle downloader GUI. I could do it in two steps:
1) Start the docker container:
2) Clone and compile QNapi
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.