Minimiversio
Tässä on jokaisen CMakeLists.txt
:n ensimmäinen rivi, joka on CMaken etsimän tiedoston vaadittu nimi:
cmake_minimum_required(VERSION 3.1)
Mainitaanpa hieman CMaken syntaksia. Komennon nimicmake_minimum_required
ei erota isoja ja pieniä kirjaimia, joten yleinen käytäntöon käyttää pieniä kirjaimia. 1 VERSION
on erityinen avainsana tälle toiminnolle. Ja version arvo seuraa avainsanaa. Kuten kaikkialla tässä kirjassa, klikkaa komennon nimeä nähdäksesi virallisen dokumentaation,ja käytä pudotusvalikkoa vaihtaaksesi dokumentaatiota CMake-versioiden välillä.
Tämä rivi on erityinen! 2 CMaken versio sanelee myös käytännöt,jotka määrittelevät käyttäytymisen muutokset. Jos siis asetat minimum_required
:n VERSION2.8
:ksi, saat vääränlaisen linkityskäyttäytymisen esimerkiksi macOS:ssä, jopa uusimmissa CMake-versioissa. Jos asetat sen arvoksi 3.3 tai vähemmän, saat väärän käyttäytymisen piilotettujen symbolien suhteen jne. Luettelo käytännöistä ja versioista on saatavilla osoitteessapolicies.
Alkaen CMake 3.12:sta tämä tukee vaihteluväliä, kuten VERSION 3.1...3.15
;tämä tarkoittaa, että tuet niinkin alhaista kuin 3.1:tä, mutta olet myös testannut sitä uusilla politiikkasäädöksillä aina 3.15:een asti. Tämä on paljon miellyttävämpää käyttäjille, jotka tarvitsevat parempia asetuksia, ja syntaksissa olevan tempun ansiosta se on taaksepäin yhteensopiva CMaken vanhempien versioiden kanssa (vaikka itse asiassa CMake 3.1-3.11:n käyttäminen asettaa vain 3.1-version politiikat tässä esimerkissä, koska nuo versiot eivät käsitelleet tätä erityisesti). Uudet versiot käytännöistä ovat yleensä tärkeimpiä macOS- jaWindows-käyttäjille, joilla on yleensä myös hyvin tuore CMake-versio.
Tämä on mitä uusien projektien tulisi tehdä:
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()
Jos CMake-versio on pienempi kuin 3.12, if-lohko on true, ja käytännöt asetetaan nykyiseen CMake-versioon. Jos CMake on 3.12 tai uudempi, if-lohko on false, mutta cmake_minimum_required
:n uutta syntaksia noudatetaan ja tämä toimii edelleen oikein!
VAROITUS: MSVC:n CMake-palvelintilassa oli alunperin vikaa tämän muodon lukemisessa, joten jos sinun täytyy tukea komentorivin ulkopuolisia Windows-rakentamisia vanhemmille MSVC-versioille,sinun kannattaa tehdä sen sijaan näin:
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()
Jos sinun on todella asetettava alhainen arvo tässä, voit käyttääcmake_policy
nostamaan politiikka-arvon tasoa ehdollisena tai asettamaan spesifisen politiikan. Tee tämä ainakin macOS-käyttäjille!
Projektin asettaminen
Nyt jokaisessa ylimmän tason CMake-tiedostossa on seuraava rivi:
project(MyProject VERSION 1.0 DESCRIPTION "Very nice project" LANGUAGES CXX)
Nyt näemme vielä enemmän syntaksia. Merkkijonot ovat lainausmerkeissä, välilyönneillä ei ole väliä, japrojektin nimi on ensimmäinen argumentti (positional). Kaikki avainsana-argumentit tässä ovat valinnaisia. Versio asettaa joukon muuttujia, kutenMyProject_VERSION
ja PROJECT_VERSION
. Kielet ovat C
, CXX
,Fortran
, ASM
, CUDA
(CMake 3.8+), CSharp
(3.8+) ja SWIFT
(CMake3.15+ experimental). C CXX
on oletusarvo. CMake 3.9:ssä lisättiin DESCRIPTION
myös projektin kuvauksen asettamista varten. project
:n dokumentaatiosta voi olla apua.
Kommentteja voi lisätä #
-merkillä. CMakessa on myös inline-syntaksi kommentteja varten, mutta sitä käytetään harvoin.
Projektin nimessä ei oikeastaan ole mitään erityistä. Kohteita ei lisätä tässä vaiheessa.
Toteutettavan ohjelman tekeminen
Vaikka kirjastot ovat paljon mielenkiintoisempia, ja tulemme viettämään suurimman osan ajastamme niiden kanssa, aloitetaan yksinkertaisesta suoritettavasta ohjelmasta.
add_executable(one two.cpp three.h)
Tässä on useita purettavia asioita. one
on sekä luodun suoritettavan tiedoston nimi että luodun CMake-kohteen nimi (kuulet pian paljon enemmän kohteista, lupaan sen). Lähdetiedostoluettelo tulee seuraavaksi, ja voit luetella niin monta kuin haluat. CMake on fiksu ja kääntää vain lähdetiedostopäätteitä. Otsikot jätetään useimmiten huomiotta; ainoa syy niiden listaamiseen on saada ne näkymään IDE:ssä. Kohteet näkyvät kansioina monissa IDE-ohjelmissa. Lisää yleisestä build-järjestelmästä ja kohteista löytyy osoitteesta buildsystem.
Kirjaston tekeminen
Kirjaston tekeminen tapahtuu add_library
:llä, ja se on yhtä yksinkertaista:
add_library(one STATIC two.cpp three.h)
Voit valita kirjaston tyypin, STATIC, SHARED tai MODULE. Jos jätät tämän valinnan pois päältä, käytetään BUILD_SHARED_LIBS
:n arvoa valitsemaan STATIC:n ja SHARED:n välillä.
Kuten näet seuraavissa kappaleissa, usein sinun täytyy tehdä kuvitteellinen kohde, eli sellainen, jossa mitään ei tarvitse kääntää, esimerkiksi pelkän otsikkokirjaston kohdalla. Tätä kutsutaan INTERFACE-kirjastoksi, ja se on toinen vaihtoehto; ainoa ero on se, että sitä ei voi seurata tiedostonimet.
Voit myös tehdä ALIAS
-kirjaston olemassa olevalla kirjastolla, jolloin saat vain uuden nimen kohteelle. Tämän yksi hyöty on se, että voit tehdä kirjastoja, joiden nimessä on ::
(jonka näet myöhemmin). 3
Kohteet ovat ystäväsi
Nyt olemme määritelleet kohteen, miten lisäämme tietoa siitä? Ehkä se tarvitsee esimerkiksi include-hakemiston:
target_include_directories(one PUBLIC include)
target_include_directories
lisää kohteeseen include-hakemiston. PUBLIC
ei merkitse paljon suoritettavalle ohjelmalle; kirjastolle se antaa CMaken tietää, että kaikkien tähän kohteeseen linkittyvien kohteiden täytyy myös tarvita tämä include-hakemisto. Muita vaihtoehtoja ovat PRIVATE
(vaikuttaa vain nykyiseen kohteeseen, ei riippuvuuksiin) ja INTERFACE
(tarvitaan vain riippuvuuksiin).
Voidaan sitten ketjuttaa kohteita:
add_library(another STATIC another.cpp another.h)target_link_libraries(another PUBLIC one)
target_link_libraries
on luultavasti CMaken hyödyllisin ja hämmentävin komento. Se ottaa kohteen (another
) ja lisää riippuvuuden, jos kohde on annettu. Jos kyseisen nimistä kohdetta (one
) ei ole olemassa, se lisää linkin polullasi olevaan kirjastoon nimeltä one
(siitä komennon nimi). Tai voit antaa sille koko kirjaston polun. Tai linkityslippulauseen. Lisätäkseni viimeisen sekaannuksen, klassinen CMake mahdollisti sen, että voit ohittaa avainsanavalinnan PUBLIC
jne. Jos tämä tehtiin kohteessa, saat virheilmoituksen, jos yrität sekoittaa tyylejä alempana ketjussa.
Keskity käyttämään kohteita kaikkialla ja avainsanoja kaikkialla, niin pärjäät hyvin.
Kohteissa voi olla include-hakemistoja, linkitettyjä kirjastoja (tai linkitettyjä kohteita), käännösvaihtoehtoja, käännösmäärittelyjä, käännösominaisuuksia (ks. C++11-lukua) ja muuta. Kuten näet kahdessa including projects -luvussa, voit usein saada kohteet (ja aina tehdä kohteet) edustamaan kaikkia käyttämiäsi kirjastoja. Jopa asiat, jotka eivät ole todellisia kirjastoja, kuten OpenMP, voidaan esittää kohteilla. Tämän takia Modern CMake on loistava!
Sukella sisään
Katso, voitko seurata seuraavaa tiedostoa. Siinä tehdään yksinkertainen C++11-kirjasto ja sitä käyttävä ohjelma. Ei mitään riippuvuuksia. Käsittelen myöhemmin lisää C++-standardivaihtoehtoja, käytän toistaiseksi CMake 3.8 -järjestelmää.
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. Tässä kirjassa vältän enimmäkseen näyttämästä sinulle väärää tapaa tehdä asioita; netistä löytyy runsaasti esimerkkejä siitä. Mainitsen silloin tällöin vaihtoehtoja, mutta niitä ei suositella, elleivät ne ole ehdottoman välttämättömiä; usein ne ovat vain apuna vanhemman CMake-koodin lukemisessa.
2. Näet joskus tässä
FATAL_ERROR
, jota tarvittiin tukemaan mukavia epäonnistumisia, kun tätä ajettiin CMake <2.6:ssa, minkä ei pitäisi enää olla ongelma.
3.
::
-syntaksi oli alun perin tarkoitettuINTERFACE IMPORTED
-kirjastoille, joiden piti nimenomaan olla nykyisen projektin ulkopuolella määriteltyjä kirjastoja. Mutta tämän takia useimmattarget_*
-komennot eivät toimiIMPORTED
-kirjastoissa, mikä tekee niistä vaikeasti itse määritettäviä. Älä siis toistaiseksi käytäIMPORTED
-avainsanaa ja käytä sen sijaanALIAS
-kohdetta; se toimii hyvin, kunnes alat viedä kohteita. Tämä rajoitus korjattiin CMake 3.11:ssä.