Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
La théorie
La
cross compilation consiste à compiler une application pour un environnement d'exécution
différent de celui où est effectuée la compilation. Ce procédé est utilisé en informatique industrielle (on ne peut compiler un programme pour un automate en utilisant l'automate lui-même ; c'est plus pratique de le faire depuis un PC, par exemple).
Source : Wikipédia.
Dans notre cas, il va s'agir de créer un exécutable Windows
en restant sous Linux. C'est pratique dans le cas où l'on développe une application qu'on veut distribuer à un maximum de gens, mais que l'on n'a pas Windows par exemple (et pourquoi pas ?

).
Prérequis
Pour suivre le tutoriel, vous aurez besoin d'une distribution Linux.
La présence d'un environnement graphique n'est pas obligatoire.
Ensuite, il faudra installer les paquets suivants :
- mingw32 qui permettra de compiler (les paquets mingw32-binutils et mingw32-runtime seront automatiquement installés) ;
- wine pour installer Qt pour Windows et tester vos applications.
Voici la commande pour les distributions basées sur Debian (en tant que
root) :
Code : Console | # aptitude install mingw32 wine |
Tout d'abord, il faut télécharger la version Windows de Qt :
http://trolltech.com/developer/downloads/qt/windows.
Choisissez l'installateur en
.exe (au milieu de la page).
Nous allons exécuter cet installateur grâce à Wine :
Code : Console | wine /home/tuto/qt-win-opensource-4.4.0-mingw.exe |
Pensez à adapter cette commande en fonction du nom du fichier téléchargé, et du dossier dans lequel vous l'avez téléchargé !
On suit l'assistant en prenant bien soin de choisir un chemin d'installation sans espace. Pour la suite, je considérerai que vous avez pris le dossier d'installation
C:\Qt\4.4.0\ (qui correspond dans l'arborescence Linux à
/home/tuto/.wine/drive_c/Qt/4.4.0/).
Le chemin de ce dossier dans l'arborescence Linux sera utilisé par la suite, donc notez-le bien (et remplacez le nom d'utilisateur
tuto par le vôtre).
Maintenant que la version Windows de Qt est installée, nous allons devoir créer un nouveau
mkspec pour pouvoir compiler comme il faut.
Les
mkspec sont présents dans le dossier
/usr/share/qt4/. Il s'agit de fichiers de configuration qui vont aider la commande
qmake à créer notre fichier
Makefile.
Nous allons nous baser sur un
mkspec existant :
win32-g++.
On copie donc ce dossier vers un nouveau, que nous appellerons
win32-x-g++.
Il suffit d'exécuter cette commande (en
root) :
Code : Console | cp -r /usr/share/qt4/mkspecs/win32-g++ /usr/share/qt4/mkspecs/win32-x-g++ |
Nous allons ensuite remplacer le fichier
/usr/share/qt4/mkspecs/win32-x-g++/qmake.conf par un nouveau :
- sudo nano /usr/share/qt4/mkspecs/win32-x-g++/qmake.conf en console OU,
- kdesu kate /usr/share/qt4/mkspecs/win32-x-g++/qmake.conf en utilisant le bloc-note de la suite KDE.
- sudo gedit /usr/share/qt4/mkspecs/win32-x-g++/qmake.conf en utilisant le bloc-note de la suite Gnome.
Voici le nouveau fichier :
Code : Autre1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
| #
# qmake configuration for win32-x-g++
#
# Written for MinGW
#
MAKEFILE_GENERATOR = MINGW
TEMPLATE = app
CONFIG += qt warn_off release link_prl copy_dir_files 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 = i586-mingw32msvc-gcc
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 = i586-mingw32msvc-g++
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/i586-mingw32msvc/include
QMAKE_INCDIR_QT = /home/tuto/.wine/drive_c/Qt/4.4.0/include # A MODIFIER !!!!!!!!!!!!!!!!!!!!!
QMAKE_LIBDIR_QT = /home/tuto/.wine/drive_c/Qt/4.4.0/lib # A MODIFIER !!!!!!!!!!!!!!!!!!!!!
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 = i586-mingw32msvc-g++
QMAKE_LFLAGS = -mthreads -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mwindows
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 = /
QMAKE_COPY = cp
QMAKE_COPY_DIR = cp -r
QMAKE_MOVE = mv
QMAKE_DEL_FILE = rm
QMAKE_MKDIR = mkdir -p
QMAKE_DEL_DIR = rm -r
QMAKE_CHK_DIR_EXISTS = test -d
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_IDL = midl
QMAKE_LIB = i586-mingw32-ar -ru
QMAKE_RC = i586-mingw32msvc-windres
QMAKE_ZIP = zip -r -9
QMAKE_STRIP = i586-mingw32msvc-strip
QMAKE_STRIPFLAGS_LIB += --strip-unneeded
load(qt_config) |
Ce fichier est donc une version modifiée de l'ancien, qui permet d'utiliser les utilitaires de notre environnement Linux pendant la compilation. N'oubliez pas de le modifier (là où j'ai commenté) en fonction du répertoire d'installation de Qt Windows et de votre nom d'utilisateur.
Nous allons également éditer le fichier
/usr/share/qt4/mkspecs/qconfig.pri et enlever le mot
debug de la ligne :
Code : Autre1
| CONFIG += no_mocdepend debug stl qt_no_framework |
On obtient donc :
Code : Autre1
| CONFIG += no_mocdepend stl qt_no_framework |
Nous avons créé notre nouveau
mkspec, il ne reste plus qu'à l'utiliser !
On ouvre un terminal et on se place dans le dossier où sont nos sources (et surtout le précieux fichier
.pro, généré avec la commande
qmake -project ou à la main) et on crée un dossier
win32 qui contiendra les fichiers compilés pour Windows. On va ensuite lancer la commande
qmake, mais en lui indiquant d'utiliser notre nouveau
mkspec (et le bon dossier) :
Code : Console | cd /home/tuto/mon_programme
mkdir win32
qmake -spec win32-x-g++ -o win32/ |
À ce stade, on a normalement un fichier
Makefile dans le dossier
/home/tuto/mon_programme/win32/. On va pouvoir lancer la compilation, après s'être placé dans le bon dossier :
Code : Console
Je vous conseille de compiler d'abord votre code pour Linux, dans le but d'éliminer les erreurs de compilation. Vous pourrez ensuite compiler pour Windows sans crainte.
De plus, vous n'avez pas à copier vos sources : dans /home/tuto/mon_programme/ vous avez tous les fichiers de votre projet dont les sources et les fichiers compilés normalement pour Linux, et dans /home/tuto/mon_programme/win32/ uniquement les fichiers compilés pour Windows.
Il ne reste plus qu'à lancer le résultat avec Wine :
Code : Console
Hé là ! Rien ne se passe !
C'est normal ! Nous avons oublié une particularité de Windows : il faut les bonnes
DLL pour permettre à notre programme de fonctionner.
Nous allons devoir récupérer trois DLL (peut-être plus, en fonction des fonctionnalités que vous avez utilisées dans votre programme Qt). On a deux possibilités : placer les DLL dans
le même dossier que notre programme, ou les placer dans
C:\Windows\system32\.
On va opter pour la première solution, mais vous savez qu'il en existe une autre :
- mingw32m10.dll : elle est fournie avec les paquets mingw32 :
gunzip -c /usr/share/doc/mingw32-runtime/mingwm10.dll.gz > /home/tuto/mon_programme/win32/mingwm10.dll
- QtCore4.dll : elle est dans le dossier bin installé avec Qt Windows :
cp /home/tuto/.wine/drive_c/Qt/4.4.0/bin/QtCore4.dll /home/tuto/mon_programme/win32/QtCore4.dll
- QtGui4.dll : elle est aussi dans le dossier bin installé avec Qt Windows :
cp /home/tuto/.wine/drive_c/Qt/4.4.0/bin/QtGui4.dll /home/tuto/mon_programme/win32/QtGui4.dll
Nous pouvons maintenant relancer notre programme, qui doit alors fonctionner.