Die langen Kompilationszeiten bei C++ ...
Haben Sie auch Angst vor dem nächsten recompile all? Hüten Sie sich schon seit langer Zeit davor, Änderungen an einer zentralen Basisklasse Ihres Projekts vorzunehmen, weil Sie dann erst einmal eine halbe Stunde auf den Compiler warten müssen? Dann sind vorkompilierte Header vielleicht etwas für Sie!
Vorkompilierte Header sind letztendlich ein Hack für das archaische include-System von C++ (und auch
von C). Hierbei werden durch die #include
-Direktive des Präprozessors benötigte Deklarationen
einer .cpp
Datei aus den Header-Dateien geparst. Da Header-Dateien ihrerseits meist
weitere Header-Dateien inkludieren, und das Parsen eines Headers nicht-trivial sein kann (zum
Beispiel wegen Templates oder ähnlichem), dauert dies oft sehr lange, und verschlingt in der Regel
den größten Teil der Kompilationszeit.
In vielen Fällen inkludieren die Quelldateien eines Projekts aber die gleichen Dateien. Vorkompilierte Header verwenden heißt also, wie der Name schon andeutet, das Ergebnis des Parsens einer Header-Datei abzuspeichern und für das Kompilieren möglichst vieler Quelldateien zu nutzen. Natürlich macht das nur dann Sinn, wenn das Projekt auch wirklich viele Quelldateien enthält.
Vorkompilierte Header werden zum Beispiel von den Microsoft C++ Compilern unterstützt. Der gcc wird vorkompilierte Header ab Version 3.4 unterstützen.
Vorkompilierte Header mit Microsoft Visual C++
Visual C++ bietet eine Automatik für vorkompilierte Header an. Diese funktioniert nur in Ausnahmefällen, nämlich bei MFC-Projekten, die mit Wissen um die Automatik geschrieben sind. Zudem merkt man als Entwickler nicht, wenn die automatische Funktion die falschen Einstellungen vorgenommen hat - das Projekt kompiliert dann nur deutlich langsamer als ganz ohne vorkompilierte Header, weil die vorkompilierten Header-Dateien erzeugt und auf die Festplatte geschrieben, dann aber nicht benutzt werden! Es ist dies auch der Grund dafür, das vorkompilierte Header einen schlechten Ruf besitzen und oft empfohlen wird, sie einfach auszuschalten.
Alles in allem ist es also unbedingt empfehlenswert, die Konfiguration der vorkompilierten Header in den Projekt-Einstellungen per Hand vorzunehmen. Die Schritte dazu sind im Folgenden beschrieben.
- Zunächst muss man eine Header-Datei identifizieren, die von möglichst allen Quelldateien benötigt
und zumindest indirekt inkludiert wird. In Frage kömmt je nach verwendeten Bibliotheken zum Beispiel
windows.h
oderqmainwindow.h
, aber auch STL-Bibliotheken wieiostream
. Gibt es mehrere solcher Include-Dateien, legt man eine neue Include-Dateiprecompiled.h
an, die genau diese fraglichen Dateien inkludiert, und sonst nichts tut. Im folgenden gehe ich davon aus, dassprecompiled.h
der Name der vorkompilierten Header-Datei ist. -
Nun nimmt man in das Projekt eine Datei
precompiled.cpp
auf, deren einzige Nicht-Kommentar-Zeile#include "precompiled.h"
ist. -
Alle anderen Quelldateien im Projekt modifiziert man dahingehend, dass sie als erste Zeile
precompiled.h
inkludieren. Stellen Sie außerdem sicher, dass all diese Dateien mit den gleichen Compiler-Einstellungen kompiliert werden. Sollten diese beiden Dinge für einige Dateien nicht möglich oder sinnvoll sein, sind im nun folgenden Schritt die betroffenen Dateien von der Verwendung vorkompilierter Header auszunehmen. -
Nun werden die Projekteinstellungen in folgender Weise verändert (in VC6: Projekt ->
Einstellungen -> C/C++ -> Vorkompilierte Header):
- Für das gesamte Projekt: Vorkompilierte Header verwenden durch Header
precompiled.h
. - Für die Datei
precompiled.cpp
: Vorkompilierte Header erstellen durch Headerprecompiled.h
. - Für Quelldateien, in denen man in der ersten Zeile
precompiled.h
nicht inkludieren konnte: Vorkompilierte Header nicht verwenden
- Für das gesamte Projekt: Vorkompilierte Header verwenden durch Header
- Dann kompilieren Sie neu, und staunen Sie über die Geschwindigkeit!
Wenn Sie einen Fehler gemacht haben, erhalten Sie glücklicherweise eine einigermaßen nachvollziehbare Fehlermeldung.
Nachteile
Vorkompilierte Header haben einen schlechten Einfluss auf die Programmier-Regel, die Anzahl der
include-Abhängigkeiten
möglichst gering zu halten. Durch die Aufnahme eines Headers in precompiled.h
, der von
vielen, aber längst nicht allen Quelldateien benötigt wird, beschleunigt sich die Kompilation im
Allgemeinen! Auch wenn dies also verlockend erscheinen mag, sollte man im Sinne des Software-Engineerings
darauf verzichten.
Ansonsten ist der einzige Nachteil vorkompilierter Header der, dass Ihr schöner neuer Rechner, den Sie sich extra zum Kompilieren beschaffen wollten, nun noch lange wird warten müssen. Eine Beschleunigung des Kompilierens um den Faktor zwei bis zehn ist je nach Projekt völlig realistisch.