Dieses Dokument gibt einen schnellen Überblick über CMake – eine plattformübergreifende Alternative zu Linux Makefiles und make. Für Hilfe bei der Verwendung von make und Makefiles ohne CMake, lesen Sie bitte die Dokumentation von Prof. Newhall. Dieses Dokument wurde für cmake Version 2.6 geschrieben, das auf den Labormaschinen über stow installiert ist (Stand: Januar 2009).
Ich persönlich mag CMake, weil es mir intuitiver erscheint als das Schreiben eines Standard-Makefiles. Einfache und alltägliche Dinge sind ziemlich einfach und schwierigere Dinge sind möglich, obwohl das meiste, was ich baue, ziemlich einfach ist. Um CMake zu demonstrieren, habe ich einige Beispiele in die Datei cmake.tgz (4 KB) eingefügt. Speichern Sie die Datei und entpacken Sie den Inhalt irgendwo in Ihrem Verzeichnis. Zum Beispiel:
$ tar xzvf cmake.tgz$ cd cmake$ lsCMakeLists.txt w01-cpp/
CMake wird durch das Schreiben von Anweisungen in CMakeLists.txt-Dateien gesteuert. Jedes Verzeichnis in Ihrem Projekt sollte eine CMakeLists.txt Datei haben. Das Schöne an CMake ist, dass die CMakeLists.txt Dateien in einem Unterverzeichnis die Eigenschaften des übergeordneten Verzeichnisses erben, wodurch die Menge an doppeltem Code reduziert wird. Für unser Beispielprojekt haben wir nur ein Unterverzeichnis: w01-cpp. Die Datei CMakeLists.txt für das übergeordnete cmake-Verzeichnis ist recht einfach, demonstriert aber einige wichtige Funktionen.
cmake_minimum_required(VERSION 2.6)project(CMAKEDEMO)#There are lots of scripts with cmake#for finding external libraries. #see /usr/local/share/cmake-2.6/Modules/Find*.cmake for more examplesfind_package(GLUT)find_package(OpenGL)set(CMAKE_CXX_FLAGS "-g -Wall")add_subdirectory(w01-cpp)
Dieser Demo-Code enthält Code, der externe OpenGL-Bibliotheken für Grafiken benötigt. In einer typischen Makefile-Konfiguration müssten wir wahrscheinlich angeben, wo sich die OpenGL-Header-Dateien befinden, z.B. -I/usr/local/include, welche Bibliotheken verwendet werden sollen, z.B. -lGL -lGLU -lglut, und wo die Bibliotheken liegen. Der Ort der Header-Dateien und Bibliotheken variiert wahrscheinlich von Installation zu Installation und von Plattform zu Plattform. Normalerweise gibt es jedoch einige Standardorte, an denen man suchen kann, und CMake automatisiert diese Suche mit find_package-Makros. So findet find_package(GLUT) und find_package(OpenGL) den Ort der Header-Dateien und Bibliotheken und stellt die gängigsten Bibliotheken ein, die in einem typischen OpenGL-Projekt eingebunden werden. CMake bietet Unterstützung für das Auffinden vieler Pakete. Siehe /usr/local/share/cmake-2.6/Modules/Find*.cmake für weitere Beispiele. Um eines dieser Skripte zu verwenden, verwenden Sie find_package(PKGname), wenn das CMake-Skript FindPKGname.cmake heißt.
Weitere Informationen über das Auffinden externer Bibliotheken oder das Erstellen eigener find package-Makros finden Sie im KitWare-Wiki zu diesem Thema.
Sie können gängige Flags setzen, die Sie in einem typischen Makefile mittelsset(VARNAME VALUE) setzen würden. In diesem Beispiel habe ich Debugging-Symbole (-g) und alle Warnungen (-Wall) aktiviert. Außerdem habe ich diesem CMake-Projekt mit project(CMAKEDEMO) einen Namen gegeben. Sie können Ihr Projekt benennen, wie Sie wollen. Wir werden diese Informationen in der Datei CMakeLists.txt im Verzeichnis w01-cpp verwenden. Schließlich geben wir an, dass sich der Großteil des Codes wirklich im w01-cpp befindet, indem wir unserer CMakeLists.txt-Datei auf oberster Ebene die Anweisung add_subdirectory(w01-cpp)
Werfen wir einen Blick auf die CMakeLists.txt-Datei im Unterverzeichnis w01-cpp:
include_directories(${CMAKEDEMO_SOURCE_DIR}/w01-cpp)link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp)#the one C fileadd_executable(cdemo cdemo.c)target_link_libraries(cdemo m) #link the math library#these are all compiled the same wayset(PROGRAMS oglfirst pointers)set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m)foreach(program ${PROGRAMS}) add_executable(${program} ${program}.cpp) target_link_libraries(${program} ${CORELIBS})endforeach(program)#building just a library. add_library(geometry geometry.cpp)add_executable(test_geometry test_geometry.cpp)#linking against a custom librarytarget_link_libraries(test_geometry ${CORELIBS} geometry)
Das include_directories-Makro sagt CMake, wo es nach Quelldateien suchen soll. Durch die Deklaration des Projektnamens CMAKEDEMO in der Datei CMakeLists.txt auf oberster Ebene werden die Variablen CMAKEDEMO_SOURCE_DIR und CMAKEDEMO_BINARY_DIR in Abhängigkeit vom aktuellen Speicherort Ihres Codes und dem aktuellen Speicherort Ihres Build-Verzeichnisses gesetzt (mehr zu letzterem Speicherort später). Das Hinzufügen eines Ziels für eine neue binäre ausführbare Datei ist einfach. Fügen Sie einfach eine Zeile add_executable(cdemo cdemo.c) ein. CMake findet den Compiler automatisch anhand der Dateityp-Erweiterung heraus. Wenn zusätzliche Bibliotheken benötigt werden, können Sie CMake mit target_link_libraries(cdemo m) anweisen, gegen diese zu linken. Dies teilt CMake mit, dass das cdemo-Programm gegen die mathematische Bibliothek gelinkt werden muss. Sie können gegen mehr als eine Bibliothek linken, indem Sie die Bibliotheken in einer Liste angeben. Siehe zum Beispiel set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m). Die Variablen GLUT_LIBRARY und OPENGL_LIBRARY werden von CMake gesetzt, wenn wir find_package(GLUT) und find_package(OpenGL) verwenden. Um herauszufinden, welche Variablen bei der Verwendung von find_package gesetzt werden, müssen Sie wahrscheinlich die entsprechende Datei Find*.cmake öffnen und die normalerweise hilfreiche, aber knappe Dokumentation lesen.
Da mehrere Programme in diesem w01-cpp-Ordner auf die gleiche Weise kompiliert und gegen dieselben Bibliotheken gelinkt werden, können wir sie alle mit einer einfachen Schleife verarbeiten, wie oben gezeigt, indem wir das foreach-Makro in CMake verwenden. Schließlich zeigen wir, wie wir unsere eigene Bibliothek mit add_library(geometry geometry.cpp) erstellen und gegen diese Bibliothek mit target_link_libraries(test_geometry ${CORELIBS} geometry) linken.
Das Einrichten einer Reihe von CMakeLists.txt Dateien wird Ihnen nicht sofort erlauben, Ihr Projekt zu bauen. CMake ist nur ein plattformübergreifender Wrapper für traditionellere Build-Systeme. Im Falle von Linux bedeutet dies make. Ein kurzer Vorverarbeitungsschritt wird Ihre CMakeLists.txt-Beschreibung automatisch in ein traditionelles make-Build-System umwandeln. Ein nettes und sehr empfehlenswertes Feature von CMake ist die Möglichkeit, Out-of-Source-Builds zu erstellen. Auf diese Weise können Sie alle Ihre .o-Dateien, verschiedene temporäre abhängige Dateien und sogar die ausführbaren Binärdateien erstellen, ohne Ihren Quellcode-Baum durcheinander zu bringen. Um Out-of-Source-Builds zu verwenden, erstellen Sie ein Build-Verzeichnis in Ihrem Top-Level-Ordner (technisch gesehen kann dies überall sein, aber der Top-Level-Projektordner scheint eine logische Wahl zu sein). Wechseln Sie dann in Ihr Build-Verzeichnis und führen Sie cmake aus, wobei Sie auf das Verzeichnis der CMakeLists.txt der obersten Ebene zeigen. Zum Beispiel:
cumin$ cd cmake/cumin$ lsCMakeLists.txt w01-cpp/cumin$ mkdir buildcumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ cd build/cumin$ cmake ..
Gedenken Sie daran, dass Sie sich in Ihrem Build-Verzeichnis befinden und cmake nur auf das Verzeichnis verweisen, das die CMakeLists.txt Datei der obersten Ebene enthält, nicht auf die Datei selbst. Wenn alles gut geht, verarbeitet cmake Ihre CMakeLists.txt Dateien, findet den Ort aller Bibliotheken und Include-Pfade und spuckt einen Haufen Konfigurationsinformationen einschließlich eines traditionellen Makefiles in Ihr Build-Verzeichnis. (Wenn Sie mit autotools/autohell vertraut sind, ist dieser cmake-Prozess ähnlich wie ./configure). Sie sind nun bereit, mit dem traditionellen make-System zu bauen. Führen Sie make in Ihrem Build-Verzeichnis aus, um alles zu kompilieren und zu linken. CMake fügt sogar ein paar nette Farben und Fortschrittsbalken ein und unterdrückt eine Reihe von gcc-Ausgaben. Wenn Sie eine ausführliche Ausgabe wünschen, können Sie VERBOSE=1 make eingeben (hilfreich, wenn etwas schief geht).
Aufgrund der Art und Weise, wie wir das Out-of-Source-Build und die link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp) eingerichtet haben, befinden sich unsere frisch kompilierten Binärdateien im Ordner w01-cpp im Build-Verzeichnis, in dem wir gerade make ausgeführt haben.
cumin$ cd w01-cpp/cumin$ lsCMakeFiles/ cdemo* libgeometry.a pointers*Makefile cmake_install.cmake oglfirst* test_geometry*cumin$ ./cdemo Sqrt(2) = 1.4142 This concludes a short C democumin$ ./oglfirst cumin$ ./test_geometry
Drücken Sie ESC, um die OpenGL-Demos zu beenden.
Wenn Sie Code in Ihrem Quellverzeichnis ändern, einschließlich einer CMakeLists.txt-Datei, und make im Build-Verzeichnis erneut ausführen, werden make und cmake die notwendigen Änderungen neu kompilieren und neu aufbauen. Wenn Sie nur Änderungen in einem Unterverzeichnis vornehmen, können Sie einfach make in dem entsprechenden Unterverzeichnis im Build-Baum ausführen, um die Aktualisierungen zu verarbeiten.
Eine anfängliche Quelle der Verwirrung mit Out-of-Source-Builds ist, dass Sie im Grunde zwei Kopien Ihres Quellbaums haben, eine mit dem tatsächlichen Quellcode und eine mit Makefiles und binären ausführbaren Dateien (im Build-Tree). Es ist wahrscheinlich am besten, zwei Fenster offen zu halten, eines im Build-Tree für das Erstellen und Ausführen von Programmen und ein Fenster im Source-Tree für das Ändern von Quelldateien.
Eine nette Sache an Out-of-Source-Builds ist, dass man Objektdateien, Makedepend-Dateien, Binärdateien und anderen Build-Müll einfach löschen kann, da es keinen Source gibt. Sie können auch make clean verwenden, um die eigentlichen Objekt- und Binärdateien zu säubern, aber wenn Sie vorhaben, Ihre Quellen zu tarieren oder Ihren Code an die Massen zu verteilen, können Sie einfach
cumin$ cd cmakecumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ rm -rf build/cumin$ lsCMakeLists.txt w01-cpp/
ihren Code säubern und verpacken.
Dies ist nur ein kleiner Ausschnitt dessen, was CMake kann. Im CMake-Wiki finden Sie weitere Informationen. Ich hoffe, dass ich diese Seite aktualisieren kann, wenn wir auf komplexere Beispiele stoßen, und ich freue mich über Feedback und Tipps von anderen Kursen, die CMake verwenden. Für sehr fortgeschrittene Benutzer hat CMake ein Begleitprogramm CPack, mit dem man automatisch Binärdateien und Quellcode für Ubuntu/Debian (.deb), Red Hat (.rpm), OSXX11, tgz, CygWin und Nullsoft-Systeme verpacken kann.