Qt 5.8 ist eine sehr umfangreiche Softwarebibliothek, die unter anderem ein großes Widgetset besitzt, aber auch weitere Funktionalitäten, wie Boost-ähnliche Container, Zustandsautomaten und Skriptingsprache. Obendrauf erlaubt diese Bibliothek auch noch die platformübergreifende Entwicklung für PC, Android, iOS, Windows Tablets und noch weitere Zielplatformen. Für mich ist das Grund genug, die Möglichkeit zu prüfen, auf Basis von Qt Teile meiner Spiele zu entwicklen, bzw. einzelne Komponenten davon. Da Qt unter anderem auch eine Datenbank-Abstraktionsebene bietet, möchte ich Qt zusammen mit PostgreSQL einsetzen. Die auf der Qt-Webseite zum Download bereitsgestellten Installationspakete enthalten allerdings keine direkte Unterstützung für PostgreSQL. Damit bleiben nur zwei Möglichkeiten, entweder das Plugin für PostgreSQL wird von mir separat nachträglich kompiliert und ich verwende ein fertiges Paket, oder ich kompiliere Qt komplett aus den Sourcepaketen und binde dabei die PostgreSQL-Funktionalität direkt ein. Ich habe mich für letztere Option entschieden, da ich Qt5.8 eigentlich ursprünglich für Visual Studio 2008 kompilieren wollte. Leider musste ich einsehen, wie der Titel dieses Artikels bereits verät, das VS2008 nun wirklich in die Jahre gekommen ist und Qt damit nicht mehr wirklich gut kompiliert werden kann, zumal es vom Qt-Projekt nicht mehr supported wird. Deshalb und weil ich doch einige Informationen zusammentragen musste um Qt 5.8 zu kompilieren, beschreibe ich im Folgenden, wie ich Qt 5.8 mit Visual Studio 2013 Community Edition kompiliert habe.
Zwischenzeitlich nutze ich aber nun die Visual Studio 2015 Community Edition, weswegen meine aktuellen Arbeiten damit durchgeführt werden. Deshalb habe ich auch den Titel angepasst.
Qt und -static-runtime
Eigentlich ist es ne coole Sache ein statisches Qt mit einer statischen VC-Runtime zu bauen, weil man dann direkt das erzeugte Executable verwenden kann und keine weiteren Abhängigkeiten benötigt. Die Lizenzrechtlichen Angelegenheiten die diesbezüglich die LGPL mitbringt lasse ich hier bewußt außen vor, da es mir nicht um einen Lizenzrechtlichen Aspekt hier geht, sondern um einen technischen. Ich habe einige zeit damit verbracht Qt 5.8 mit statischer Runtime zu kompilieren. Das funktioniert zunächst einmal ganz gut. Bis man an den Punkt kommt, an dem man seine Anwendung linkt. Dann werden nämlich alle statisch kompilierten Bibliotheken erst zur Anwendung zusammen gelinkt. Un da fängt das Problem an. Es müssen wirklich alle Bibliotheken, die in Eurer Anwendung verwendet werden mit der gleichen statischen Runtime gebaut worden sein, mit der ihr auch Qt gebaut habt. Und damit meine ich wirklich alle. Das geht soweit, dass man auch alle Abhängigkeiten die Qt einbindet mit der gleichen statischen Runtime bauen muss. Bei mir hat das dazu geführt, dass ich PostgreSQL mit statischer Runtime hätte bauen müssen, wo es mir dann einfach zu viel wurde. Ich wollte nicht den Großteil meiner Zeit mit Bibliotheken bauen verbringen. Das war den letzten Endes auch der Grund, warum ich mich für eine dynamische Runtime entschieden habe. Das Leben ist jetzt sehr viel einfacher beim Bauen von Bibliotheken.
Damit will ich sagen überlegt es Euch nicht nur zweimal, sondern besser dreimal bevor Ihr anfangt Qt mit statischer Runtime zu bauen. Der dadurch gewonnene Vorteil ist meiner Meinung nach den Aufwand nicht wert.
Vorraussetzungen und Setup
Zur Durchführung benötigt werden:
- Visual Studio 2013 CE - Visual Studio 2015 CE
- Qt 5.8 Windows Source ZIP
- ausreichend Platz auf der Fetsplatte ( ca. ?? GB)
- Python > 2.7
- Perl Strawberry
- (optional) Jom
Zunächst braucht man natürlich eine installierte Version von VS2015 CE. Für das kompilieren von Qt5.8 verwende ich die x64-VS-Commandline. Man findet diese in der Programmgruppe von VS2015 CE. Auf die Installation der VS2015 CE gehe ich hier nicht gesondert ein, da sie selbsterklärend ist.
Mit Hilfe der Kommandozeile legt man sich die Verzeichnisstruktur an, in der später das Kompilat liegen soll. Bei mir sieht das so aus, dass ich zunächst mal einen Entwicklungsordner habe. Dort liegen alle Softwarebibliotheken, die ich in meinen Programmen verwende, wie z.B. Qt. In diesem Verzeichnis lege ich mir ein Unterverzeichnis mit dem Namen "qt" an. Dort werden, dann für jede Version, die ich von Qt kompiliere, Verzeichnisse angelegt. Im Beispiel von Qt5.8.0 lege ich mir also ein Verzeichnis "5.8.0" an. Wenn ich einen reinen Debugbuild kompiliere, ergänze ich den Namen noch um das Suffix "-deb". Das mache ich deshalb weil ich mit dem kompilieren von Qt in Debug und Release im gleichen Buildverzeichnis schlechte Erfahrungen gemacht habe. Damit kann ich später Debug- und Release-Builds auseinanderhalten. Also im konkreten Beispiel sieht dass dan wie folgt aus:
cd d:\devel
mkdir qt
cd qt
mkdir 5.8.0-deb
Ergebnispfad: d:\devel\qt\5.8.0-deb
Sobald dies erledigt ist, kommt der erste Schritt, nämlich das Konfigurieren des Qt-Builds mit dem configure-Skript. Bitte stellt im Vorfeld sicher, dass sowohl perl als auch python im Pfad sind, so dass diese Tools während des späteren Kompiliervorgangs aufrufbar sind. Der Aufruf des configure-Skripts ist der Knackpunkt. Hier muss man genau angeben wass man von Qt alles haben will und von eventuelle 3rd-Partybibliotheken die include- und lib-Verzeichnisse angeben. In meinem Fall ist das z.B. PostgreSQL. Zunächst mal der Aufruf den ich verwende als Beispiel:
configure -debug -prefix %CD% -shared -platform win32-msvc2015 -sql-psql -no-warnings-are-errors -opengl desktop -qt-zlib -nomake examples -nomake tests -I "E:\devel_2017\pgsql\include" -I "E:\devel_2017\qt-ZLib" -L e:\devel_2017\qt-ZLib\x64\Debug -L E:\devel_2017\pgsql\lib
Nun mal die Parameter im einzelnen:
- debug - ist klar, es wird nur die Debug-Version gebaut
- prefix - legt fest wo ich die Kompilate ablege, in meinem Fall im aktuelle Verzeichnis, indem ich configure aufrufe, dazu später mehr.
- shared - Qt wird als DLLs gebaut
- platform gibt proinzipiell den Kompilier an (interessanterweise bleibt das win32-msvc2015 obwoh ich für 64-bit baue
- sql-psql - bedeutet, dass das PostgreSQL-Plugin gebaut wird. Das bedeutet aber auch, dass ich die PostgreSQL libraries und includes verfügbar haben muss.
- no-warning-are-errors - keine Warnings als Errors. Beim ersten Bauen von Qt lass ich diese Einstellung so, später kann man das immer noch ändern. D.h. aber auch, dass der Qt-Build ohne Warnings durchlaufen muss.
- opengl verwende OpenGL im Desktop
- qt-zlib verwende eine externe zLib ( ich verwende hier die gleiche zLib die ich auch in meinen anderen Codeteilen verwende)
- nomake examples baue keine Beispiele ( spart Zeit)
- nomake tests (spart Zeit)
- -I inlucde-Verzeichnisse zu den 3rd-Partybibliotheken
- -L lib-Verzeichnisse zu den 3rd-Partybibliotheken
Dieses Kommando rufe ich immer im Verzeichnis auf in das die Kompilate gebaute werden sollen. Also z.B. liegt mein Qt opensource code in E:\dev-3rd-src\qt-everywhere-opensource-src-5.8.0, aber mein out-of-source build wird dann in E:\devel_2017\qt\5.8-deb liegen. Der Aufruf erfolgt dann in E:\devel_2017\qt\5.8-deb und sieht exakt wie oben angegeben aus. Hier noch mal der Vollständigkeit halber:
Will man Qt statisch bauen, ersetzt man -shared durch -static. Ich würde es grundsätzlich vermeiden, configure mit -static-runtime aufzurufen (siehe seperater Kasten), da man damit in die dependency-Hölle kommt. (Just my 2 cents). Nach dem Ausführen von configure bekommt man am Ende eine Zusammenfassung wie etwa die folgende:
Im Anschluß daran beginnt das Erzeugen der Makefiles. Ich verwende dazu wie vom Qt-Projekt empfohlen anstelle von nmake, jom.
D.h. ich rufe im Verzeichnis e:\devel_2017\qt\5.8.0-static-deb den Befehl jom auf. Jom ist ein Tool, dass paralleles kompilieren erlaubt und von der Qt-Wiki-Webseite heruntergeladen werden kann. Der Aufruf erfolgt dann mit <Pfad-zu-Jom>\jom.exe. Von da an sollte die Kompilierung von Qt laufen. sollte es wieder erwarten während der Kompilierung abbrechen, würde ich es zunächst nochmals neu starten. Wenn dann der Fehler nochmals auftritt, dann sollte man dem Fehler mehr Aufmerksamkeit. Meist befindet sich der einige Zeilen vorher, bevor der eigentlich Kompileabbruch stattgefunden hat.
Kommt man gar nicht mehr weiter, dann kann man sich immer noch an das Qt-Form wenden. ich hatte dort bisher immer hilfsbereite und nette Menschen getroffen.
Soviel erstmal zum Kompilieren von Qt 5.8.0 mit VS 2015 CE.
Fragen und Feedback könnt ihr gerne in den Kommentaren hinterlassen.
Thoran