Why is cross-compiling not supported out of the box?
Hello to everyone,
Qt has a very good cross platform support but I noticed that it lacks on support and documentation for building my application for different targets (a part from mobile/symbian). I wonder why?
I am not looking for some exotic combinations, but even compiling 32bit code on my 64bit linux box isn't supported by default. I thought it where somewhat complicated to support cross compiling but after googling a lot I found out that it isn't. When building a desktop application the typical target is Windows, Mac OS X and Linux.
I am trying to find an answer to this question. On various forums I read for example that it's a nonsense to build for a target that you can't execute on your development platform (for example compiling a windows binary on linux). First of all this is not entirely true. I can execute 32bit binary linux code on my 64bit linux box. And to some extend I can execute a windows binary through the wine application.
But the major point is that running my application within the development environment is necessary only for specific debugging. Before releasing a new version I need in any case to complete a full testing on the target platform that doesn't contain a development environment but the most common user environment (I need to test the installer too). And I need to test the application under different operating systems. Even with just one 32bit windows binary I need to test it at least under Windows XP, Vista and Windows 7. And I'm not going to setup a build environment for each of these O.S., but I may do temporarily if I have a nasty bug to handle with that specific target.
The whole point for cross-compiling is convenience:
With one click I build for all my targets and with a well written script I have ready my final installer, even uploaded somewhere on the web and I do the common debugging in my development environment/target.
So, I don't accept the answer that cross compiling isn't useful.
Another reason seems that it's complicated to setup cross compiling and I too thought so. But Using Qt Creator I found out that the requirements are 'only':
- a cross compiler for your specific target (sometimes available)
- the source/binary/header libraries for your specific target (these are always available by copying them from a target machine)
- a spec file that I specify with '-spec myspec' in the additional arguments of qmake/build steps. This we to do setup manually.
Let's make some examples. There are maybe some errors, I just found out by testing and googling, so please correct when necessary:
Setup linux 32bit target under linux 64bit:
- the cross compiler g++ is supported by default (with -m32 switch)
- the 32bit libraries where available, I just had to install them using the packaging manager.
"gcc multilib" "g++-multilib" "ia32-libs" and "lib32stdc++6". They will be located in /usr/lib32 because /usr/lib is for the 64bit libraries.
- The '-spec linux-g++-32' will not work because I think it's supposed to be used on 32bit linux for 32bit compiling.
I created a new specification folder copied from /usr/share/qt/mkspecs/linux-g++-32 into linux-g++-32_on64.
Then to compile the hellogl example application I had only to change the library settings of the qmake.conf file, the last three lines:
QMAKE_LIBDIR_QT = /usr/lib32
Probably more changes are required with more complicate projects.
After these changes I only had to specify '-spec linux-g++-32_on64' to compile 32bit targets on my 64bit linux.
Setup windows 32bit target under linux 64bit:
- The available cross compiler is MinGW, installed (i think) through package 'gcc-mingw32'.
- To get the Windows libraries/header/source files the easiest solution is to copy it from a Windows machine. So I installed the Qt framework on a Windows PC, and then I copied the folders include, src, lib to a new folder /usr/qt4win32
- As with the previous example I had to create a new spec file, copied from the win32-g++ specification and adding several changes because the applications to compile/link/build are different on linux than on windows (see next post).
Setting up 64bit compiling for Windows is probably similar.
At last it would be nice to have also a Mac OS X Target, here the major issue is to get the cross compiler, because the libraries are always available by copying them from a target machine that you can use sometimes for debugging particular bugs for that platform.
Someone managed to do it (http://www.sandroid.org/imcross/).
So at last I am asking....
Why not offer at least one environment where cross compiling is available for the major platforms out of the box? Maybe as an additional setup.
Why not offer at least the documentation where it is explained how to setup cross compiling?
I had to find on my own all the answers through googling (thanks to all who wrote the various articles on cross compiling)...
Only some cross compilers are available, they are very few, why not offer support/documentation for them?
changes in the spec file for win32 compiling (got it from here http://blog.2of1.org/2010/08/23/cross-compiling-a-qt-win32-app-on-linux/):
QMAKE_CXX = /usr/bin/i586-mingw32msvc-g++
QMAKE_INCDIR = /usr/i586-mingw32msvc/include
QMAKE_INCDIR_QT = /usr/qt4win32/include
QMAKE_LIBDIR_QT = /usr/qt4win32/lib32
QMAKE_LINK = /usr/bin/i586-mingw32msvc-g++
QMAKE_LFLAGS = -mthreads -static-libgcc -static -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mwindows
QMAKE_DIR_SEP = /
QMAKE_COPY = cp
QMAKE_COPY_DIR = cp -r
QMAKE_MOVE = mv
QMAKE_DEL_FILE = rm -f
QMAKE_MKDIR = mkdir -p
QMAKE_DEL_DIR = rm -rf
QMAKE_MOC = $$[QT_INSTALL_BINS]/moc-qt4
QMAKE_UIC = $$[QT_INSTALL_BINS]/uic-qt4
QMAKE_IDC = $$[QT_INSTALL_BINS]/idc-qt4
QMAKE_RC = /usr/bin/i586-mingw32msvc-windres
QMAKE_STRIP = /usr/bin/i586-mingw32msvc-strip
Again maybe with more complicated projects other changes are requested.
Qt is a library, not a build system. Qt runs where ever it is compiled.
Qt Creator is an IDE that sits on top of the tool chain(s) that you have installed. Cross compiling is the domain of the tool chain, not Creator's. The very same holds for qmake (which is just used by Creator).
Then you mix different things.
32/64 bit is not really cross compiling in the actual sense. Most of these systems are dual stack and have all the necessary libs for 64 bit and for 32 bit. Most 64bit boxes have the 32bit version on board too.
Copying headers and some libs around might not be enough. Very often you need some system libs too, which may be hidden somewhere deep in the filesystem. Not to mention licensing issues.
And you need not to compile a separate version for each windows version out in the wild. It's the advantage of Qt being cross platform, that there are only rare cases, where things are messed up a bit.
Creating Mac version is a beast of its own - think of universal binaries, I don't know of any tool on other platforms that can create them. Carbon/Cocoa headers/libs are subject to the licensing issue again.
The, please do not mix up cross compilation with building installers. There are cross platform install builders out there, but I don't know if they support building a - say - windows installer on a linux box. Let alone creating Mac disk images (DMG) on something else than a Mac.
This all can be achieved, yes. It's a timely, error prone task and it does not save you from setting up all the needed development environments because you eventually will have to run you development steps on the target system, at least to debug things (which may become harder, as the native tool chain might behave slightly different than the cross compiler).
So, to make a long story short: Yep, Qt tools (qmake & Creator) support cross compilation out of the box. It all depends on your installed tool chain(s). Adding more than this is not worth the effort, in my opinion, as the requirements are far too different.
Yes, I understand that supporting (even just one) cross compiling development environment is a hassle and (probably) out of the scope of Qt, that's why I suggested option 2. a short documentation/guideline on how to setup cross compiling.
For example the requirements for cross compiling (compiler+libraries+spec file). The description of the specs file format used by qmake, and maybe some sample specs files usable for cross compiling.
the specfiles are not specifically to cross compiling, they are specific for the cimpiler. And there are many examples, all in the file structure.
And regarding an example, which one? host linux, windows or mac? Which compiler to use for the target environment? All this depends on the host and target environment, and each compiler might be different. How to do cross compiling is just a thing of the toolchain, and so it heavily depends on that.
Giving an example with Linux (perhaps Suse enterprise) and chroot mechanism would fulfill linux, what with mac and windows? So I think, it's ok how it is. It could be something for the wiki here, if someopne writes something for a specific environment and toolchain.