Cross Compilation Native d'application Qt depuis Linux/Unix Like
Par P@sNox le samedi, avril 14 2007, 10:01 - Installation - Lien permanent
- Qu'est ce que la cross compilation ?
- Comment créer un executable pour une architecture différente ?
- Comment créer un exécutable Windows sous Linux ?
Un compilateur croisé (en anglais cross compiler.) est un programme capable de traduire un code source en code objet ayant un environnement d'exécution (architecture matérielle, système d'exploitation) différent de celui où la compilation est effectuée. Ces compilateurs sont principalement utilisés en informatique industrielle.
Cet article va detailler la mise en place et l'utilisation d'un environnement de compilation multi plateforme.
En effet, tout le monde n'a pas Windows dans sa poche ( et heureusement :D ), et fournir un executable pour une architecture autre que la sienne peut parfois etre un vrai calvaire.
Aussi à travers de ce tutoriel, nous allons mettre un place un tel systeme en utilisant mingw32 et Qt4.
Version : Qt4 (supérieur ou égal à Qt 4.0, peut etre valable pour n'importe quelle autre librairie)
Auteur : Filipe Azevedo (pasnox)
Test : Kubuntu Feisty 7.04 beta (Qt 4.2.3)
Pré-requis
Le but de ce tutoriel est de montrer comment compiler une application Qt 4 pour Windows depuis Linux. Nous aurons donc besoin d'installer les logiciels suivant :
- mingw32 (disponible normalement dans les paquets de votre distribution, il aura pour effet d'installer en plus les paquets suivant :
mingw32-binutilsetmingw32-runtime) - Wine (pour ensuite tester votre application Windows sous Linux)
- Une installation correcte de Qt 4 pour Windows version mingw
- Une installation correcte de Qt 4 pour Linux
Installation des paquets (système basé sur debian)
La façon la plus simple d'installer mingw32 et Wine est d'ouvrir une console (ou bien un gestionnaire de paquet, tel Adept) et d'y inscrire les commandes suivante :
pasnox@pasnox-desktop:~$ sudo apt-get install mingw32 pasnox@pasnox-desktop:~$ sudo apt-get install wine
Note : les commandes d'installation de paquet ci contre ne sont valables que pour debian/ubuntu/kubuntu, ou tout systeme basé sur debian, veuillez vous réferrer à la documentation de votre distribution linux le cas échéant.
Installation de Qt 4 Windows
Maintenant que nous avons installé Wine, nous pouvons installer la version Windows de Qt 4 qui utilise mingw (par exemple la version 4.2.3) Une fois téléchargé, pour l'installer, veuillez ouvrir une console et taper :
pasnox@pasnox-desktop:~$ wine chemin/de/qt/pour/windows/qt-win-opensource-4.2.3-mingw.exe
Je vous conseille d'installer la librairie Qt dans un dossier dont le chemin ne contient pas d'espace, par exemple : C:\Development\Qt\4.2.3 (chemin qui sera utilisé par la suite).
Attention : il n'est pas nécessaire d'installer mingw depuis l'installateur, même si celui-ci vous dit qu'il ne le trouve pas.
Configuration de Wine
Maintenant que Qt 4 pour Windows est installé, il faut indiquer à Wine où trouver les librairies Qt. Il s'agit en fait de modifier la base de registres, car les variables d'environnement ne sont pas accessibles. Pour ce faire, exécuter le logiciel Wine RegEdit.
pasnox@pasnox-desktop:~$ wine regedit
Rendez-vous dans la clé HKEY_CURRENT_USER.
Si la clé Environment n'existe pas, veuillez la créer en faisant clique droit sur la clé HKEY_CURRENT_USER, puis nouvelle clé.
Dans cette clé ( Environment ), la valeur nommé PATH devrait s'y trouver .
Si celle-ci n'existe pas créez là : clique droit sur la clé Environment puis nouvelle valeur chaine.
Nommez-la PATH et donnez lui la valeur du chemin d'installation des exécutables de Qt, c'est à dire C:\Development\Qt\4.2.3\bin.
Parfait, il manque maintenant une dll, celle-ci se nomme mingwm10.dll et est disponible depuis les paquets installés. Pour ne pas être embêté, nous allons la copier dans le dossier system32 de Wine, ce qui permettra d'executer des applications mingw depuis Wine plus facilement.
Ouvrez une console et tapez :
pasnox@pasnox-desktop:~$ gunzip -c /usr/share/doc/mingw32-runtime/mingwm10.dll.gz > ~/.wine/drive_c/windows/system32/mingwm10.dll
Vous disposez maintenant d'une version de Wine prête pour l'exécution d'application Qt 4.
Création d'un mkspec
Pour pouvoir compiler notre application, il va nous falloir créer un nouveau mkspec basé sur celui de win32-g++.
Copiez donc le contenu grâce à la commande suivante (/usr/share/qt4 est le répertoire d'installation par défaut des paquets Qt4 sous distribution à base de Debian) :
pasnox@pasnox-desktop:~$ sudo cp -r /usr/share/qt4/mkspecs/win32-g++ /usr/share/qt4/mkspecs/win32-x-g++
On a donc maintenant un nouveau mkspec nommé win32-x-g++ basé sur win32-g++.
Il faut remplacer quelques variables contenues dans le fichier qmake.conf de ce nouveau mkspec, toujours dans la console tapez :
pasnox@pasnox-desktop:~$ sudo kate /usr/share/qt4/mkspecs/win32-x-g++/qmake.conf
Note : Vous pouvez utiliser autre chose que kate comme éditeur de texte.
Les variables à remplacer sont en fait les compilateurs C et C++ ( gcc et g++ ) ainsi que les commandes DOS.
Voici les variables a modifier :
QMAKE_CC = i586-mingw32msvc-gcc
QMAKE_CXX = i586-mingw32msvc-g++
QMAKE_INCDIR = /usr/i586-mingw32msvc/include
QMAKE_INCDIR_QT = ~/.wine/drive_c/Development/Qt/4.2.3/include
QMAKE_LIBDIR_QT = ~/.wine/drive_c/Development/Qt/4.2.3/lib
QMAKE_LINK = i586-mingw32msvc-g++
# N'oubliez pas le -mwindows a la fin pour éviter d'avoir une console dans vos applications
QMAKE_LFLAGS = -mthreads -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mwindows
# les commande DOS sont à remplacer par les commandes shell unix
#isEqual(MINGW_IN_SHELL, 1) {
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
#} else {
# Vous pouvez effacer la partie else qui ne sert a rien, ainsi que le isEqual du dessus
#}
# Enlever les .exe des executables
QMAKE_MOC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}moc
QMAKE_UIC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}uic
QMAKE_IDC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}idc
QMAKE_RCC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}rcc
QMAKE_LIB = i586-mingw32-ar -ru
QMAKE_RC = i586-mingw32msvc-windres
QMAKE_STRIP = i586-mingw32msvc-strip
Une fois terminée, vous êtes enfin prêt à compiler votre application pour windows :)
Pour ce faire vous utiliserez le mkspec win32-x-g++ lors de l'apelle à qmake :
pasnox@pasnox-desktop:~$ qmake-qt4 -spec win32-x-g++ && make
Note : Il semblerait que sous mac, il faille ajouter la platforme à la ligne de commande qmake : -win32
Une fois compilée, l'application se trouve dans le dossier release en cas de compilation release, ou bien dans le dossier debug ( vous aurez besoin de compiler Qt en debug pour cela )
Pour lancer l'application grace à Wine :
pasnox@pasnox-desktop:~$ wine release/mon_application.exe
Il est à noter que le binaire aura besoin, tout comme une compilation via mingw32 sous Windows, des dll Qt (au minimum de QtCore pour une application console, et QtCore/QtGui pour une application graphique simple) ainsi que de mingwm10.dll.
Note : Pour supprimer la dépendance aux dlls de Qt, il est nécessaire de compiler Qt4 Windows en version statique, mais c'est un problème qui n'est pas traité ici... peut-être plus tard.
Bonne cross compilation !
Autres sources
Vous trouverez ici d'autres informations sur la cross-compilation ici :

Commentaires
Suite a un post concernant la cross compilation depuis mac os x, le tutoriel a été legerement modifier, notemment l'ajout dela commande rcc à modifier dans le qmake.conf, ainsi que le parametre -win32 à la commande qmake.
P@sNox,
Ce tuto est vraiment super :) , ça faisait longtemps que je cherchais comment faire ce qui est expliqué !!
Salut, merci pour ce tuto.
J'ai juste eu un petit problème avec les chemin d'accès : ~/.wine/drive_c/Development/Qt/4.2.3/* il à fallut que je mette le chemin absolu sinon le compilateur ne trouvé pas les fichiers : /home/fantome/.wine/drive_c/Development/Qt/4.2.3/*
Et pour moc et uic j'ai du ajouter moc-qt4 et uic-qt4 sinon il essayer avec les versions Qt3
Salut tout le monde, ce tuto est très important.
Je viens juste de m'inscrire sur Qt forum fr. Je suis néerlandais est mon français est vraiment au bas niveau, alors je m'excuse.
Voila, je travail sur une machine windows et j'aimerai pouvoir créer un exécutable Linux sous Windows pour Qt applications. J'ai cherché partout comment le faire mais sans résulta. Y a t'il quelqu’un qui peu m'aider ou qui a une ide?
C'est donc à ça que servais le paquet mingw32
C'est donc à ça que servais le paquet mingw32
Donc pour ceux que ça interesse, je viens en m'aidant de ce tuto de réaliser la même chose pour mon mac qui est sous Leopard. Les choses suivantes sont à changer:
- J'ai utilisé la version 4.4.1 de Qt pour Mac, compilée et installée dans /usr/local/Trolltech/Qt-4.4.1
- J'ai utilisé la version 4.4.1 de Qt pour Windows, installée dans CrossOver dans le dossier "C:\Qt\4.4.1" via CrossOver.
- Suite à des problèmes de noms de dossiers contenant des espaces, j'ai créé un lien symbolique à la racine de mon dur vers le dossier d'installation de Qt pour windows. Le lien est nomé "/Qt_4.4.1_MinGW": l'installation de Qt par CrossOver est dans quelque chose comme "/Library/Application Support/CrossOver/Bottles/Win2K/drive_c/Qt/4.4.1", ce qui pose ensuite problème. Le lien symbolique est donc très important.
- A la place de wine, j'ai utilisé CrossOver (Version d'essai ici: http://www.codeweavers.com/products...).
- Concernant MinGW, j'ai téléchargé la version 3.4.5 pour mac, elle s'installe normalement dans "/usr/local/i386-mingw32-3.4.5".
- J'ai sauté l'étape de modification des clés de la base de registre, car je ne souhaite pas tester mes applis avec CrossOver sur mon Mac.
- Le fichier de spé du compilo ("/usr/local/Trolltech/Qt-4.4.1/mkspecs/win32-x-g++/qmake.conf") resemble à cela. Attention, certaines lignes ont été modifiées comme dans le tuto, par contre d'autres ont été AJOUTEES, et c'est très important...
- Sinon, si vous voulez lancer votre appli compilée avec CrossOver, je vous conseille de copier les librairies Qt présentes dans "C:\Qt\4.4.1\lib" vers "C:\Windows\System32" ou dans le même dossier que votre appli compilée...
Voilà, en espérant en aider certains :)
Pierre.
# --------------------------------------------
MAKEFILE_GENERATOR = MINGW
TEMPLATE = app
CONFIG += qt warn_on release link_prl copy_dir_files debug_and_release debug_and_release_target precompile_header
QT += core gui
DEFINES += UNICODE QT_LARGEFILE_SUPPORT
QMAKE_COMPILER_DEFINES += __GNUC__ WIN32
QMAKE_EXT_OBJ = .o
QMAKE_EXT_RES = _res.o
QMAKE_CC = i386-mingw32-gcc # Modified for CrossP compilation.
QMAKE_LEX = flex
QMAKE_LEXFLAGS =
QMAKE_YACC = byacc
QMAKE_YACCFLAGS = -d
QMAKE_CFLAGS =
QMAKE_CFLAGS_DEPS = -M
QMAKE_CFLAGS_WARN_ON = -Wall
QMAKE_CFLAGS_WARN_OFF = -w
QMAKE_CFLAGS_RELEASE = -O2
QMAKE_CFLAGS_DEBUG = -g
QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
QMAKE_CXX = i386-mingw32-g++ # Modified for CrossP compilation.
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
QMAKE_CXXFLAGS_RTTI_ON = -frtti
QMAKE_CXXFLAGS_RTTI_OFF = -fno-rtti
QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions -mthreads
QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions
QMAKE_INCDIR = /usr/local/i386-mingw32-3.4.5/include # Modified for CrossP compilation.
QMAKE_INCDIR_QT = /Qt_4.4.1_MinGW/include # Modified for CrossP compilation.
QMAKE_LIBDIR_QT = /Qt_4.4.1_MinGW/lib # Modified for CrossP compilation.
QMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src
QMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
QMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src
QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
QMAKE_LINK = i386-mingw32-g++ # Modified for CrossP compilation.
QMAKE_LFLAGS = -mthreads -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mwindows # Modified for CrossP compilation.
QMAKE_LFLAGS_EXCEPTIONS_ON = -mthreads -Wl
QMAKE_LFLAGS_EXCEPTIONS_OFF =
QMAKE_LFLAGS_RELEASE = -Wl,-s
QMAKE_LFLAGS_DEBUG =
QMAKE_LFLAGS_CONSOLE = -Wl,-subsystem,console
QMAKE_LFLAGS_WINDOWS = -Wl,-subsystem,windows
QMAKE_LFLAGS_DLL = -shared
QMAKE_LINK_OBJECT_MAX = 10
QMAKE_LINK_OBJECT_SCRIPT= object_script
QMAKE_LIBS =
QMAKE_LIBS_CORE = -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lws2_32
QMAKE_LIBS_GUI = -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lws2_32 -lole32 -luuid -luser32 -ladvapi32
QMAKE_LIBS_NETWORK = -lws2_32
QMAKE_LIBS_OPENGL = -lopengl32 -lglu32 -lgdi32 -luser32
QMAKE_LIBS_COMPAT = -ladvapi32 -lshell32 -lcomdlg32 -luser32 -lgdi32 -lws2_32
QMAKE_LIBS_QT_ENTRY = -lmingw32 -lqtmain
QMAKE_DIR_SEP = / # Added for CrossP compilation.
QMAKE_COPY = cp # Modified for CrossP compilation.
QMAKE_COPY_DIR = cp -r # Modified for CrossP compilation.
QMAKE_MOVE = mv # Modified for CrossP compilation.
QMAKE_DEL_FILE = rm -f # Modified for CrossP compilation.
QMAKE_MKDIR = mkdir # Modified for CrossP compilation.
QMAKE_DEL_DIR = rm -rf # Modified for CrossP compilation.
QMAKE_CHK_DIR_EXISTS = if not exist # Added for CrossP compilation.
QMAKE_MOC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}moc # Modified for CrossP compilation.
QMAKE_UIC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}uic # Modified for CrossP compilation.
QMAKE_IDC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}idc # Modified for CrossP compilation.
QMAKE_RCC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}rcc
QMAKE_IDL = midl
QMAKE_LIB = i386-mingw32-ar -ru # Modified for CrossP compilation.
QMAKE_RC = i386-mingw32-windres # Modified for CrossP compilation.
QMAKE_ZIP = zip -r -9
QMAKE_STRIP = i386-mingw32-strip # Modified for CrossP compilation.
QMAKE_STRIPFLAGS_LIB += --strip-unneeded
load(qt_config)
J'ai aussi eu besoin pour
QMAKE_INCDIR_QT
QMAKE_LIBDIR_QT
d'indiquer les chemins absolus.
j'ai remarqué une petite coquille. Sur ubuntu la ligne suivante
QMAKE_LIB = i586-mingw32-ar -ru
doit être modifiée par
QMAKE_LIB = i586-mingw32msvc-ar -ru
E tout fonctionne avec une appli comprenant des plugins