Acest document oferă o scurtă prezentare generală a CMake – o alternativă multi-platformă la linux Makefiles și make. Pentru ajutor privind utilizarea make și Makefiles fără CMake, vă rugăm să consultați documentația profesorului Newhall. Acest document a fost scris pentru versiunea cmake 2.6, care este instalată pe mașinile de laborator prin stow (începând cu ianuarie 2009).
Personal îmi place CMake pentru că este pare mai intuitiv decât scrierea unui Makefile standard. Lucrurile de bază și comune sunt destul de ușoare, iar lucrurile mai dificile sunt posibile, deși majoritatea lucrurilor pe care le construiesc sunt destul de simple. Pentru a demonstra CMake, am inclus câteva exemple de cod în fișierul cmake.tgz (4 KB). Salvați fișierul și despachetați conținutul oriunde în directorul dumneavoastră. De exemplu:
$ tar xzvf cmake.tgz$ cd cmake$ lsCMakeLists.txt w01-cpp/
CMake este controlat prin scrierea de instrucțiuni în fișierele CMakeLists.txt. Fiecare director din proiectul dumneavoastră ar trebui să aibă un fișier CMakeLists.txt. Ceea ce este frumos la CMake este că fișierele CMakeLists.txt dintr-un subdirectorat moștenesc proprietățile setate în directorul părinte, reducând cantitatea de duplicare a codului. Pentru exemplul nostru de proiect, avem doar un singur subdirectoriu: w01-cpp. Fișierul CMakeLists.txt pentru directorul cmake de nivel superior este destul de simplu, dar demonstrează câteva caracteristici cheie.
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)
Acest cod demonstrativ include cod care necesită biblioteci OpenGL externe pentru grafică. Într-o configurație tipică a fișierului Makefile ar trebui probabil să specificăm unde se află fișierele de antet OpenGL, de exemplu, -I/usr/local/include, ce biblioteci să folosim, de exemplu, -lGL -lGLU -lglut, și locația bibliotecilor. Locația fișierelor de antet și a bibliotecilor variază probabil de la o instalare la alta și de la o platformă la alta. Cu toate acestea, există, de obicei, câteva locuri standard în care trebuie să căutați, iar CMake automatizează această căutare cu ajutorul macrourilor find_package. Astfel, find_package(GLUT) și find_package(OpenGL) găsește locația fișierelor de antet și a bibliotecilor și stabilește cele mai comune biblioteci care sunt legate într-un proiect OpenGL tipic. CMake are suport pentru a găsi o mulțime de pachete. Consultați /usr/local/share/cmake-2.6/Modules/Find*.cmake pentru mai multe exemple. Pentru a utiliza unul dintre aceste scripturi, utilizați find_package(PKGname) dacă scriptul CMake se numește FindPKGname.cmake.
Pentru mai multe informații despre găsirea bibliotecilor externe sau despre crearea propriilor macros de găsire a pachetelor, consultați KitWare wiki pe această temă.
Puteți seta indicatori comuni pe care i-ați seta într-un fișier Makefile tipic utilizândingset(VARNAME VALUE). În acest exemplu am activat simbolurile de depanare (-g) și toate avertismentele (-Wall). De asemenea, am dat un nume acestui proiect CMake folosind project(CMAKEDEMO). Puteți numi proiectul dvs. cum doriți. Vom folosi aceste informații în fișierul CMakeLists.txt din directorul w01-cpp. În cele din urmă, indicăm că cea mai mare parte a codului se află de fapt în w01-cpp, spunându-i fișierului nostru CMakeLists.txt de nivel superior să add_subdirectory(w01-cpp)
Să aruncăm o privire la fișierul CMakeLists.txt din subdirectorul 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)
Macro include_directories îi spune lui CMake unde să caute fișierele sursă. Prin declararea numelui proiectului CMAKEDEMO în fișierul de nivel superior CMakeLists.txt, variabilele CMAKEDEMO_SOURCE_DIR și CMAKEDEMO_BINARY_DIR sunt setate în funcție de locația curentă a codului dvs. și de locația curentă a directorului dvs. de construcție (mai multe despre această din urmă locație mai târziu). Adăugarea unei ținte pentru un nou executabil binar este ușoară. Trebuie doar să adăugați o linie add_executable(cdemo cdemo.c). CMake își va da seama automat de compilator pe baza extensiei tipului de fișier. Dacă sunt necesare biblioteci suplimentare, îi puteți spune lui CMake să se lege cu acestea folosind target_link_libraries(cdemo m). Acest lucru îi spune lui CMake că programul cdemo trebuie să se lege de biblioteca matematică. Puteți face legătura cu mai mult de o bibliotecă specificând bibliotecile într-o listă. A se vedea, de exemplu, set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m). Variabilele GLUT_LIBRARY și OPENGL_LIBRARY sunt setate de CMake atunci când am folosit find_package(GLUT) și find_package(OpenGL). Pentru a afla ce variabile sunt setate atunci când se utilizează find_package, va trebui probabil să deschideți fișierul Find*.cmake corespunzător și să citiți documentația, de obicei utilă, dar laconică.
Din moment ce mai multe programe din acest dosar w01-cpp sunt compilate în același mod și legate cu aceleași biblioteci, le putem procesa pe toate cu o buclă simplă prezentată mai sus, folosind macroul foreach din CMake. În cele din urmă, arătăm cum să ne creăm propria bibliotecă folosind add_library(geometry geometry.cpp) și legarea la această bibliotecă în target_link_libraries(test_geometry ${CORELIBS} geometry).
Configurarea unei grămezi de fișiere CMakeLists.txt nu vă va permite imediat să vă construiți proiectul. CMake este doar un înveliș pentru platforme încrucișate în jurul unor sisteme de construire mai tradiționale. În cazul linuxului, acest lucru înseamnă make. Un pas rapid de preprocesare va converti automat descrierea CMakeLists.txt în sistemul tradițional de construire make. O caracteristică plăcută și foarte recomandată a CMake este capacitatea de a face compilări din sursă. În acest fel, puteți crea toate fișierele .o, diversele fișiere de dependență temporare și chiar și executabilele binare fără a vă aglomera arborele de surse. Pentru a utiliza construcțiile out of source, creați un director de construcție în dosarul de nivel superior (tehnic, acesta poate fi oriunde, dar dosarul de proiect de nivel superior pare a fi o alegere logică). Apoi, schimbați-vă în directorul de construcție și rulați cmake indicându-i directorul din CMakeLists.txt de nivel superior. De exemplu:
cumin$ cd cmake/cumin$ lsCMakeLists.txt w01-cpp/cumin$ mkdir buildcumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ cd build/cumin$ cmake ..
Amintește-ți că trebuie să fii în directorul tău de construcție și să direcționezi cmake doar către directorul care conține fișierul CMakeLists.txt de nivel superior, nu către fișierul în sine. Dacă totul merge bine, cmake va procesa fișierele CMakeLists.txt, va găsi locația tuturor bibliotecilor și a căilor de includere și va scuipa o mulțime de informații de configurare, inclusiv un Makefile tradițional în directorul dvs. de construcție. (Dacă sunteți familiarizat cu autotools/autohell, acest proces cmake este similar cu ./configure). Sunteți acum gata să construiți folosind sistemul make tradițional. Rulați make în directorul dvs. de construcție pentru a compila și lega totul. CMake aruncă chiar și niște culori frumoase, bare de progres și suprimă o grămadă de ieșire gcc. Dacă doriți o ieșire verbose, puteți tasta VERBOSE=1 make (util dacă ceva nu merge bine).
Din cauza modului în care am configurat compilarea din sursă și link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp), binarele noastre proaspăt compilate se află în folderul w01-cpp din directorul de compilare în care tocmai am rulat 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
Presați ESC pentru a ieși din demonstrațiile OpenGL.
Dacă modificați codul din directorul sursă, inclusiv chiar și un fișier CMakeLists.txt și rulați din nou make în directorul de construcție, make și cmake vor recompila și reconstrui modificările necesare. Dacă faceți modificări doar într-un subdirector, puteți rula pur și simplu make în subdirectorul corespunzător din arborele de construcție pentru a procesa actualizările.
O sursă inițială de confuzie cu compilările din sursă este că, practic, aveți două copii ale arborelui de surse, una cu codul sursă real și una cu Makefile-uri și executabile binare (în arborele de compilare). Este probabil cel mai bine să păstrați două ferestre deschise, cu una în arborele de construcție pentru crearea și rularea programelor dvs. și o fereastră în arborele de surse pentru modificarea fișierelor sursă.
Un lucru bun în legătură cu construcțiile „out of source” este că curățarea fișierelor obiect, a fișierelor makedepend, a fișierelor binare și a altor diverse chestii de construcție se poate face prin simpla ștergere a întregului director de construcție, deoarece nu există sursă. De asemenea, puteți utiliza make clean pentru a curăța fișierele obiect și fișierele binare propriu-zise, dar atunci când intenționați să vă targhetați sursa sau să distribuiți codul în masă, puteți face pur și simplu
cumin$ cd cmakecumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ rm -rf build/cumin$ lsCMakeLists.txt w01-cpp/
pentru a vă curăța și împacheta codul.
Acest lucru atinge doar suprafața a ceea ce poate face CMake. Consultați CMake Wiki pentru mai multe informații. Sper să actualizez această pagină dacă vom da peste exemple mai complexe și sunt bucuros să primesc feedback sau sfaturi de la alte cursuri care ar putea folosi CMake. Pentru utilizatorii foarte avansați, CMake are un program însoțitor CPack pentru împachetarea automată a binarelor și a sursei pentru sistemele Ubuntu/Debian (.deb), Red Hat (.rpm), OSXX11, tgz, CygWin și Nullsoft.