====== Qt-Programme für 32-Bit Systeme auf einem 64-Bit System kompilieren (Linux) ====== Oftmals soll ein Programm für noch weit verbreitete 32-Bit Systeme erstellt werden, wenn aber nur ein 64-Bit System zur Entwicklung zur Verfügung steht. Da 32-Bit Systeme keine 64-Bit Bibliotheken verwenden können, dürfen ausführbare Dateien nicht einfach von einem 64-Bit System auf ein 32-Bit System kopiert werden. Dieses Problem ist momentan nicht einfach zu lösen, es gibt jedoch einen Weg Qt-Programme entsprechend zu kompilieren. \\ \\ :!: **Diese Anleitung bezieht sich ausschließlich auf Linux-Systeme, genauer gesagt Ubuntu. Vorausgesetzt wird eine funktionierende 64-Bit Installation des Qt-SDKs.** ===== Entwicklungssystem vorbereiten ===== ==== Bibliotheken installieren ==== Zu allererst muss die 32-Bit Version von Qt installiert werden. Das kannst über den Paketmanager der Distribution oder über Konsolenbefehle geschehen. Diese Pakete haben eine ":i386"-Endung, also zum Beispiel "libqtgui4:i386". Es sollten zumindest die Qt-Module "Core" und "Gui" installieren, der Rest je nach Bedarf. Außerdem wird noch das Paket "libc6-dev-i386" benötigt. ==== Links zu den Bibliotheken erstellen ==== Nun sollte sich alles am Rechner befinden, das zum Erstellen einer 32-Bit ELF benötigt wird. Bei der Installation der 32-Bit Bibliotheken wird aber ein entscheidender Fehler gemacht. Es werden nämlich keine Links erstellt, um die Bibliotheken mit ihrem richtigen Namen zu verwenden. Das kann relativ leicht mit Links korrigiert werden: $ cd /usr/lib32 $ sudo ln -s libstdc++.so.6 libstdc++.so $ cd /usr/lib/i386-linux-gnu $ sudo ln -s libQtCore.so.4 libQtCore.so $ sudo ln -s libQtGui.so.4 libQtGui.so ==== Konfigurationsdateien kopieren ==== Bei der 32-Bit Installation fehlen außerdem noch ein paar Konfigurationsdateien. Es können entweder jene der 64-Bit Version verwendet werden oder entsprechende Kopien der Dateien im richtigen Verzeichnis. $ cd /usr/lib/x86_64-linux-gnu $ sudo cp *.prl ../i386-linux-gnu/ ==== Projekt erstellen ==== Das Qt-Projekt kann ganz normal mit den üblichen Befehlen erstellt werden. $ qmake -project $ qmake ==== Makefile korrigieren ==== Am Makefile müssen noch einige Parameter und Pfade korrigiert werden. Die zu ändernden Teile sind ziemlich offensichtlich. Das "-m64" muss weg und durch "-m32" ersetzt werden. Außerdem sind die Verzeichnisse für den Linker "/usr/lib/i386-linux-gnu/" und "/usr/lib32/". Noch ein paar Kleinigkeiten, die im diff sicher leicht zu erkennen sind: --- Makefile 2012-07-14 17:25:57.937851716 +0200 +++ Makefile2 2012-07-14 17:24:37.733855068 +0200 @@ -1,6 +1,6 @@ ############################################################################# # Makefile for building: test # Generated by qmake (2.01a) (Qt 4.8.1) on: Sat Jul 14 17:25:57 2012 # Project: test.pro # Template: app # Command: /usr/bin/qmake -o Makefile test.pro @@ -11,12 +11,12 @@ CC = gcc CXX = g++ DEFINES = -DQT_WEBKIT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -CFLAGS = -m64 -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) -CXXFLAGS = -m64 -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) -INCPATH = -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. +CFLAGS = -m32 -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) +CXXFLAGS = -m32 -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) +INCPATH = -I/usr/share/qt4/mkspecs/linux-g++-32 -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. LINK = g++ -LFLAGS = -m64 -Wl,-O1 -LIBS = $(SUBLIBS) -L/usr/lib/x86_64-linux-gnu -lQtGui -lQtCore -lpthread +LFLAGS = -m32 -Wl,-O1 +LIBS = $(SUBLIBS) -L/usr/lib/i386-linux-gnu/ -L/usr/lib32/ -lQtGui -lQtCore -lpthread AR = ar cqs RANLIB = QMAKE = /usr/bin/qmake @@ -102,7 +102,7 @@ $(TARGET): $(OBJECTS) $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) -Makefile: test.pro /usr/share/qt4/mkspecs/linux-g++-64/qmake.conf /usr/share/qt4/mkspecs/common/unix.conf \ +Makefile: test.pro /usr/share/qt4/mkspecs/linux-g++-32/qmake.conf /usr/share/qt4/mkspecs/common/unix.conf \ /usr/share/qt4/mkspecs/common/linux.conf \ /usr/share/qt4/mkspecs/common/gcc-base.conf \ /usr/share/qt4/mkspecs/common/gcc-base-unix.conf \ @@ -127,8 +127,8 @@ /usr/share/qt4/mkspecs/features/yacc.prf \ /usr/share/qt4/mkspecs/features/lex.prf \ /usr/share/qt4/mkspecs/features/include_source_dir.prf \ - /usr/lib/x86_64-linux-gnu/libQtGui.prl \ - /usr/lib/x86_64-linux-gnu/libQtCore.prl + /usr/lib/i386-linux-gnu/libQtGui.prl \ + /usr/lib/i386-linux-gnu/libQtCore.prl $(QMAKE) -o Makefile test.pro /usr/share/qt4/mkspecs/common/unix.conf: /usr/share/qt4/mkspecs/common/linux.conf: @@ -155,8 +155,8 @@ /usr/share/qt4/mkspecs/features/yacc.prf: /usr/share/qt4/mkspecs/features/lex.prf: /usr/share/qt4/mkspecs/features/include_source_dir.prf: -/usr/lib/x86_64-linux-gnu/libQtGui.prl: -/usr/lib/x86_64-linux-gnu/libQtCore.prl: +/usr/lib/i386-linux-gnu/libQtGui.prl: +/usr/lib/i386-linux-gnu/libQtCore.prl: qmake: FORCE @$(QMAKE) -o Makefile test.pro ==== Programm kompilieren ==== Schlussendlich kann das Programm ganz normal kompiliert werden. $ make g++ -c -pipe -m32 -O2 -Wall -W -D_REENTRANT -DQT_WEBKIT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++-32 -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -o main.o main.cpp g++ -m32 -Wl,-O1 -o test main.o -L/usr/lib/i386-linux-gnu/ -L/usr/lib32/ -lQtGui -lQtCore -lpthread Dadurch wird folgende Datei erstellt: $ file test test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x82e53f9a66cafeaca2494ff0a6fa3c62885ca2c5, not stripped Das ganze natürlich auf einem 64-Bit System: $ uname -a Linux xps 3.2.0-26-generic #41-Ubuntu SMP Thu Jun 14 17:49:24 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux ==== Programm ausführen ==== Nun kann die ausführbare Datei einfach auf ein 32-Bit System kopiert werden. Dieses System muss aber die entsprechenden Laufzeit-Bibliotheken (in diesem Fall also 32-Bit) installiert haben.