CMake ist ein plattformunabhängiges Tool zur Erstellung von Builddateien für unterschiedliche Systeme (Visual Studio, Eclipse, Make und andere). Des Weiteren bietet CMake diverse plattformunabhängige Dateioperationen (Kopieren, Entfernen, Verzeichnisse durchsuchen etc).
Find*.cmake
Dateien ab. Diese liegen im CMakeFiles Ordner der Bibliothek oder im Installationspfad von CMake z.B. FindVTK.cmake oder FindQt.cmake). Für Multi-Konfiguration Builds (z.B. Visual Studio) sind oft Anpassungen in diesen Dateien nötig.
Der Build-Prozess wird mittels Dateien mit dem Namen CMakeLists.txt
beschrieben. Diese werden üblicherweise im Hauptordner und den verschiedenen Unterodner des Projektes abgelegt.
Die nachfolgende Grafik zeigt grob die Verzeichnisse, welche in einer CMake-Umgebung vorhanden sind und deren wichtigste Inhalte. Aus dem Quellverzeichnis wird mittels CMake das Ausgabeverzeichnis (Binary dir) erzeugt. Es enthält die Werte der Konfiguration, sowie die Ergebnisse von Tests (z.B. Endianess) und Dateien für die Einbindung in andere CMake-Projekte. Letztere müssen jedoch durch den Benutzer erzeugt werden (siehe Export von Projekten). Durch die Installation wird die Software üblicherweise ins Zielsystem installiert (z.B. Ablage nach C:/Program Files/xyz unter Windows). Dieser Schritt kann jedoch auch dazu verwendet werden, um alle benötigten Zusatzbilbiotheken ins Zielverzeichnis zu kopieren. Die Installation enthält relative Pfade und ist somit unabhängig vom Zielsystem.
Für die Konfiguration eines CMake-Projektes wird oft das CMake-GUI verwendet. Es wird der Pfad zur Haupt-CMakeLists.txt angegeben und ein Ordner, welcher die Dateien für den Build enthält. Im Configure Schritt wird der Compiler festgelegt und die Umgebung analysiert. Neue Variablen werden rot eingefärbt und sollten überprüft werden. Configure wird solange ausgeführt, bis keine Variablen mehr rot sind. Der Aufruf von Generate erzeugt die entsprechenden Build-Dateien (Solutions etc.).
<Kommando-Name>(Argumente)
Leerzeichengetrennte Argumente werden als Liste interpretiert. Ansonsten können Anführungszeichen verwendet werden.
set(<Variable> Argumente)
Variablen können über ${Variablenname} abgerufen werden. Umgebungsvariablen können via $ENV{Variablenname} und die Windows-Registry über deren Keys HKEY_... angesprochen werden. Eine Variable ist im aktuellen Ordner sowie allen Unterordnern sichtbar. In Unterordner kann eine Variable jedoch nur durch Angabe von PARENT_SCOPE geändert werden. Variablen können auch mit Variablen definiert werden z.B. ${${Name}_DIR}_FLAG.
if(Ausdruck) elseif() else() endif()
Als Ausdruck können logische Verknüpfungen von Variablen, aber auch String und Integervergleiche und Verzeichnisabfragen eingesetzt werden. Detaillierte Informationen siehe CMake Documentation Command if
foreach(Variable Liste) endforeach()
while(Ausdruck) endwhile()
function(Funktionsname Argumente) endfunction()
macro(Funktionsname Argumente) endmacro()
Funktionen haben einen eigenen Variablen-Scope, wohingegen Makros nur eine Textersetzung darstellen.
Um die Kompatibilität mit älteren CMake-Versionen sicherzustellen sind verschiedene Policies vorhanden. Wird das Verhalten einer Funktion geändert, so wird dazu in neueren Versionen eine Policy eingeführt, welche standardmässig das alte Verhalten anwendet und eine Warnung ausgibt. Policies können einzeln angepasst oder durch Definition der Minimal-Version
cmake_minimum_required(VERSION <Versionsnummer>)
global gesetzt werden.
Für die plattformunabhängige Übergabe von Direktiven ist das Kommando
add_definitions(-D<Direktive>)
vorgesehen.
Mit Hilfe von CMake können Dateien aus Vorlagen und aktuellen Variablendefinitionen erzeugt werden. Der Inhalt der Vorlagedatei wird dabei kopiert und die Platzhalter mit Variableninhalt gefüllt.
configure_file( ${PROJECT_SOURCE_DIR}/template.in ${PROJECT_BINARY_DIR}/template.out )
/* Insert a #define if the Variable is set */ cmakedefine <Variablename> /* Insert the contents of a Variable */ String userFolder = ${USER_FOLDER}
Um CMake-Projekte in anderen zu referenzieren können die Buildinformationen exportiert werden. Weitere Informationen siehe Mastering CMake Kapitel 5.7 Creating CMake Package Configuration Files.
set(PACKAGE_NAME <Paketname>) Set variable containing all include directories, used in configure file get_target_property(${PACKAGE_NAME}_INCLUDE_DIRS <Target> INCLUDE_DIRECTORIES) export(TARGETS <Targetliste> FILE ${PACKAGE_NAME}-targets.cmake) configure_file( ${${PROJECT_NAME}_SOURCE_DIR}/${PACKAGE_NAME}-config.cmake.in ${${PROJECT_NAME}_BINARY_DIR}/${PACKAGE_NAME}-config.cmake ) set(VERSION <Versionsnummer>) configure_file( ${${PROJECT_NAME}_SOURCE_DIR}/${PACKAGE_NAME}-config-version.cmake.in ${${PROJECT_NAME}_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake )
# Import the targets include("@@PROJECT_NAME@_BINARY_DIR@/@PACKAGE_NAME@-targets.cmake") # Report other information i.e include directories used # Nested @ are not supported set(@PROJECT_NAME@_INCLUDE_DIRS "@<Projektname>_INCLUDE_DIRS@")
set(PACKAGE_VERSION "@version@") if(NOT "${PACKAGE_FIND_VERSION}" VERSION_GREATER "@version@") set (PACKAGE_VERSION_COMPATIBLE 1) if("${PACKAGE_FIND_VERSION}" VERSION_EQUAL "@version@") set(PACKAGE_VERSION_EXACT 1) endif() endif()
Achtung statische Bibliotheken
Um ein Projekt plattformunabhängig zu installieren (z.B. nach C:/Program Files/…) bietet CMake das install Kommando. Die Details zur nachstehenden Syntax sind Mastering CMake zu entnehmen.
install( TARGETS <Targetlist> RUNTIME DESTINATION bin COMPONENT Runtime LIBRARY DESTINATION lib COMPONENT Runtime ARCHIVE DESTINATION lib/<projectname> COMPONENT Development )
Damit Drittbibliotheken nicht von Hand in den Output-Ordner kopiert werden müssen (z.B. für Visual Studio) sind die BundleUtilities vorhanden. Dazu wird das Target zuerst installiert siehe Install Scripts. Über die Anwendung (oder Bibliothek) wird nach abhängigen Bibliotheken gesucht.
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/FixBundle.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake @ONLY ) install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake)
include(BundleUtilities) # Set bundle to the full path name of the executables already existing set(bundle "${CMAKE_INSTALL_PREFIX}/@PROJECT_NAME@@CMAKE_EXECUTABLE_SUFFIX@") # Set other_libs to a list of full path names to additionale libraries that cannot be reached by dependency analysis (i.e dynamically loaded plugins) set(other_libs "") # Set dirs to a list of directories where prerequisite libraries may be found set(dirs "@LIBRARY_OUTPUT_PATH@") fixup_bundle("${bundle}" "${other_libs}" "${dirs}")
Ken Martin, Bill Hoffman: Mastering CMake. ISBN 978-1930934221.