Beim Versuch, CMake zu lernen, konnte ich keine gute Einführung finden. Die CMake-Dokumentation ist recht umfangreich, aber nicht für Anfänger geeignet. Es gibt einige nützliche Tutorials, die im CMake-Wiki verlinkt sind, aber die meisten decken nur sehr spezifische Probleme ab oder sind zu einfach. Also habe ich diese kurze CMake-Einführung als destillierte Version dessen geschrieben, was ich nach dem Durcharbeiten der Dokumente und dem Befolgen von Stackoverflow-Fragen herausgefunden habe.
Es ist ein Work in progress und ich werde versuchen, es kontinuierlich zu verbessern.
CMake ist ein Meta-Build-Tool, mit dem Sie native Build-Skripte für eine Reihe von Plattformen generieren können:
- Unix Makefiles
- Xcode
- Visual Studio
- CodeBlocks
- Eclipse
- und mehr …
Siehe die vollständige Liste der CMake-Generatoren.
Nehmen wir an, wir haben eine einfache App mit einem einzigen .c-Datei.
Wir erstellen eine CMakeLists.txt
Datei im Stammverzeichnis unseres Projekts.
cmake_minimum_required(VERSION 2.8)project(app_project)add_executable(myapp main.c)install(TARGETS myapp DESTINATION bin)
Das ist alles, was wir brauchen, um unsere App mit einem der verfügbaren Generatoren erstellen zu können.
add_executable
definiert unsere Binärdatei mit allen verknüpften Quelldateien.
install
weist cmake an, unsere Binärdatei im bin
Verzeichnis des Installationsverzeichnisses zu installieren.
Bauen
CMake unterstützt Out-of-Source—Builds – also geht unser gesamter kompilierter Code in ein Verzeichnis, das von den Quellen getrennt ist.
Um einen Build zu starten, erstellen wir einen neuen Ordner:
mkdir _build
cd _build
Und rufen cmake mit dem Pfad zum Stammverzeichnis des Projekts (in diesem Fall dem übergeordneten Ordner) auf:
cmake ..
Dadurch werden Build—Skripte mit dem Standardgenerator generiert – unter Linux / OSX sollten dies Makefiles sein.
Standardmäßig installiert cmake unseren Build in den Systemverzeichnissen.
Um ein benutzerdefiniertes Installationsverzeichnis zu definieren, übergeben wir es einfach an cmake:
cmake .. -DCMAKE_INSTALL_PREFIX=../_install
Um das Build-Skript auszuführen, können Sie einfach das Makefile verwenden:
make
make install
Wir können jetzt unsere Binärdatei aus dem Installationsverzeichnis ausführen:
../_install/bin/myapp
Wenn wir einen anderen Generator verwenden wollten, übergeben wir ihn mit dem -G
Parameter an cmake:
cmake .. -GXcode
Dies gibt ein leicht konfiguriertes Xcode-Projekt zum Erstellen unserer App aus.
CMake mit Bibliotheken verwenden
Um eine Bibliothek zu erstellen, verwenden wir ein ähnliches Skript:
cmake_minimum_required(VERSION 2.8)project(libtest_project)add_library(test STATIC test.c)install(TARGETS test DESTINATION lib)
install(FILES test.h DESTINATION include)
CMake erstellt die Bibliothek als libtest.a
und installiert sie im Ordner lib des Installationsverzeichnisses.
Wir fügen auch unsere öffentliche Header-Datei in den Installationsschritt ein und weisen cmake an, sie in include
.
Anstelle einer statischen Bibliothek können wir auch eine gemeinsame Bibliothek erstellen:
add_library(test SHARED test.c)
Verknüpfen von Bibliotheken mit ausführbaren Dateien mit CMake
Wir können unsere ausführbare Datei von oben erweitern, indem wir sie mit unserer Bibliothek verknüpfen libtest.a
.
Beginnen wir mit dem Hinzufügen des Bibliotheksverzeichnisses als Unterverzeichnis zu unserem myapp-Projekt.
Jetzt können wir die in CMakeLists definierte Bibliothek verwenden.txt von libtest_project in den CMakeLists von myapp.txt:
cmake_minimum_required(VERSION 2.8)project(myapp)add_subdirectory(libtest_project)add_executable(myapp main.c)target_link_libraries(myapp test)install(TARGETS myapp DESTINATION bin)
add_subdirectory
stellt die in libtestproject definierte Bibliothek test
dem Build zur Verfügung.
In target_link_libraries
weisen wir CMake an, es mit unserer ausführbaren Datei zu verknüpfen. CMake stellt sicher, dass zuerst ein Test erstellt wird, bevor er mit myapp verknüpft wird.
Externe Bibliotheken mit anderen Build-Systemen einbinden
Während CMake zunehmendes Interesse genießt, gibt es immer noch viele Bibliotheken, die native Build-Systeme wie Unix-Makefiles verwenden. Sie können sie in Ihrem CMake-Projekt verwenden, ohne ihre Build-Skripte neu schreiben zu müssen.
Alles, was wir brauchen, ist Cmakes Unterstützung für externe Projekte und importierte Bibliotheken:
ExternalProject_Add(project_luajit
URL http://luajit.org/download/LuaJIT-2.0.1.tar.gz
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/luajit-2.0.1
CONFIGURE_COMMAND ""
BUILD_COMMAND make
INSTALL_COMMAND make install
PREFIX=${CMAKE_CURRENT_BINARY_DIR}/luajit-2.0.1
)ExternalProject_Get_Property(project_luajit install_dir)add_library(luajit STATIC IMPORTED)set_property(TARGET luajit PROPERTY IMPORTED_LOCATION ${install_dir}/lib/libluajit-5.1.a)add_dependencies(luajit project_luajit)add_executable(myapp main.c)include_directories(${install_dir}/include/luajit-2.0)target_link_libraries(myapp luajit)
ExternalProject_Add
ermöglicht es uns, unserem Projekt ein externes Projekt als Ziel hinzuzufügen. Wenn Sie keine Befehle wie BUILD_COMMAND
oder INSTALL_COMMAND
angeben, sucht CMake im externen Projekt nach einer CMakeLists.txt
und führe es aus.
In unserem Fall möchten wir die Luajit-Bibliothek verwenden, die mit einem Makefile erstellt wird.
add_library
unterstützt auch den Import von bereits erstellten Bibliotheken – wir müssen nur die IMPORTED_LOCATION
Eigenschaft festlegen.
Aufruf von ExternalProject_Add
gibt nur das externe Projekt als Ziel an, erstellt es jedoch nicht automatisch. Es wird nur erstellt, wenn wir eine Abhängigkeit hinzufügen. Wir rufen daher add_dependencies
auf, um unsere importierte Bibliothek vom externen Projekt abhängig zu machen.
Endlich können wir unsere importierte Bibliothek wie eine „normale“ Bibliothek mit target_link_libraries
verknüpfen.