In der Java-Welt gibt es schon lange die sinnvolle Konvention kompilierte class-Dateien in einer anderen Verzeichnisstruktur abzulegen als den Quellcode. So eine eine Konvention hat viele Vorteile:

  • Falls der Quellcode in ein Versionskontrollsystem eingecheckt wird (und das sollte er auf jeden Fall), müssen nicht umständliche Regeln zum Excluden der kompilierten Dateien geschrieben werden.
  • Dateioperationen im Source-Tree (z. B. ein Aufruf von find oder grep) müssen nicht aufwendig um die kompilierten Dateien herumgelenkt werden

Leider ist dies in der C++-Welt teilweise noch nicht ganz angekommen, deshalb hier ein kurzer Reminder, wie solche “Out-of-Source Builds” mit CMake gemacht werden können.

Das schöne an CMake ist, dass man eigentlich gar nichts tun muss, um ein Out-of-Source Build zu erstellen. Angenommen die Projektstruktur sie so aus:

languitar@bird /tmp/cmakeexample $ find .
./bin
./src
./src/yourCodeHere.cpp
./CMakeLists.txt

Um jetzt ein Out-of-Source Build zu erstellen, bei dem alle kompilierten Dateien in bin abgelegt werden, reicht es in das bin-Verzeichnis zu navigieren und dort cmake .. aufzurufen. Alle Dateien, die CMake intern benötigt, inklusive des generierten Makefiles,  und alle Ergebnisse des Compilers / Linkers werden so in bin angelegt und sowohl src als auch der Projektordner bleiben unangetastet. Diese Vorgehen hat bei CMake auch noch einen besonderen Vorteil: Eigentlich sollte CMake Änderungen an der CMakeLists.txt eigenständig feststellen und das Makefile neu generieren beim Bauen. Das klappt des Öfteren jedoch nicht richtig. Hätte man CMake im Projektverzeichnis aufgerufen müsste man dort jetzt mühselig alle von ihm generierten Dateien wie den CMakeCache.txt löschen um von vorne anzufangen. Im Falle eines Out-of-Source Builds kann man hingegen bedenkenlos und einfach den Build-Ordner leeren.

Ein paar Kleinigkeiten muss man für saubere Out-of-Source Builds mit CMake allerdings doch noch beachten. Auch wenn CMake das eigentliche Bauen und das Verwalten der internen Dateien sauber im Build-Ordner durchführt, verhindert es keine Fehler durch den Anwender. Falls man CMake z. B. noch selbst benutzt um Dateien zu generieren (z. B. pkg-config Files) sollten diese auch im Build-Ordner erstellt werden. Dieses Verzeichnis kann man in CMake mit den Variablen CMAKE_BINARY_DIR bzw. CMAKE_CURRENT_BINARY_DIR abfragen. Dateien sollten also immer über diese Variablen gespeichert werden und nicht über CMAKE_SOURCE_DIR bzw. CMAKE_CURRENT_SOURCE_DIR. Im Falle eines “In-Source” Builds (also der Aufruf cmake . im Projektordner) zeigen CMAKE_BINARY_DIR und CMAKE_SOURCE_DIR etc. übrigens auf dieselben Verzeichnisse.