Minimum verzió
Itt van minden CMakeLists.txt
első sora, ami a CMake által keresett fájl kötelező neve:
cmake_minimum_required(VERSION 3.1)
Mondjuk meg a CMake szintaxisát. A parancsnévcmake_minimum_required
nem érzékeny a nagy- és kisbetűkre, ezért az általános gyakorlat a kisbetűs írásmód. 1 A VERSION
egy speciális kulcsszó erre a funkcióra. A kulcsszó után pedig a verzió értéke következik. Mint mindenhol ebben a könyvben, csak kattintsunk a parancs nevére a hivatalos dokumentáció megtekintéséhez,és a legördülő menü segítségével válthatunk a dokumentáció között a CMake verziók között.
Ez a sor különleges! 2 A CMake verziója diktálja az irányelveket is,amelyek a viselkedésváltozásokat határozzák meg. Tehát, ha a minimum_required
-at VERSION2.8
-ra állítod, akkor például macOS-en rossz linkelési viselkedést kapsz, még a legújabb CMake verziókban is. Ha 3.3-ra vagy annál kisebbre állítod, akkor rossz lesz a rejtett szimbólumok viselkedése, stb. A házirendek és verziók listája elérhető apolicies.
A CMake 3.12-től kezdve ez egy tartományt támogat, például VERSION 3.1...3.15
;ez azt jelenti, hogy már a 3.1-es verziót is támogatja, de az új házirend beállításaival is tesztelték egészen a 3.15-ig. Ez sokkal szebb azoknál a felhasználóknál, akiknek szükségük van a jobb beállításokra, és a szintaxis egy trükkje miatt visszafelé kompatibilis a CMake régebbi verzióival (bár valójában a CMake 3.1-3.11 futtatása csak a 3.1-es verziójú házirendeket fogja beállítani ebben a példában, mivel azok a verziók nem kezelték ezt külön). A házirendek új verziói általában a macOS ésWindows felhasználók számára a legfontosabbak, akik általában a CMake nagyon friss verziójával is rendelkeznek.
Az új projekteknek ezt kell tenniük:
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()
Ha a CMake verziója kisebb, mint a 3.12, az if blokk igaz lesz, és a házirend az aktuális CMake verzióra lesz beállítva. Ha a CMake 3.12 vagy magasabb verziószámú, az ifblokk hamis lesz, de a cmake_minimum_required
új szintaxisát tiszteletben tartjuk, és ez továbbra is megfelelően fog működni!
FIGYELMEZTETÉS: Az MSVC CMake szervermódja eredetileg hibás volt ennek a formátumnak az olvasásában, ezért ha a régebbi MSVC verziókhoz nem parancssoros Windows-építést kell támogatnia,akkor ezt kell tennie helyette:
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()
Ha itt valóban alacsony értékre kell beállítania, akkor acmake_policy
segítségével feltételesen növelheti a házirend szintjét, vagy beállíthat egy specifikus házirendet. Kérlek, legalább ezt tedd meg a macOS felhasználóknak!
Projekt beállítása
Most minden felső szintű CMake fájlban a következő sor lesz:
project(MyProject VERSION 1.0 DESCRIPTION "Very nice project" LANGUAGES CXX)
Most még több szintaxist látunk. A karakterláncok idézőjelben vannak, a szóközök nem számítanak, ésa projekt neve az első argumentum (pozicionális). Minden kulcsszóargumentum itt opcionális. A verzió egy csomó változót állít be, mint példáulMyProject_VERSION
és PROJECT_VERSION
. A nyelvek a C
, CXX
,Fortran
, ASM
, CUDA
(CMake 3.8+), CSharp
(3.8+) és SWIFT
(CMake3.15+ experimental). A C CXX
az alapértelmezett. A CMake 3.9-ben a DESCRIPTION
hozzá lett adva a projekt leírásának beállításához is. Aproject
dokumentációja hasznos lehet.
Az #
karakterrel megjegyzéseket adhat hozzá. A CMake-nek van egy inline szintaxisa is a megjegyzésekhez, de ritkán használják.
A projektnévvel kapcsolatban nincs semmi különös. Ezen a ponton nem adunk hozzá célokat.
Futtatható állomány készítése
Noha a könyvtárak sokkal érdekesebbek, és az időnk nagy részét velük fogjuk tölteni, kezdjük egy egyszerű futtatható állomány elkészítésével.
add_executable(one two.cpp three.h)
Ezzel kapcsolatban több dolgot is ki kell csomagolni. one
egyrészt a generált futtatható fájl neve, másrészt a létrehozott CMake target neve (a targetekről hamarosan többet fogsz hallani, ígérem). A forrásfájlok listája következik, és annyit sorolhatsz fel, amennyit csak szeretnél. A CMake okos, és csak a forrásfájlok kiterjesztéseit fordítja le. A fejléceket a legtöbb esetben figyelmen kívül hagyja; az egyetlen ok a felsorolásukra az, hogy megjelenjenek az IDE-kben. A célok sok IDE-ben mappaként jelennek meg. Az általános építési rendszerről és a célokról bővebben a buildsystem oldalon olvashatsz.
Könyvtár készítése
A könyvtár készítése a add_library
segítségével történik, és nagyjából ilyen egyszerű:
add_library(one STATIC two.cpp three.h)
Választhatod a könyvtár típusát, STATIC, SHARED vagy MODULE. Ha ezt a választást kihagyjuk, akkor a BUILD_SHARED_LIBS
értéke alapján választunk a STATIC és a SHARED között.
Amint azt a következő szakaszokban látni fogjuk, gyakran lesz szükségünk fiktív célkönyvtár készítésére, vagyis olyanra, ahol semmit sem kell lefordítani, például egy csak fejléceket tartalmazó könyvtár esetében. Ezt INTERFACE könyvtárnak hívják, és ez egy másik lehetőség; az egyetlen különbség, hogy nem követhetik fájlnevek.
Egy meglévő könyvtárral is készíthetünk egy ALIAS
könyvtárat, ami egyszerűen egy új nevet ad a célpontnak. Ennek egyetlen előnye, hogy készíthetsz olyan könyvtárakat, amelyeknek a nevében ::
szerepel (amit később látni fogsz). 3
A célpontok a barátaid
Most már megadtunk egy célpontot, hogyan adhatunk hozzá információt? Például lehet, hogy szüksége van egy include könyvtárra:
target_include_directories(one PUBLIC include)
target_include_directories
hozzáad egy include könyvtárat egy célponthoz. A PUBLIC
nem jelent sokat egy végrehajtható program esetében; egy könyvtár esetében tudatja a CMake-kel, hogy minden olyan célnak, amely erre a célpontra linkel, szüksége van erre az include könyvtárra is. További opciók a PRIVATE
(csak az aktuális célpontra hat, a függőségekre nem), és a INTERFACE
(csak a függőségekhez szükséges).
Azután láncolhatjuk a célpontokat:
add_library(another STATIC another.cpp another.h)target_link_libraries(another PUBLIC one)
target_link_libraries
valószínűleg a CMake leghasznosabb és legzavaróbb parancsa. Vesz egy célpontot (another
), és hozzáad egy függőséget, ha megadunk egy célpontot. Ha nincs ilyen nevű target (one
), akkor hozzáad egy linket egy one
nevű könyvtárhoz az útvonaladon (innen a parancs neve). Vagy megadhatja a könyvtár teljes elérési útvonalát. Vagy egy linker flaget. Csak hogy egy utolsó kis zavart okozzon, a klasszikus CMake lehetővé tette, hogy kihagyd a PUBLIC
kulcsszó kiválasztását, stb. Ha ez egy célponton történt, hibát fogsz kapni, ha megpróbálod keverni a stílusokat lejjebb a láncban.
Fókuszálj arra, hogy mindenhol célpontokat használj, és mindenhol kulcsszavakat, és minden rendben lesz.
A célpontokhoz tartozhatnak include könyvtárak, linkelt könyvtárak (vagy linkelt célpontok), fordítási opciók, fordítási definíciók, fordítási funkciók (lásd a C++11 fejezetet), és így tovább. Amint azt a két, projekteket tartalmazó fejezetben látni fogod, gyakran kaphatsz olyan célokat (és mindig készíthetsz célokat), amelyek az összes használt könyvtárat képviselik. Még az olyan dolgok is, amelyek nem valódi könyvtárak, mint például az OpenMP, reprezentálhatók targetekkel. Ezért nagyszerű a Modern CMake!
Merülj bele
Nézd meg, hogy tudod-e követni a következő fájlt. Egy egyszerű C++11 könyvtárat és egy azt használó programot készít. Nincsenek függőségek. Később még több C++ szabványos lehetőséget fogok tárgyalni, egyelőre a CMake 3.8-as rendszerét használva.
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. Ebben a könyvben többnyire kerülni fogom, hogy megmutassam, hogyan kell rosszul csinálni dolgokat; erre rengeteg példát találsz a neten. Időnként megemlítek alternatívákat, de ezeket nem ajánlom, hacsak nem feltétlenül szükséges; gyakran csak azért vannak, hogy segítsenek a régebbi CMake-kód olvasásában.
2. Itt néha
FATAL_ERROR
fogsz látni, erre azért volt szükség, hogy a CMake <2.6-ban történő futtatásakor szép hibákat támogassunk, aminek már nem kellene problémát jelentenie.
3. A
::
szintaxis eredetileg aINTERFACE IMPORTED
könyvtáraknak volt szánva, amelyeknek kifejezetten az aktuális projekten kívül definiált könyvtáraknak kellett volna lenniük. De emiatt atarget_*
parancsok többsége nem működik aIMPORTED
könyvtárakon, ami megnehezíti a saját beállításukat. Ezért egyelőre ne használd aIMPORTED
kulcsszót, és helyette használj egyALIAS
célt; ez jó lesz, amíg el nem kezdesz célokat exportálni. Ezt a korlátozást a CMake 3.11-ben javították.