Fremde Welten
Crosscompiler – Entwickeln für andere Systeme
Wer manchmal selbst programmiert oder Software kompiliert, der kennt die üblichen Prozeduren, um ein einfaches C-Programm zu compilieren und auszuführen, wie
gcc -Wall -o helloworld helloworld.c ; ./helloworld
oder auch den Dreisatz ./configure; make; make install, um Programme einzurichten, die das GNU-Automake-System verwenden. Daneben gibt es noch etliche andere Build-Systeme wie etwa Cmake, Scons und Konsorten. Üblicherweise liegt der Software eine Datei INSTALL bei, die (hoffentlich gut) dokumentiert, wie man das Programm übersetzt und auf dem System einrichtet.
Was haben alle diese Prozeduren und Anleitungen – so verschieden sie erscheinen mögen – gemeinsam? Klar: Man kompiliert das Programm üblicherweise auf dem selben System, auf dem man es später auch ausführt. Freilich lässt sich ein fertig übersetztes Programm auch auf andere Rechner transferieren oder auch bereits als Binary herunterladen – aber das Betriebssystem und die CPU-Architektur der Zielplattform muss passen. Linux-Software läuft auf Windows gar nicht, und auch umgekehrt geht es per Wine nur recht mühsam. Von anderen Systemen, wie OpenSolaris oder Irix schweigt des Sängers Höflichkeit.
Crosscompiler
Hier kommen Crosscompiler in Spiel, also Compiler, die Programme für ein anderes Zielsystem erzeugen. Dabei können sich alle Komponenten des sogenannten Targets unterscheiden, sei es das Betriebssystem, die Registerbreite (von 8 bis 64 Bit) oder sogar der CPU-Typ an sich. Die Zielplattform muss nicht einmal real existieren: So portierte etwa das Projekt Trillian [1] den Linux-Kernel schon auf die Intel-IA64-Plattform ("Itanium"), bevor es eine entsprechende CPU überhaupt gab – der Linux-Port lief vorher nur in einem Simulator.
Portierungen auf eine noch gar nicht existierendes Target dürften freilich eher die Ausnahme darstellen. Doch selbst, wenn die Zielplattform bereits physikalisch existiert, gibt es anfangs in der Regel weder ein Betriebssystem noch einen Compiler darauf. Beides gilt es also auf einem anderen System für das neue Target zu übersetzen – das nennt der Fachmann Bootstrapping.
Gelegentlich kommt es auch vor, dass die Zielplattform zwar existiert, man aber keinen Zugriff darauf hat. Möglicherweise läuft darauf auch ein Closed-Source-Betriebssystem, das man als Open-Source-Verfechter nicht anfassen will – oder schlicht die Lizenzgebühren für Betriebssystem und Entwicklungstools nicht zahlen kann oder möchte. In vielen Fällen ziehen es Entwickler aber auch schlicht vor, die gewohnten und bewährten Entwicklungstools zu nutzen, um Executables für andere Plattformen zur Verfügung zu stellen.
Ein gängiges Einsatzfeld für Crosscompiling stellen daneben Embedded-Systeme dar: kleine und kleinste Rechner mit mickrigen CPUs, wenig RAM und kaum Massenspeicher. Selbst wenn die Ressourcen eines solchen Systems ausnahmsweise einmal für den Compiler und dessen Infrastruktur ausreichen, kann man in aller Regel durch Crosscompiling auf einem leistungsfähigen Rechner sehr viel Zeit sparen.
Möglicherweise haben auch Sie schon einmal mit einem Crosscompiler gearbeitet, ohne sich dessen bewusst zu sein: Auf 64-Bit-Linux-Systemen ist der GNU-Compiler gcc so installiert, dass er sowohl 32- als auch 64-Bit-Executables erzeugen kann. Es handelt sich also um einen sogenannten Bi-Arch-Compiler: In der Vorgabe übersetzt er Programme wie das typische helloworld.c aus Listing 1 für ein 64-Bit-System; über die Option -m32 weisen Sie ihn im Bedarfsfall an, ein 32-Bit-Binary zu erzeugen (Listing 2).
Listing 1
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
Listing 2
$ gcc -Wall -o helloworld helloworld.c $ file helloworld helloworld: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, not stripped $ gcc -Wall -m32 -o helloworld helloworld.c $ file helloworld helloworld: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, not stripped
Windows als Target
Warum sollte jemand unter Linux ausgerechnet für Microsoft Windows entwickeln wollen? Ganz einfach: Eine Windows-Version der eigenen Software verbreitert das Zielpublikum deutlich, und das sogar, ohne dass man dafür ein Windows-System benötigt. Zudem erspart das Crosscompiling hier die Pflege verschiedener Build-Systeme – etwa Autoconf/Automake für Linux und diverse andere Unix-Varianten sowie zusätzlich Visual-C-Projekte für Windows.
Entsprechende Windows-Crosscompiler bringen die meisten Distribution bereits in ihren Repositories mit. Unter Debian/Ubuntu genügt beispielsweise der Befehl apt-get install mingw32, um den Crosscompiler zu installieren. Das Kürzel Mingw steht für "Minimalist GNU for Windows", eine minimale Portierung der GNU-Entwicklungstools auf Windows. Im Gegensatz zu Cygwin, einer umfassenden Portierung der GNU-Umgebung auf Windows, braucht man hier keine zusätzliche DLLs als Emulationsschicht.
Bei Opensuse 11.3 fehlt ein Windows-Crosscompiler im Standard-Repository, lässt sich jedoch recht einfach vom Opensuse-Server nachziehen. Dazu fügen Sie in YaST unter Software | Software-Repositories das Software-Repository:
http://download.opensuse.org/repositories/CrossToolchain:/mingw/openSUSE_11.3/
hinzu und installieren anschließend das Paket cross-mingw-gcc über Yast2 nach. Ist der Crosscompiler schließlich im System installiert, übersetzen Sie beispielsweise das helloworld.c aus Listing 1) kurzerhand als Windows-Programm (Listing 3).
Listing 3
$ /opt/cross/bin/i386-mingw32msvc-gcc -Wall -o helloworld.exe helloworld.c $ file helloworld.exe helloworld.exe: PE32 executable for MS Windows (console) Intel 80386 32-bit
Das resultierende Programm helloworld.exe, hergestellt nur mit freier Software, lauft nur auf Windows (bitte testen, wenn vorhanden) – oder unter Linux mit Hilfe von Wine.
Unter Debian/Ubuntu funktioniert das Ganze nahezu identisch, nur heißt der Compiler in diesem Fall i586-mingw32msvc-gcc und liegt direkt unter /usr/bin. Zum Übersetzen des kleinen Windows-Programms genügt also der Befehl
$ i586-mingw32msvc-gcc -Wall -o helloworld.exe helloworld.c
Lassen Sie die Option -o mit dem Namen der Ausgabedatei (-o helloworld.exe) weg, lautet der Standard-Dateiname des Binaries unter Unix a.out. Unter Windows ist die Dateierweiterung relevant, der Vorgabename lautet hier daher a.exe.



