Minimální verze
Tady je první řádek každého CMakeLists.txt
, což je požadovaný název souboru, který CMake hledá:
cmake_minimum_required(VERSION 3.1)
Zmíníme se trochu o syntaxi CMake. Název příkazucmake_minimum_required
nerozlišuje velká a malá písmena, takže běžnou praxí je používat malá písmena. 1 VERSION
je speciální klíčové slovo pro tuto funkci. A hodnota verze následuje za klíčovým slovem. Stejně jako všude vtéto knize stačí kliknout na název příkazu, abyste viděli oficiální dokumentaci,a pomocí rozbalovacího seznamu můžete přepínat dokumentaci mezi verzemi CMake.
Tento řádek je speciální! 2 Verze CMake bude také diktovat zásady,které definují změny chování. Pokud tedy nastavíte minimum_required
na VERSION2.8
, získáte například v systému MacOS nesprávné chování při linkování, a to i v nejnovějších verzích CMake. Pokud ji nastavíte na verzi 3.3 nebo nižší, získáte nesprávné chování skrytých symbolů atd. Seznam politik a verzí je k dispozici na adresepolitiky.
Počínaje verzí CMake 3.12 to podporuje rozsah, například VERSION 3.1...3.15
;to znamená, že podporujete již verzi 3.1, ale také jste to testovali s nastavením nové politiky až do verze 3.15. To je mnohem příjemnější pro uživatele, kteří potřebují lepšínastavení, a díky triku v syntaxi je to zpětně kompatibilní se staršímiverzemi CMake (i když ve skutečnosti spuštění CMake 3.1-3.11 nastaví pouze 3.1verzi politik v tomto příkladu, protože tyto verze to nijak zvlášť neošetřovaly). Nové verze politik bývají nejdůležitější pro uživatele systémů MacOS aWindows, kteří mají obvykle také velmi čerstvou verzi CMake.
Takto by měly postupovat nové projekty:
cmake_minimum_required(VERSION 3.7...3.20)if(${CMAKE_VERSION} VERSION_LESS 3.12) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})endif()
Pokud je verze CMake nižší než 3.12, blok if bude true a politika bude nastavena na aktuální verzi CMake. Pokud je verze CMake 3.12 nebo vyšší, bude blok if false, ale nová syntaxe v cmake_minimum_required
bude respektována a bude to nadále fungovat správně!
Pozor: Serverový režim CMake MSVC měl původně chybu ve čtení tohoto formátu, takže pokud potřebujete podporovat sestavení systému Windows bez příkazového řádku pro starší verze MSVC,budete chtít místo toho provést toto:
cmake_minimum_required(VERSION 3.7)if(${CMAKE_VERSION} VERSION_LESS 3.20) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})else() cmake_policy(VERSION 3.20)endif()
Pokud zde opravdu potřebujete nastavit nízkou hodnotu, můžete použítcmake_policy
pro podmíněné zvýšení úrovně politiky nebo nastavit specifickou politiku. Udělejte to prosím alespoň pro uživatele systému MacOS!
Nastavení projektu
Nyní bude mít každý soubor CMake nejvyšší úrovně následující řádek:
project(MyProject VERSION 1.0 DESCRIPTION "Very nice project" LANGUAGES CXX)
Nyní vidíme ještě více syntaxe. Řetězce jsou v uvozovkách, na bílých místech nezáleží ajméno projektu je první argument (poziční). Všechna klíčová slova jsou zde nepovinná. Verze nastavuje řadu proměnných, napříkladMyProject_VERSION
a PROJECT_VERSION
. Jazyky jsou C
, CXX
,Fortran
, ASM
, CUDA
(CMake 3.8+), CSharp
(3.8+) a SWIFT
(experimentální CMake3.15+). C CXX
je výchozí hodnota. Ve verzi CMake 3.9 byl přidán parametr DESCRIPTION
, který umožňuje nastavit také popis projektu. Nápomocná může být dokumentace pro project
.
Komentáře můžete přidávat pomocí znaku #
. CMake má pro komentáře také řádkovou syntaxi, ale ta se používá jen zřídka.
Na názvu projektu není opravdu nic zvláštního. V tomto bodě se nepřidávají žádné cíle.
Vytvoření spustitelného souboru
Ačkoli jsou knihovny mnohem zajímavější a strávíme s nimi většinu času, začneme s jednoduchým spustitelným souborem.
add_executable(one two.cpp three.h)
Je zde několik věcí, které je třeba rozbalit. one
je jednak jméno vygenerovaného spustitelného souboru, jednak jméno vytvořeného cíle CMake (o cílech brzy uslyšíte mnohem více, slibuji). Následuje seznam zdrojových souborů, kterých můžete uvést libovolný počet. CMake je chytrý a zkompiluje pouze přípony zdrojových souborů. Hlavičky budou pro většinu záměrů a účelů ignorovány; jediný důvod, proč je uvádět, je ten, aby se zobrazily v IDE. Cílové soubory se v mnoha IDE zobrazují jako složky. Více o obecném systému sestavování a cílech najdete na stránce buildsystem.
Vytvoření knihovny
Vytvoření knihovny se provádí pomocí add_library
a je stejně jednoduché:
add_library(one STATIC two.cpp three.h)
Můžete si vybrat typ knihovny, STATIC, SHARED nebo MODULE. Pokud tuto volbu necháte vypnutou, použije se hodnota BUILD_SHARED_LIBS
pro výběr mezi STATIC a SHARED.
Jak uvidíte v následujících částech, často budete potřebovat vytvořit fiktivní cíl, tedy takový, kde není třeba nic kompilovat, například pro knihovnu pouze s hlavičkami. Taková knihovna se nazývá INTERFACE a je další možností; jediným rozdílem je, že za ní nemohou následovat jména souborů.
Můžete také vytvořit ALIAS
knihovnu s existující knihovnou, čímž jednoduše získáte nové jméno pro cíl. Jedinou výhodou je, že můžete vytvářet knihovny s ::
v názvu (což uvidíte později). 3
Targets are your friend
Teď jsme zadali cíl, jak o něm přidáme informace? Například možná potřebuje adresář include:
target_include_directories(one PUBLIC include)
target_include_directories
přidá k cíli adresář include. PUBLIC
pro spustitelný soubor mnoho neznamená; pro knihovnu dává CMake vědět, že všechny cíle, které se na tento cíl odkazují, musí také potřebovat tento adresář include. Další volby jsou PRIVATE
(ovlivňuje pouze aktuální cíl, nikoli závislosti) a INTERFACE
(potřebný pouze pro závislosti).
Můžeme pak řetězit cíle:
add_library(another STATIC another.cpp another.h)target_link_libraries(another PUBLIC one)
target_link_libraries
je pravděpodobně nejužitečnější a nejzmatenější příkaz v CMake. Přijímá cíl (another
) a přidává závislost, pokud je cíl zadán. Pokud žádný cíl tohoto jména (one
) neexistuje, přidá odkaz na knihovnu s názvem one
na vaší cestě (odtud název příkazu). Nebo mu můžete zadat úplnou cestu ke knihovně. Nebo příznak linkeru. Jen na závěr dodám trochu zmatku: klasický CMake umožňoval vynechat výběr klíčového slova PUBLIC
atd. Pokud to bylo provedeno v cíli, dostanete chybu, pokud se pokusíte míchat styly dále v řetězci.
Soustřeďte se na používání cílů všude a klíčových slov všude a bude to v pořádku.
Cíle mohou mít adresáře include, linkované knihovny (nebo linkované cíle), volby kompilace, definice kompilace, funkce kompilace (viz kapitola C++11) a další. Jak uvidíte ve dvou kapitolách o zahrnutí projektů, můžete často získat cíle (a vždy vytvořit cíle), které budou představovat všechny používané knihovny. Dokonce i věci, které nejsou skutečnými knihovnami, jako je OpenMP, lze reprezentovat pomocí cílů. Proto je Modern CMake skvělý!
Ponořte se
Podívejte se, zda dokážete sledovat následující soubor. Vytváří jednoduchou knihovnu C++11 a program, který ji používá. Žádné závislosti. Další možnosti standardu C++ proberu později, zatím používám systém CMake 3.8.
cmake_minimum_required(VERSION 3.8)project(Calculator LANGUAGES CXX)add_library(calclib STATIC src/calclib.cpp include/calc/lib.hpp)target_include_directories(calclib PUBLIC include)target_compile_features(calclib PUBLIC cxx_std_11)add_executable(calc apps/calc.cpp)target_link_libraries(calc PUBLIC calclib)
1. V této knize se většinou vyhnu tomu, abych vám ukazoval špatný způsob, jak věci dělat; na internetu najdete spoustu příkladů. Občas se zmíním o alternativách, ale ty se nedoporučují, pokud nejsou nezbytně nutné; často jsou zde jen proto, aby vám pomohly při čtení staršího kódu CMake.
2. Občas zde uvidíte
FATAL_ERROR
, který byl potřeba pro podporu pěkných chyb při spuštění v CMake <2.6, což už by neměl být problém.
3. Syntaxe
::
byla původně určena proINTERFACE IMPORTED
knihovny, což měly být výslovně knihovny definované mimo aktuální projekt. Z tohoto důvodu však většina příkazůtarget_*
nefunguje na knihovnáchIMPORTED
, což znesnadňuje jejich vlastní nastavení. Klíčové slovoIMPORTED
tedy prozatím nepoužívejte a místo něj použijte cílALIAS
; bude to v pořádku, dokud nezačnete cíle exportovat. Toto omezení bylo opraveno v CMake 3.11.