C++ Programm von Windows auf Linux portieren
Ich zeige euch wie man ein C++ Programm von Windows auf Linux portieren kann. Im letzten Artikel habe ich euch bereits CodeLite für den Raspberry Pi vorgestellt, nun werden wir diese Entwicklungsumgebung und den GCC Compiler verwenden um ein und das selbe Programm auf verschiedene Systeme zu portieren. Im Anschluss daran werden wir das Programm noch von einer x86 auf eine ARM Architektur übernehmen.
C++ Programm von Windows auf Linux portieren
Nachdem heute vermehrt mit Java und C# entwickelt wird, verlieren die jungen Programmierer langsam das Verständnis über unterschiedliche Systeme. Java hat den Vorteil, dass der selbe Code auf allen Systemen läuft. Er wird in der JVM, einer virtuellen Umgebung, ausgeführt. In den letzten 10 Jahren hat sich der Nachteil von viel langsameren Programmen gegenüber C++ immer weiter verbessert. Heute besteht nur noch wenig Unterschied. Aus diesem Grund macht es meist keinen Sinn nicht Java oder C# zu entwickeln. Ein Java Konsolenprogramm würde auf Anhieb unter Windows oder Linux funktionieren und auch unter einer ARM Architektur.
Beispiel
Als Beispiel nehme ich ein unter und für Windows entwickeltes Konsolenprogramm. Heightmap erstellt geführt über mehrere Abfragen eine Heightmap (eine Schwarz/Weiß Bitmap für Höhendaten). Die genaue Theorie dahinter findet ihr in meinem Buch „Terrain Rendering mit Geometrie Clipmaps für Spiele„. Aus dieser kann man ein Terrain für Spiele oder Simulationen erstellen. Es gibt zahlreiche Algorithmen die diese Heightmap für bestimmte Landschaften mit mehr oder weniger Realismus erstellen (dazu in einem anderen Artikel mehr). Die Komplexität des Programms besteht hauptsächlich aus Algortihmen, weshalb die Portierung relativ einfach sein wird.
Wenn man sich beim Programm durcharbeitet bekommt man als Ergebnis mehrere Bilder. Darunter eine Höhenkarte des erstellten Terrains und eine texturierte Version, die man rein theoretisch bereits für die Simulation verwenden könnte.
Source Code unter Linux
Den vollständigen Source Code findet ihr auf meiner GitHub Projektseite. Dort gibt es neben den Windows Source Code auch den bereits angepassten für Linux. Wir gehen nun aber vom Windows Source Code aus und erstellen dafür unser CodeLite Projekt. Ich erstelle deshalb ein neues leeres gcc Konsolenprogramm Projekt mit dem Namen Heightmap. Darauf hin wird das Projekt mit einem Hello World main.c angelegt.
Die main.c können wir nun löschen, dafür kopieren wir uns aber den kompletten Quellcode vom Windows Source Code in den Projektordner. Dabei ist auch eine *.vcproj Datei, welche wir entweder nicht mit kopieren oder löschen. CodeLite kann mit der Visual Studio Projektdatei nichts anfangen.
Dateien ins CodeLite Projekt aufnehmen
Wenn ihr die main.c Datei korrekt entfernt habt solltet euer Projektverzeichnis in CodeLite bis auf den virtuellen src Order vollständig leer sein. Mit einem Rechtsklick auf den src Ordner und „Add an existing File…“ wählen wir nun alle *.cpp und *.h Dateien aus. Diese erscheinen dann im CodeLite Projektbaum. Wir fügen nun noch einen virtuellen Folder mit dem Namen „header“ ein und ordnen alle *.cpp Dateien dem src Ordner zu und alle *.h Dateien dem header Ordner. Das ist zwar nicht unbedingt notwendig, gerade bei größeren Projekten aber übersichtlicher.
Bibliotheken
Damit eine Heightmap auch als *.bmp Bild gespeichert werden kann benutzt das Programm die EasyBMP Bibliothek. Es macht kaum Sinn etwas neu zu entwickeln, dass man bereits fertig und optimiert einbinden kann. So auch für die Arbeit mit BMP Dateien. Dazu erstellen wir einen EasyBMP Ordner, die Unterordner src un header und fügen erneut die existierenden Dateien hinzu. Das Projekt sieht dann so aus:
main
Wenn man versucht das Projekt zu erstellen, dann wirft der Compiler gleich mal eine Fehlermeldung. Die windows.h Datei konnte nicht gefunden werden, klar, die gibt es unter Linux nicht. Wir müssen den Code portieren. Da ich das Programm vor vielen Jahren geschrieben habe weiß ich nicht wofür diese Header überhaupt eingebunden wurde. Eine Quick und Dirty Fehlersuche ist nun recht einfach:
- windows.h entfernen
- neu compilieren
Der nächste Versuch endet wie erwartet in einer Fehlermeldung und zeigt, warum die windows.h eingebunden war:
Beim Anlegen eines neuen Projekts damals unter Visual Studio und Windows wurde die main Methode passend für Windows erzeugt. Unter Linux muss jedes Programm einen Statuscode zurückgeben. Das ist normalerweise 0, beziehungsweise im Fehlerfall eine Nummer höher als 0 (das entspricht dann der hoffentlich dokumentierten Fehlernummer). Die Lösung ist nun aus einem:
void main()
ein
int main()
zu machen. Wer es ganz sauber haben will gibt am Ende der Main Funktion 0 zurück.
Korrekte Header
Bleibt nur noch eine Fehlermeldung über:
Die Funktion srand war offenbar ebenfalls in der windows.h Datei definiert. Die Lösung ist nun recht einfach, wir benötigten nur die richtige Header Datei für die Zulfallswerte. In der C++ Referenz erfährt man, dass diese Funktion zur cstdlib Bibliothek gehört, weshalb wir einfach diese Bibliothek einbinden und dann neu compilieren.
#include <cstdlib>
Schon klappt es und das Programm erscheint im neu geöffneten Konsolenfenster. Gratulation, du hast soeben das erste Windows Programm auf Linux portiert!
Fazit
Ich habe euch an einem Beispiel gezeigt wie man ein C++ Programm von Windows auf Linux portieren kann. Das war in diesem Fall recht einfach. Gerade Konsolenprogramme sind oft sehr simpel zu portieren. Sobald große Grafikbibliotheken Dabei sind (Windows GUI, Direct X usw…) wird das erheblich komplizierter. Nichts ist jedoch unmöglich.