I've recently been playing rediscovering Qt with Qt4. Qt is a great cross-platform programming environment for GUI apps—the best I've used, at least. Anyway, as I put my app together, I thought that I should release it as a windows binary as well—both to use (and test!) this Qt cross-platform compatibility and because I expect the majority of the tool users would be windows users. Alas, I don't have a working windows os (I do have installed some 120-day evaluation version of win2003 somewhere, but even if it works, which I doubt, given some hardware changes since I've last launched it, I think the evaluation period is over anyway), let alone windows development environment.
So, I immediately thought about cross-compiling. Cross-compiling is compiling for another target platform than the host platform (where we run compilation). Generally, mingw32-gcc works marvels for linux-to-win32 cross-compilation and I've been using it some time ago for GTK apps. That was easier, because GTK/win is available in compiled form, so I just needed to cross-compile my own apps. For Qt4/win, no mingw32 binaries are readily available. So I had to take a go at compiling it myself.
After some googling, I've found that although some people tried to achieve that, none of them succeeded. This turned me down a little bit, but I'm not a person which would run away from a challenge.
The main problem with this cross-compilation is Qt4 build system. Although it seems to support cross-compilation, it really can only do it out-of-the-box between different Unix platforms. Since mingw32 is not strictly a Unix platform and different codepaths need to be compiled, this approach fails. So what we need to do is trick the buildsystem into thinking that win32 codepaths apply to unix.
Without further ado, I present you with step-by-step instructions on how to cross-compile Qt4/win. First, though, you need to obtain cross-compiling environment. On gentoo it's simple. Run the following as root:
emerge crossdev
crossdev -t mingw32
Well, simple as it may be, compilation was broken on my box on one step. It seems that it didn't find the right compiler to compile win32api. What was needed is
gcc-config mingw32-4.2.0
source /etc/profile
After that I've re-issued the crossdev -t mingw32 command and everything worked.
Now for the compilation of Qt4/win. You need to have Qt4/X11 already installed on your system, as we'll use Qt utilities already available on the system. Make sure you don't the following as root, because the build system for some reason insists on installing DLLs in /usr/bin
(doesn't break if it can't, so no harm).
- Get Qt4/win sources. I've used 4.3.1 edition.
- Unpack them. Enter the directory.
- Trick the buildsystem into using win32 feature files:
cd mkspecs/features
ln -s win32 unix
cd ../..
- Download the patch. Apply it.
patch -p1 < qt4win-cross-mingw.patch
- Make sure qmake doesn't use compilation paths meant for unix
find src -name '*.pro' -o -name '*.pri' | xargs sed -i -e 's/\(^\|[^_/]\)unix/\1linux/g;'
- Make qmake use compilation paths meant for Windows.
find src -name '*.pro' -o -name '*.pri' | xargs sed -i -e 's/\(^\|[^_/]\)win32\([^-]\|$\)/\1unix\2/g;'
- Trick configure into using system utilities.
for f in moc rcc uic qmake; do ln -s `which $f` bin; done
- Make sure we don't build them:
echo qmake: > qmake/Makefile.unix
for f in `ls src/tools`; do echo TEMPLATE = subdirs > src/tools/$f/$f.pro; done
- We need some files from the Qt/X11 source, specifically
configure
script and config.tests
directory. I've got them from my qt-copy
(from KDE repo); you can use that or download Qt/X11 sources. Put them in the main source directory.
- Configure. These options are carefully chosen not to break compilation (except
-prefix
and -prefix-install
; the latter doesn't seem to work anyway).
./configure -prefix $PWD -xplatform win32-g++ -no-largefile -exceptions -no-accessibility -no-qt3support -make libs -prefix-install $PWD -no-reduce-exports
- Make a missing makefile.
qmake -spec $PWD/mkspecs/win32-g++ src/winmain/winmain.pro -o src/winmain/Makefile
- Build.
make
- Done!
If you have Wine, you can even test it. Just make sure the dlls are where Wine can find them: cp /usr/mingw32/usr/bin/mingwm10.dll lib/*.dll /home/divide/.wine/c/windows/system/. To compile the demos, do
cd demos
qmake -spec ../mkspecs/win32-g++ demos.pro
make
wine demos/affine/affine.exe
The only problem I've found with using Qt4 in wine is that the latter doesn't implement some font handling functions and it sometimes breaks font rendering where text is laid out dynamically—esp. QGraphicsView and QTextEdit seem to be the worst offenders.