====== CMake ======
===== Allgemein =====
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).
===== Anleitungen =====
* [[http://www.cmake.org/cmake/help/cmake_tutorial.html | CMake Tutorial]]
* [[http://www.youtube.com/watch?v=8Ut9o4OdSC0 | CMake Einführung (Video, englisch)]]
* [[http://www.cmake.org/cmake/help/syntax.html | Einführung zur Syntax]]
* [[http://www.vtk.org/Wiki/CMake/Examples | Beispiele]]
* [[http://www.cmake.org/Wiki/CMake_FAQ | FAQ]]
* [[http://www.cmake.org/cmake/help/documentation.html | Referenzdokumentation]]
* [[http://www.cmake.org/cmake/help/mailing.html | Mailing Liste]]
* [[http://rachid.koucha.free.fr/tech_corner/cmake_manual.html | Praktische Beispiele]]
* [[.:CMake & TFS | Notizen zu CMake und TFS]]
* [[.:CMakeQVTK | Notizen zu CMake VTK und QT]]
===== Best Practices & Tipps =====
* Es ist stets ein //Out-of-Source// Build anzustreben. Dies erleichtert die Verwendung verschiedener IDE's und Versionsverwaltungen.
* Der CMake Cache führt manchmal zu Problemen, da Variablen falsch initialisiert werden. D.h. bei Problemen Cache löschen.
* Die Einbindung von Bibliotheken hängt stark von der Qualität der ''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.
* TODO Ordnerstruktur (build, cmake, etc.)
===== Einführung =====
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.
==== Konfiguration ====
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.).
==== Sprachkonstrukte ====
=== Kommando ===
(Argumente)
Leerzeichengetrennte Argumente werden als Liste interpretiert. Ansonsten können Anführungszeichen verwendet werden.
=== Variablen ===
set( 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.
=== Bedingung ===
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 [[http://www.cmake.org/cmake/help|CMake Documentation Command if]]
=== Schleifen ===
foreach(Variable Liste)
endforeach()
while(Ausdruck)
endwhile()
=== Funktionen & Makros ===
function(Funktionsname Argumente)
endfunction()
macro(Funktionsname Argumente)
endmacro()
Funktionen haben einen eigenen Variablen-Scope, wohingegen Makros nur eine Textersetzung darstellen.
==== Policies ====
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 )
global gesetzt werden.
===== Spezielle Funktionen =====
==== Präprozessormakros ====
Für die plattformunabhängige Übergabe von Direktiven ist das Kommando add_definitions(-D)
vorgesehen.
==== Configure-Files ====
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
/* Insert the contents of a Variable */
String userFolder = ${USER_FOLDER}
==== Export von Projekten ====
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 )
Set variable containing all include directories, used in configure file
get_target_property(${PACKAGE_NAME}_INCLUDE_DIRS INCLUDE_DIRECTORIES)
export(TARGETS 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 )
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 "@_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()
Werden statische Bilbiotheken gelinkt, so enthält der Export zwar die Information der Abhängigkeit, jedoch nicht den Standort der Bibliotheken. Um dies zu beheben, wird im *-config File ein //find_package// für die statische Bibliothek eingefügt.
==== Install Scripts ====
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
RUNTIME DESTINATION bin COMPONENT Runtime
LIBRARY DESTINATION lib COMPONENT Runtime
ARCHIVE DESTINATION lib/ COMPONENT Development
)
==== Drittbibliotheken ====
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| 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}")
===== Literatur =====
Ken Martin, Bill Hoffman: //Mastering CMake.// ISBN 978-1930934221.