Tento dokument poskytuje stručný přehled o CMake – multiplatformní alternativě k linuxovým Makefile a make. Nápovědu k používání make a Makefiles bez CMake naleznete v dokumentaci profesora Newhalla. Tento dokument byl napsán pro cmake verze 2.6, který je nainstalován na laboratorních strojích prostřednictvím stow (od ledna 2009).
Osobně mám CMake rád, protože se mi zdá intuitivnější než psaní standardního souboru Make. Základní a běžné věci jsou docela snadné a složitější věci jsou možné, i když většina věcí, které sestavuji, jsou docela základní. Pro demonstraci CMake jsem přiložil několik ukázek kódu v souboru cmake.tgz (4 KB). Soubor uložte a jeho obsah rozbalte kdekoli ve svém adresáři. Například:
$ tar xzvf cmake.tgz$ cd cmake$ lsCMakeLists.txt w01-cpp/
CMake se ovládá zápisem instrukcí do souborů CMakeLists.txt. Každý adresář ve vašem projektu by měl mít soubor CMakeLists.txt. Na systému CMake je příjemné, že soubory CMakeLists.txt v podadresáři dědí vlastnosti nastavené v nadřazeném adresáři, což snižuje množství duplicitního kódu. V našem ukázkovém projektu máme pouze jeden podadresář: w01-cpp. Soubor CMakeLists.txt pro adresář cmake nejvyšší úrovně je poměrně jednoduchý, ale demonstruje několik klíčových vlastností.
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)
Tento ukázkový kód obsahuje kód, který pro grafiku vyžaduje externí knihovny OpenGL. V typické konfiguraci souboru Makefile bychom pravděpodobně potřebovali určit, kde jsou hlavičkové soubory OpenGL, např. -I/usr/local/include, které knihovny se mají použít, např. -lGL -lGLU -lglut, a umístění knihoven. Umístění hlavičkových souborů a knihoven se pravděpodobně liší od instalace k instalaci a od platformy k platformě. Obvykle však existuje několik standardních míst, kde je třeba hledat, a CMake toto hledání automatizuje pomocí maker find_package. Takto find_package(GLUT) a find_package(OpenGL) vyhledá umístění hlavičkových souborů a knihoven a nastaví nejběžnější knihovny, které se linkují v typickém projektu OpenGL. CMake má podporu pro vyhledávání mnoha balíčků. Další příklady najdete v /usr/local/share/cmake-2.6/Modules/Find*.cmake. Chcete-li použít jeden z těchto skriptů, použijte příkaz find_package(PKGname), pokud se skript CMake jmenuje FindPKGname.cmake.
Další informace o vyhledávání externích knihoven nebo vytváření vlastních maker pro vyhledávání balíčků naleznete na wiki KitWare.
Běžné příznaky, které byste nastavili v typickém souboru Makefile, můžete nastavit pomocíingset(VARNAME VALUE). V tomto příkladu jsem povolil ladění symbolů (-g) a všechna varování (-Wall). Také jsem tomuto projektu CMake dal jméno pomocí project(CMAKEDEMO). Svůj projekt můžete pojmenovat, jak chcete. Tyto informace použijeme v souboru CMakeLists.txt v adresáři w01-cpp. Nakonec naznačíme, že většina kódu je skutečně v adresáři w01-cpp, a to tak, že našemu souboru CMakeLists.txt nejvyšší úrovně řekneme add_subdirectory(w01-cpp)
Podívejme se na soubor CMakeLists.txt v podadresáři 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)
Makro include_directories říká CMake, kde má hledat zdrojové soubory. Deklarováním názvu projektu CMAKEDEMO v souboru CMakeLists.txt nejvyšší úrovně se nastaví proměnné CMAKEDEMO_SOURCE_DIR a CMAKEDEMO_BINARY_DIR v závislosti na aktuálním umístění vašeho kódu a aktuálním umístění adresáře pro sestavení (více o tomto druhém umístění později). Přidání cíle pro nový binární spustitelný soubor je snadné. Stačí přidat řádek add_executable(cdemo cdemo.c). CMake automaticky zjistí kompilátor na základě přípony typu souboru. Pokud jsou zapotřebí další knihovny, můžete programu CMake říci, aby je linkoval pomocí target_link_libraries(cdemo m). Tím řeknete programu CMake, že program cdemo se musí linkovat proti matematické knihovně. Můžete linkovat proti více než jedné knihovně zadáním knihoven v seznamu. Viz například set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m). Proměnné GLUT_LIBRARY a OPENGL_LIBRARY nastaví CMake, když jsme použili příkazy find_package(GLUT) a find_package(OpenGL). Chcete-li zjistit, které proměnné se nastavují při použití find_package, budete pravděpodobně muset otevřít příslušný soubor Find*.cmake a přečíst si obvykle užitečnou, ale stručnou dokumentaci.
Protože je několik programů v této složce w01-cpp zkompilováno stejným způsobem a linkováno proti stejným knihovnám, můžeme je všechny zpracovat pomocí výše uvedené jednoduché smyčky s použitím makra foreach v CMake. Nakonec si ukážeme, jak vytvořit vlastní knihovnu pomocí add_library(geometry geometry.cpp) a linkování proti této knihovně v target_link_libraries(test_geometry ${CORELIBS} geometry).
Nastavení několika souborů CMakeLists.txt vám hned neumožní sestavit projekt. CMake je pouze multiplatformní obal kolem tradičnějších systémů sestavování. V případě Linuxu to znamená make. Rychlý krok předzpracování automaticky převede váš popis CMakeLists.txt na tradiční sestavovací systém make. Jednou z pěkných a velmi doporučovaných vlastností CMake je možnost provádět sestavení ze zdrojových kódů. Tímto způsobem můžete vytvořit všechny své soubory .o, různé dočasné závislé soubory a dokonce i binární spustitelné soubory, aniž byste zahltili svůj zdrojový strom. Chcete-li používat sestavení mimo zdrojový kód, vytvořte adresář pro sestavení ve složce nejvyšší úrovně (technicky vzato to může být kdekoli, ale složka projektu nejvyšší úrovně se zdá být logickou volbou). Poté přejděte do adresáře pro sestavení a spusťte příkaz cmake s nasměrováním na adresář CMakeLists.txt nejvyšší úrovně. Například:
cumin$ cd cmake/cumin$ lsCMakeLists.txt w01-cpp/cumin$ mkdir buildcumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ cd build/cumin$ cmake ..
Nezapomeňte být v adresáři pro sestavení a nasměrovat cmake pouze na adresář obsahující soubor CMakeLists.txt nejvyšší úrovně, nikoli na soubor samotný. Pokud vše proběhne v pořádku, cmake zpracuje vaše soubory CMakeLists.txt, zjistí umístění všech knihoven a cest k include a vypustí do vašeho adresáře pro sestavení spoustu konfiguračních informací včetně tradičního souboru Makefile. (Pokud máte nějaké povědomí o autotools/autohell, je tento proces cmake podobný procesu ./configure). Nyní jste připraveni k sestavení pomocí tradičního systému make. Spusťte make v adresáři pro sestavení, abyste vše zkompilovali a nalinkovali. CMake dokonce přihodí několik pěkných barev, ukazatele průběhu a potlačí spoustu výstupu gcc. Pokud chcete slovní výstup, můžete zadat VERBOSE=1 make (užitečné, pokud se něco pokazí).
Vzhledem k tomu, jak jsme nastavili sestavení ze zdrojových kódů a adresáře link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp), jsou naše čerstvě zkompilované binární soubory ve složce w01-cpp v adresáři sestavení, kde jsme právě spustili 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
Stisknutím ESC ukončíte demoverzi OpenGL.
Pokud změníte kód ve zdrojovém adresáři, včetně třeba i souboru CMakeLists.txt, a znovu spustíte make v adresáři pro sestavení, make a cmake překompilují a znovu sestaví potřebné změny. Pokud provádíte změny pouze v podadresáři, můžete jednoduše spustit make v příslušném podadresáři ve stromu sestavení a zpracovat aktualizace.
Počáteční zmatek při sestavování ze zdrojových kódů spočívá v tom, že máte v podstatě dvě kopie zdrojového stromu, jednu se skutečným zdrojovým kódem a druhou se soubory Make a binárními spustitelnými soubory (ve stromu sestavení). Pravděpodobně je nejlepší mít otevřená dvě okna, jedno ve stromu sestavení pro vytváření a spouštění programů a jedno okno ve stromu zdrojových kódů pro úpravy zdrojových souborů.
Jednou z příjemných věcí na sestaveních mimo zdrojové kódy je, že čištění objektových souborů, souborů makedepend, binárních souborů a dalšího různého odpadu pro sestavení lze provést prostým smazáním celého adresáře sestavení, protože v něm nejsou žádné zdrojové kódy. K vyčištění skutečných objektových a binárních souborů můžete také použít make clean, ale pokud plánujete zdrojový kód zmastit nebo distribuovat masám, můžete jednoduše provést
cumin$ cd cmakecumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ rm -rf build/cumin$ lsCMakeLists.txt w01-cpp/
úklid a zabalení kódu.
Toto se jen dotýká povrchu toho, co CMake umí. Podívejte se na Wiki CMake, kde najdete další informace. Doufám, že tuto stránku budu aktualizovat, pokud narazíme na složitější příklady, a rád přijmu zpětnou vazbu nebo tipy z jiných kurzů, které by mohly CMake používat. Pro velmi pokročilé uživatele má CMake doprovodný program CPack pro automatické balení binárních souborů a zdrojových kódů pro systémy Ubuntu/Debian (.deb), Red Hat (.rpm), OSXX11, tgz, CygWin a Nullsoft.