Cmake

Questo documento fornisce una rapida panoramica di CMake – un’alternativa multipiattaforma a Makefiles e make di Linux. Per aiuto sull’uso di make e Makefiles senza CMake, per favore vedi la documentazione del Prof. Newhall. Questo documento è stato scritto per cmake versione 2.6, che è installato sulle macchine del laboratorio tramite stow (da gennaio 2009).

Perché CMake

Personalmente mi piace CMake perché sembra più intuitivo che scrivere un Makefile standard. Le cose basilari e comuni sono abbastanza facili e le cose più difficili sono possibili, anche se la maggior parte delle cose che costruisco sono abbastanza basilari. Per dimostrare CMake, ho incluso del codice di esempio nel file cmake.tgz (4 KB). Salva il file e scompatta il contenuto in qualsiasi punto della tua directory. Per esempio:

$ tar xzvf cmake.tgz$ cd cmake$ lsCMakeLists.txt w01-cpp/
CMakeLists.txt

CMake è controllato scrivendo istruzioni nei file CMakeLists.txt. Ogni directory del tuo progetto dovrebbe avere un file CMakeLists.txt. Ciò che è bello di CMake è che i file CMakeLists.txt in una sotto-directory ereditano le proprietà impostate nella directory madre, riducendo la quantità di duplicazione del codice. Per il nostro progetto di esempio, abbiamo solo una sottodirectory: w01-cpp. Il file CMakeLists.txt per la directory principale di cmake è abbastanza semplice ma dimostra alcune caratteristiche chiave.

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)

Questo codice demo include codice che richiede librerie OpenGL esterne per la grafica. In una tipica configurazione Makefile avremmo probabilmente bisogno di specificare dove sono i file header OpenGL, ad esempio, -I/usr/local/include, quali librerie utilizzare, ad esempio, -lGL -lGLU -lglut, e la posizione delle librerie. La posizione dei file header e delle librerie probabilmente varia da installazione a installazione e da piattaforma a piattaforma. Ci sono comunque di solito alcuni posti standard dove guardare, e CMake automatizza questa ricerca usando le macro find_package. Così find_package(GLUT) e find_package(OpenGL) trova la posizione dei file header e delle librerie e imposta le librerie più comuni che sono collegate in un tipico progetto OpenGL. CMake ha il supporto per trovare molti pacchetti. Vedere /usr/local/share/cmake-2.6/Modules/Find*.cmake per altri esempi. Per usare uno di questi script, usa find_package(PKGname) se lo script CMake si chiama FindPKGname.cmake.

Per saperne di più su come trovare librerie esterne o creare le tue macro di find package, vedi il wiki KitWare sull’argomento.

Puoi impostare flag comuni che imposteresti in un tipico Makefile usandoingset(VARNAME VALUE). In questo esempio ho abilitato i simboli di debug (-g) e tutti gli avvertimenti (-Wall). Ho anche dato un nome a questo progetto CMake usando project(CMAKEDEMO). Puoi dare al tuo progetto il nome che vuoi. Useremo queste informazioni nel file CMakeLists.txt nella directory w01-cpp. Infine indichiamo che la maggior parte del codice è davvero nella w01-cpp dicendo al nostro file CMakeLists.txt di primo livello di add_subdirectory(w01-cpp)

Diamo un’occhiata al file CMakeLists.txt nella sottodirectory 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)

La macro include_directories dice a CMake dove cercare i file sorgente. Dichiarando il nome del progetto CMAKEDEMO nel file CMakeLists.txt di primo livello, le variabili CMAKEDEMO_SOURCE_DIR e CMAKEDEMO_BINARY_DIR sono impostate a seconda della posizione corrente del tuo codice e della posizione corrente della tua directory di build (più avanti su quest’ultima posizione). Aggiungere un obiettivo per un nuovo eseguibile binario è facile. Basta aggiungere una linea add_executable(cdemo cdemo.c). CMake capirà automaticamente il compilatore basandosi sull’estensione del tipo di file. Se sono necessarie librerie aggiuntive, puoi dire a CMake di linkarle usando target_link_libraries(cdemo m). Questo dice a CMake che il programma cdemo ha bisogno di collegarsi con la libreria matematica. Puoi fare il collegamento con più di una libreria specificando le librerie in una lista. Vedi per esempio set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m). Le variabili GLUT_LIBRARY e OPENGL_LIBRARY sono impostate da CMake quando abbiamo usato find_package(GLUT) e find_package(OpenGL). Per capire quali variabili sono impostate quando si usa find_package, probabilmente dovrete aprire il file Find*.cmake appropriato e leggere la documentazione, solitamente utile ma tersa.

Siccome diversi programmi in questa cartella w01-cpp sono compilati allo stesso modo e collegati alle stesse librerie, possiamo processarli tutti con un semplice ciclo mostrato sopra usando la macro foreach in CMake. Infine mostriamo come creare la nostra libreria usando add_library(geometry geometry.cpp) e linkando contro questa libreria in target_link_libraries(test_geometry ${CORELIBS} geometry).

Costruire con CMake

Impostare un mucchio di file CMakeLists.txt non ti permetterà immediatamente di costruire il tuo progetto. CMake è solo un wrapper per piattaforme incrociate intorno a sistemi di compilazione più tradizionali. Nel caso di Linux, questo significa make. Un rapido passo di pre-elaborazione convertirà automaticamente la tua descrizione CMakeLists.txt in un sistema di compilazione tradizionale make. Una caratteristica carina e altamente raccomandata di CMake è la capacità di fare build out of source. In questo modo puoi fare tutti i tuoi file .o, vari file temporanei dipendenti, e anche gli eseguibili binari senza ingombrare il tuo albero dei sorgenti. Per usare le compilazioni out of source, crea una directory di compilazione nella tua cartella di primo livello (tecnicamente, questa può essere ovunque, ma la cartella di primo livello del progetto sembra essere una scelta logica). Poi, vai nella tua directory di compilazione ed esegui cmake puntando alla directory del CMakeLists.txt di primo livello. Per esempio:

cumin$ cd cmake/cumin$ lsCMakeLists.txt w01-cpp/cumin$ mkdir buildcumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ cd build/cumin$ cmake ..

Ricorda di essere nella tua directory di compilazione e punta cmake solo alla directory che contiene il file CMakeLists.txt di primo livello, non il file stesso. Se tutto va bene, cmake elaborerà i vostri file CMakeLists.txt, troverà la posizione di tutte le librerie e i percorsi di inclusione e sputerà un mucchio di informazioni di configurazione incluso un Makefile tradizionale nella vostra directory di compilazione. (Se hai familiarità con autotools/autohell, questo processo di cmake è simile a ./configure). Ora sei pronto a costruire usando il sistema tradizionale di make. Esegui make nella tua directory di compilazione per compilare e collegare tutto. CMake mette anche dei bei colori, barre di progresso, e sopprime un sacco di output di gcc. Se volete un output verboso, potete digitare VERBOSE=1 make (utile se qualcosa va storto).

A causa del modo in cui abbiamo impostato la build out of source e il link_directories (${CMAKEDEMO_BINARY_DIR}/w01-cpp), i nostri binari appena compilati sono nella cartella w01-cpp nella directory di build dove abbiamo appena eseguito make.

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 

Premete ESC per uscire dalla demo OpenGL.

Concludendo

Se modificate il codice nella vostra directory dei sorgenti, incluso anche un file CMakeLists.txt e lanciate nuovamente make nella directory di compilazione, make e cmake ricompileranno e ricostruiranno le modifiche necessarie. Se stai solo apportando modifiche in una sottodirectory, puoi semplicemente eseguire make nella sottodirectory corrispondente nell’albero di compilazione per elaborare gli aggiornamenti.

Una fonte iniziale di confusione con le build out of source è che fondamentalmente hai due copie del tuo albero dei sorgenti, una con il codice sorgente effettivo, e una con i Makefiles e gli eseguibili binari (nell’albero di build). Probabilmente è meglio tenere due finestre aperte, una nell’albero di compilazione per creare ed eseguire i tuoi programmi, e una finestra nell’albero dei sorgenti per modificare i file sorgente.

Una cosa bella delle compilazioni out of source è che la pulizia dei file oggetto, dei file makedepend, dei binari e di altri vari cruft di compilazione può essere fatta semplicemente cancellando l’intera directory di compilazione perché non ci sono sorgenti. Si può anche usare make clean per pulire i file oggetto e binari veri e propri, ma quando si ha intenzione di fare il tar up del sorgente o distribuire il codice alle masse, si può semplicemente fare

cumin$ cd cmakecumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ rm -rf build/cumin$ lsCMakeLists.txt w01-cpp/

per pulire e impacchettare il codice.

Altro da esplorare

Questo tocca solo la superficie di ciò che CMake può fare. Controlla la Wiki di CMake per maggiori informazioni. Spero di aggiornare questa pagina se ci imbattiamo in esempi più complessi, e sono felice di accettare feedback o suggerimenti da altri corsi che potrebbero usare CMake. Per utenti molto avanzati, CMake ha un programma compagno CPack per impacchettare automaticamente binari e sorgenti per Ubuntu/Debian (.deb), Red Hat (.rpm), OSXX11, tgz, CygWin, e sistemi Nullsoft.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.