Cmake

Ez a dokumentum gyors áttekintést nyújt a CMake-ről – a linuxos Makefiles és a make platformok közötti alternatívájáról. A make és a Makefiles CMake nélküli használatához segítséget nyújt Prof. Newhall dokumentációja. Ez a dokumentum a cmake 2.6-os verziójához készült, amely a stow segítségével van telepítve a laboratóriumi gépekre (2009 januárjától).

Miért a CMake

Én személy szerint azért szeretem a CMake-et, mert intuitívabbnak tűnik, mint egy szabványos Makefile írása. Az alapvető és gyakori dolgok elég egyszerűek, és a nehezebb dolgok is lehetségesek, bár a legtöbb dolog, amit építek, elég egyszerű. A CMake bemutatásához mellékeltem néhány mintakódot a cmake.tgz fájlban (4 KB). Mentsd el a fájlt, és csomagold ki a tartalmát bárhová a könyvtáradban. Például:

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

A CMake-et a CMakeLists.txt fájlba írt utasítások vezérlik. A projekted minden könyvtárában kell lennie egy CMakeLists.txt fájlnak. A CMake-ben az a szép, hogy az alkönyvtárban lévő CMakeLists.txt fájlok öröklik a szülő könyvtárban beállított tulajdonságokat, így csökkentve a kódduplikáció mennyiségét. A mi mintaprojektünkben csak egy alkönyvtár van: w01-cpp. A legfelső szintű cmake könyvtár CMakeLists.txt fájlja meglehetősen egyszerű, de néhány kulcsfontosságú tulajdonságot mutat be.

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)

Ez a demo kód olyan kódot tartalmaz, amely külső OpenGL könyvtárakat igényel a grafikához. Egy tipikus Makefile konfigurációban valószínűleg meg kell adnunk, hogy hol vannak az OpenGL fejlécfájlok, pl. -I/usr/local/include, milyen könyvtárakat használjunk, pl. -lGL -lGLU -lglut, és a könyvtárak helyét. A fejlécfájlok és a könyvtárak helye valószínűleg telepítésről telepítésre és platformról platformra változik. Általában azonban van néhány szabványos hely, ahol keresni kell, és a CMake a find_package makrók segítségével automatizálja ezt a keresést. Így a find_package(GLUT) és find_package(OpenGL) megtalálja a fejlécfájlok és könyvtárak helyét, és beállítja a leggyakoribb könyvtárakat, amelyekhez egy tipikus OpenGL projektben kapcsolódnak. A CMake támogatja a sok csomag megtalálását. További példákért lásd a /usr/local/share/cmake-2.6/Modules/Find*.cmake fájlt. Ezen szkriptek egyikének használatához használja a find_package(PKGnév) parancsot, ha a CMake szkript neve FindPKGnév.cmake.

A külső könyvtárak kereséséről vagy saját find package makrók készítéséről bővebben a KitWare wikiben olvashat a témában.

A tipikus Makefile-ban szokásos zászlók beállítására a usingset(VARNAME VALUE) használatával van lehetőség. Ebben a példában engedélyeztem a hibakereső szimbólumokat (-g) és az összes figyelmeztetést (-Wall). A project(CMAKEDEMO) használatával nevet is adtam ennek a CMake projektnek. Bármilyen nevet adhatsz a projektednek, amit csak akarsz. Ezt az információt a w01-cpp könyvtárban lévő CMakeLists.txt fájlban fogjuk használni. Végül jelezzük, hogy a kód nagy része valóban a w01-cpp könyvtárban van, azzal, hogy a legfelső szintű CMakeLists.txt fájlunknak azt mondjuk, hogy add_subdirectory(w01-cpp)

Nézzük meg a CMakeLists.txt fájlt a w01-cpp alkönyvtárban:

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)

Az include_directories makró megmondja a CMake-nek, hogy hol keresse a forrásfájlokat. A CMAKEDEMO projektnév deklarálásával a legfelső szintű CMakeLists.txt fájlban a CMAKEDEMO_SOURCE_DIR és CMAKEDEMO_BINARY_DIR változók a kódunk aktuális helyétől és a build könyvtárunk aktuális helyétől függően kerülnek beállításra (ez utóbbi helyről később lesz szó). Egy új bináris futtatható fájl célpontjának hozzáadása egyszerű. Csak hozzáadunk egy sort add_executable(cdemo cdemo.c). A CMake automatikusan kitalálja a fordítót a fájltípus kiterjesztés alapján. Ha további könyvtárakra van szükség, akkor a target_link_libraries(cdemo m) paranccsal megmondhatjuk a CMake-nek, hogy linkelje őket. Ez azt mondja a CMake-nek, hogy a cdemo programnak a matematikai könyvtár ellen kell linkelnie. Egynél több könyvtárral szemben is linkelhetünk, ha a könyvtárakat egy listában adjuk meg. Lásd például set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m). A GLUT_LIBRARY és OPENGL_LIBRARY változókat a CMake akkor állította be, amikor a find_package(GLUT) és find_package(OpenGL) parancsokat használtuk. Ahhoz, hogy kiderítsük, mely változókat állítjuk be a find_package használatakor, valószínűleg meg kell nyitnunk a megfelelő Find*.cmake fájlt, és el kell olvasnunk az általában hasznos, de szűkszavú dokumentációt.

Mivel ebben a w01-cpp mappában több program is ugyanúgy van lefordítva és ugyanolyan könyvtárakkal szemben linkelve, a CMake foreach makrójának segítségével mindegyiket feldolgozhatjuk a fent látható egyszerű ciklus segítségével. Végül megmutatjuk, hogyan hozzuk létre a saját könyvtárunkat az add_library(geometry geometry.cpp) segítségével, és hogyan linkeljük ez ellen a könyvtár ellen a target_link_libraries(test_geometry ${CORELIBS} geometry) segítségével.

Építés a CMake-kel

Egy csomó CMakeLists.txt fájl beállítása nem teszi azonnal lehetővé a projekt építését. A CMake csak egy platformokon átívelő burkolat a hagyományosabb build rendszerek körül. A linux esetében ez a make-t jelenti. Egy gyors előfeldolgozási lépés automatikusan átalakítja a CMakeLists.txt leírást egy hagyományos make build rendszerré. A CMake egyik szép és erősen ajánlott funkciója a forrásból történő építés lehetősége. Így elkészítheted az összes .o fájlodat, a különböző ideiglenes függő fájlokat, sőt a bináris futtatható állományokat is anélkül, hogy a forrásfádat összezavarnád. A forráson kívüli építés használatához hozzon létre egy építési könyvtárat a legfelső szintű mappában (technikailag ez bárhol lehet, de a legfelső szintű projektmappa logikus választásnak tűnik). Ezután váltsunk át a build könyvtárba, és futtassuk a cmake-et a felső szintű CMakeLists.txt könyvtárra mutatva. Például:

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

Ne feledd, hogy a build könyvtáradban legyél, és a cmake-et csak a felső szintű CMakeLists.txt fájlt tartalmazó könyvtárra irányítsd, ne magára a fájlra. Ha minden jól megy, a cmake feldolgozza a CMakeLists.txt fájlokat, megkeresi az összes könyvtár és include elérési útvonal helyét, és egy csomó konfigurációs információt, beleértve egy hagyományos Makefile-t a build könyvtáradban. (Ha ismered az autotools/autohell-t, ez a cmake folyamat hasonló a ./configure-hoz). Most már készen állsz a hagyományos make rendszerrel történő építésre. Futtasd a make-t a build könyvtáradban, hogy mindent lefordíts és linkelj. A CMake még néhány szép színt, előrehaladási sávot is bedob, és elnyom egy csomó gcc kimenetet. Ha bőbeszédű kimenetet akarsz, írd be a VERBOSE=1 make-t (hasznos, ha valami rosszul megy).

Az out of source build és a link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp) beállítása miatt a frissen lefordított bináris állományaink a w01-cpp mappában vannak, abban a build könyvtárban, ahol az imént futtattuk a make-et.

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 

Nyomjuk meg az ESC-t az OpenGL demók kilépéséhez.

Összefoglalás

Ha módosítjuk a kódot a forráskönyvtárunkban, beleértve akár a CMakeLists.txt fájlt is, és újra futtatjuk a make-t a build könyvtárban, a make és a cmake újrafordítja és újraépíti a szükséges módosításokat. Ha csak egy alkönyvtárban végez változtatásokat, akkor a frissítések feldolgozásához egyszerűen futtathatja a make-t a build-fa megfelelő alkönyvtárában.

A forrásból történő építéssel kapcsolatos kezdeti zavar forrása az, hogy alapvetően két példánya van a forrásfának, egy a tényleges forráskóddal, és egy a Makefile-okkal és a bináris futtatható fájlokkal (az építési fában). Valószínűleg a legjobb, ha két ablakot tartunk nyitva, az egyiket a build fában a programok elkészítéséhez és futtatásához, a másikat pedig a forrásfában a forrásfájlok módosításához.

A forrás nélküli buildek egyik jó tulajdonsága, hogy az objektumfájlok, makedepend fájlok, binárisok és egyéb különféle build-zavarok eltakarítása egyszerűen elvégezhető a teljes build könyvtár törlésével, mivel nincs forrás. A make clean segítségével a tényleges objektum- és bináris fájlokat is megtisztíthatod, de ha azt tervezed, hogy a forráskódodat kátrányozni fogod, vagy terjeszted a kódodat a tömegeknek, akkor egyszerűen

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

tisztíthatod és csomagolhatod a kódodat.

Még több felfedeznivaló

Ez csak a felszínét érinti annak, amire a CMake képes. Nézd meg a CMake Wiki-t további információkért. Remélem, hogy frissíteni fogom ezt az oldalt, ha összetettebb példákba botlunk, és szívesen fogadok visszajelzéseket vagy tippeket más kurzusoktól, amelyek esetleg CMake-et használnak. A nagyon haladó felhasználók számára a CMake-nek van egy társprogramja, a CPack, amely automatikusan csomagolja a binárisokat és a forrást Ubuntu/Debian (.deb), Red Hat (.rpm), OSXX11, tgz, CygWin és Nullsoft rendszerekhez.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.