Quando si cerca di imparare CMake non ho potuto trovare una buona introduzione. La documentazione di CMake è abbastanza completa ma non adatta a un principiante. Ci sono alcuni tutorial utili collegati sul Wiki di CMake, ma la maggior parte di essi copre solo problemi molto specifici o sono troppo basilari. Così ho scritto questa breve introduzione di CMake come una versione distillata di ciò che ho scoperto dopo aver lavorato attraverso i documenti e seguendo le domande di stackoverflow.
È un work in progress e cercherò di migliorarlo continuamente.
CMake è uno strumento di meta build che consente di generare script di build nativi per una serie di piattaforme:
- Makefile Unix
- Xcode
- Visual Studio
- CodeBlocks
- Eclipse
- e altro ancora
Vedi l’elenco completo dei generatori CMake.
Supponiamo di avere una semplice app con un singolo .file C.
Creiamo un fileCMakeLists.txt
nella radice del nostro progetto.
cmake_minimum_required(VERSION 2.8)project(app_project)add_executable(myapp main.c)install(TARGETS myapp DESTINATION bin)
Questo è tutto ciò di cui abbiamo bisogno per essere in grado di costruire la nostra app con uno qualsiasi dei generatori disponibili.
add_executable
definisce il nostro binario con tutti i file sorgente collegati.
install
dice a cmake di installare il nostro binario nella directory bin
della directory di installazione.
Building
CMake supporta build out-of-source — quindi tutto il nostro codice compilato va in una directory separata dai sorgenti.
Per avviare una build creiamo una nuova cartella:
mkdir _build
cd _build
E chiamiamo cmake con il percorso alla radice del progetto (in questo caso la cartella principale):
cmake ..
Questo genererà script di build usando il generatore predefinito — su Linux/OSX questo dovrebbe essere Makefile.
Per impostazione predefinita cmake installerà la nostra build nelle directory di sistema.
Per definire una directory di installazione personalizzata la passiamo semplicemente a cmake:
cmake .. -DCMAKE_INSTALL_PREFIX=../_install
Per eseguire lo script di compilazione puoi semplicemente usare il Makefile:
make
make install
ora Possiamo eseguire il nostro binario dalla directory di installazione:
../_install/bin/myapp
Se volessimo utilizzare un altro generatore passiamo a cmake utilizzando il -G
parametro:
cmake .. -GXcode
in Questo modo, l’uscita di una facilmente configurato progetto Xcode per costruire la nostra app.
Usando CMake con le librerie
Per costruire una libreria usiamo uno script simile:
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 costruirà la libreria comelibtest.a
e la installerà nella cartella lib della directory di installazione.
Includiamo anche il nostro file di intestazione pubblica nella fase di installazione e diciamo a cmake di inserirlo ininclude
.
Invece di una libreria statica possiamo costruire anche una lib condivisa:
add_library(test SHARED test.c)
Collegando le librerie agli eseguibili con CMake
Possiamo estendere il nostro eseguibile dall’alto collegandolo al nostro libraylibtest.a
.
Iniziamo aggiungendo la directory della libreria come sottodirectory al nostro progetto myapp.
Ora, possiamo usare la libreria definita in CMakeLists.txt di libtest_project nelle CMakeLists di 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
rende disponibile per la build la libreria test
definita in libtestproject.
Intarget_link_libraries
diciamo a CMake di collegarlo al nostro eseguibile. CMake si assicurerà di eseguire il primo test di compilazione prima di collegarlo a myapp.
Incluse librerie esterne che utilizzano altri sistemi di compilazione
Mentre CMake gode di crescente interesse, ci sono ancora molte librerie che utilizzano sistemi di compilazione nativi come i Makefile Unix. Puoi usarli nel tuo progetto CMake senza dover riscrivere i loro script di compilazione.
Tutto ciò di cui abbiamo bisogno è il supporto di CMake per progetti esterni e librerie importate:
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
ci permette di aggiungere un progetto esterno come target al nostro progetto. Se non si specificano comandi come BUILD_COMMAND
o INSTALL_COMMAND
, CMake cercherà un CMakeLists.txt
nel progetto esterno ed eseguirlo.
Nel nostro caso vogliamo fare uso della libreria luajit che è costruita usando un Makefile.
add_library
supporta anche l’importazione di librerie già create – dobbiamo solo impostare la sua proprietà IMPORTED_LOCATION
.
Chiamando ExternalProject_Add
specifica solo il progetto esterno come destinazione ma non lo crea automaticamente. Sarà costruito solo se aggiungiamo una dipendenza ad esso. Chiamiamo quindiadd_dependencies
per rendere la nostra libreria importata dipendente dal progetto esterno.
Infine possiamo collegare la nostra libreria importata proprio come una libreria “normale” contarget_link_libraries
.