
Arenduse kĂ€igus meeldib mulle vahetada kompilaatoreid, koostamisreĆŸiime, sĂ”ltuvuste versioone, teostada staatilist analĂŒĂŒsi, mÔÔta jĂ”udlust, koguda katvust, genereerida dokumentatsiooni jne. Ja mulle vĂ€ga meeldib CMake, sest see vĂ”imaldab mul teha kĂ”ike seda, mida ma tahan.
Paljud kritiseerivad CMakeâi ja tihti Ă”igustatult, kuid kui sĂŒveneda, siis ei ole kĂ”ik nii hull ja viimasel ajal isegi ĂŒsna hĂ€sti, ning arengu suund on igati positiivne.
KĂ€esolevas mĂ€rkuses tahan rÀÀkida, kuidas on ĂŒsna lihtne korraldada C++ keeles pealkirjafaili CMake sĂŒsteemis, et saavutada jĂ€rgmine funktsionaalsus:
- Koostamine;
- Automaatne testide kÀivitamine;
- Koodikatvuse mÔÔtmine;
- Installeerimine;
- Autodokumenteerimine;
- Veebihoiuruumi genereerimine;
- Staatiline analĂŒĂŒs.
Kes juba teab plussidest ja CMakeâist, vĂ”ib lihtsalt ja hakata seda kasutama.
Sisu
.
âââ CMakeLists.txt
âââ README.en.md
âââ README.md
âââ doc
â âââ CMakeLists.txt
â âââ Doxyfile.in
âââ include
â âââ mylib
â âââ myfeature.hpp
âââ online
â âââ CMakeLists.txt
â âââ mylib-example.cpp
â âââ wandbox.py
âââ test
âââ CMakeLists.txt
âââ mylib
â âââ myfeature.cpp
âââ test_main.cppPeamiselt kĂ€sitletakse, kuidas organiseerida CMake-skripte, seega uurime neid ĂŒksikasjalikult. ĂlejÀÀnud faile saavad huvilised otseselt vaadata .
Esiteks tuleb kĂŒsida vajaliku CMake sĂŒsteemi versiooni. CMake areneb, muutuvad kĂ€skude signatuurid ja kĂ€itumine erinevates tingimustes. Et CMake mĂ”istaks kohe, mida me temalt tahame, peame kohe fikseerima meie nĂ”udmised.
cmake_minimum_required(VERSION 3.13)SeejÀrel mÀÀratleme meie projekti, selle nime, versiooni, kasutatavad keeled ja muud (vt. ).
Selles olukorras mÀÀrame keele CXX (mis tÀhendab C++), et CMake ei peaks muretsema ja ei peaks otsima C keele kompilaatorit (CMake sisaldab vaikimisi kahte keelt: C ja C++).
project(Mylib VERSION 1.0 LANGUAGES CXX)Siit saate kohe kontrollida, kas meie projekt on mÔnes teises projektis alamprojekti kujul. See aitab edaspidi palju.
get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)
Arvutame vÀlja kaks valikut.
Esimene valik â â moodultestide vĂ€lja lĂŒlitamiseks. See vĂ”ib olla vajalik, kui oleme kindlad, et testid on korras ja soovime nĂ€iteks ainult oma projekti installida vĂ”i paketitada. VĂ”i on meie projekt alamprojektina kaasatud â sel juhul ei ole meie projekti kasutaja huvitatud meie testide kĂ€ivitamisest. Kas te ei testeeri sĂ”ltuvusi, mida kasutate?
option(MYLIB_TESTING "Aktiveeri moodulitestimine" ON)Lisaks teeme eraldi valiku testikattete mÔÔtmiseks, kuid see vajab lisatööriistu, seega tuleb see selgesÔnaliselt aktiveerida.
option(MYLIB_COVERAGE "Aktiveeri testikattete mÔÔtmine" OFF)
Muidugi oleme me lahedad C++ programmeerijad, seega soovime kompilatsioonivaatleja maksimaalset diagnoosimist kompilatsiooni ajal. Ăkski hiir ei pÀÀse lĂ€bi.
add_compile_options(
-Werror
-Wall
-Wextra
-Wpedantic
-Wcast-align
-Wcast-qual
-Wconversion
-Wctor-dtor-privacy
-Wenum-compare
-Wfloat-equal
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wredundant-decls
-Wsign-conversion
-Wsign-promo
)Laieltame laiendused vĂ€lja, et tĂ€ielikult vastata C++ keele standardile. CMake'is on need vaikimisi sisse lĂŒlitatud.
if(NOT CMAKE_CXX_EXTENSIONS)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
Meie teek koosneb ainult pĂ€istefailidest, seega ei ole meil mingit vĂ€ljundit staatiliste vĂ”i dĂŒnaamiliste teekide nĂ€ol. Teisest kĂŒljest, et kasutada meie teeki vĂ€ljastpoolt, tuleb see installida, et see oleks sĂŒsteemis avastatav ja seostatav oma projektiga, samas koos kaasnevate pĂ€iste ning vĂ”imalik, et ka mĂ”ne tĂ€iendava omadusega.
Selle eesmÀrgi saavutamiseks loome liidese teegi.
add_library(mylib INTERFACE)Seome pÀised meie liidese teegiga.
Kaasaegne, trendikas ja noortele suunatud CMake'i kasutamine eeldab, et pĂ€ised, omadused jt edastatakse lĂ€bi ĂŒheainsa sihisse. Seega piisab öelda , ja kĂ”ik pealkirjad, mis on seotud eesmĂ€rgiga sĂ”ltuvus, on saadaval allikate jaoks, mis kuuluvad eesmĂ€rgile target. Ja mingeid ei nĂ”uta [target_]include_directories. Seda demonstreeritakse allpool, kui kĂ€sitletakse .
Samuti tasub tÀhele panna nn .
See kĂ€sk seondab vajalikud pealkirjad meie liidesti raamatukoguga; kui meie raamatukogu on ĂŒhendatud mĂ”ne eesmĂ€rgiga sama CMake hierarhia raames, siis seondatakse selle liidese pealkirjad direktorist ${CMAKE_CURRENT_SOURCE_DIR}/include, ja kui meie raamatukogu on installitud sĂŒsteemi ja ĂŒhendatud teises projektis kĂ€suga , siis seondatakse selle pealkirjad direktorist include installatsiooni direktorist.
target_include_directories(mylib INTERFACE
$
$
)Seame keele standardi. Loomulikult, kÔige uuema. Samuti mitte lihtsalt standardi kaasamine, vaid ka selle laiendamine nendele, kes meie raamatukogu kasutavad. See saavutatakse seetÔttu, et seatud omadus kuulub kategooriasse INTERFACE (vt. ).
target_compile_features(mylib INTERFACE cxx_std_17)Loome alias meie teegile. Ja kauni vĂ€ljanĂ€gemise nimel asetame selle spetsiaalsesse ânimetĂŒkkiâ. See on kasulik, kui meie teegis ilmuvad erinevad moodulid, ja me saame neid iseseisvalt lisada. .
add_library(Mylib::mylib ALIAS mylib)
Meie pĂ€isefailide installimine sĂŒsteemi. Siin on kĂ”ik lihtne. Ătleme, et kaust, kus kĂ”ik pĂ€isefailid asuvad, peab jĂ”udma installatsioonikausta include installatsiooni asukoha suhtes.
install(DIRECTORY include/mylib DESTINATION include)SeejĂ€rel teavitame ehitussĂŒsteemi, et soovime, et vĂ”ime kolmandates projektides kutsuda kĂ€sklust find_package(Mylib) ja saada eesmĂ€rgi Mylib::mylib.
install(TARGETS mylib EXPORT MylibConfig)
install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake)JĂ€rgmine peatĂŒkk tuleb mĂ”ista nii. Kui kolmandas projektis kutsume kĂ€skluse find_package(Mylib 1.2.3 REQUIRED), ja samas osutub installitud teegi tegelik versioon mitte ĂŒhilduv versiooniga 1.2.3, genereerib CMake automaatselt vea. See tĂ€hendab, et versioonide jĂ€lgimisega ei pea enam kĂ€sitsi tegelema.
include(CMakePackageConfigHelpers)
write_basic_package_version_file("${PROJECT_BINARY_DIR}/MylibConfigVersion.cmake"
VERSION
${PROJECT_VERSION}
COMPATIBILITY
AnyNewerVersion
)
install(FILES "${PROJECT_BINARY_DIR}/MylibConfigVersion.cmake" DESTINATION share/Mylib/cmake)
Kui testid on vĂ€lja lĂŒlitatud vĂ”i meie projekt on alaprojekt, st see on seotud teise CMake-projektiga kĂ€sklusega , siis me ei jĂ€tka hierarhias edasi ning skript, milles on kirjas testide genereerimise ja kĂ€itamise kĂ€sklused, ei kĂ€ivitu.
if(NOT MYLIB_TESTING)
message(STATUS "Mylibi projekti testimine on vĂ€lja lĂŒlitatud")
elseif(IS_SUBPROJECT)
message(STATUS "Mylib ei testita alamooduli reĆŸiimis")
else()
add_subdirectory(test)
endif()
Dokumentatsiooni ei genereerita samuti alaprojekti puhul.
if(NOT IS_SUBPROJECT)
add_subdirectory(doc)
endif()
Sarnaselt ei ole alaprojektil ka veebihÔlvijad.
if(NOT IS_SUBPROJECT)
add_subdirectory(online)
endif()
Esmalt leiame paketi vajaliku testimisraamistiku jaoks (asendage oma lemmikuga).
find_package(doctest 2.3.3 REQUIRED)Loomeme meie tÀitmisfail testide jaoks. Tavalise tÀitmise binaari lisan ma tavaliselt ainult faili, kus on funktsioon main.
add_executable(mylib-unit-tests test_main.cpp)Failid, kus testid on kirjeldatud, lisan hiljem. Kuid see pole kohustuslik.
target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp)Ăhendame sĂ”ltuvused. Pange tĂ€hele, et meie binaarprogrammi oleme sidunud vaid vajalike CMake-eesmĂ€rkidega, ja ei kĂ€ivitanud kĂ€sku target_include_directories. Testimisraamistiku ja meie Mylib::mylib, samuti kogumispĂ”himĂ”tted (meie puhul on see keelestandardi C++) lĂ€ksid koos nende eesmĂ€rkidega.
target_link_libraries(mylib-unit-tests
PRIVATE
Mylib::mylib
doctest::doctest
)LÔpuks loome vale eesmÀrgi, mille "kogumine" on vÔrdne testide kÀivitamisega, ja lisame selle eesmÀrgi vaikimisi kogumisse (selle eest vastutab atribuut ALL). See tÀhendab, et vaikimisi kogumine kÀivitab testide kÀivitamise, seega me kunagi ei unusta neid kÀivitada.
add_custom_target(check ALL COMMAND mylib-unit-tests)
JĂ€rgmisena lĂŒlitame sisse koodi katvuse mÔÔtmise, kui vastav valik on mÀÀratud. Ăksikasjadesse ei lasku, kuna need on rohkem seotud katvuse mÔÔtmise tööriistaga kui CMake'iga. Oluline on mĂ€rkida, et tulemuste pĂ”hjal luuakse eesmĂ€rk , millega on mugav katvuse mÔÔtmist kĂ€ivitada.
find_program(GCOVR_EXECUTABLE gcovr)
if(MYLIB_COVERAGE AND GCOVR_EXECUTABLE)
message(STATUS "Koodikattuvuse mÔÔtmine on sisse lĂŒlitatud")
target_compile_options(mylib-unit-tests PRIVATE --coverage)
target_link_libraries(mylib-unit-tests PRIVATE gcov)
add_custom_target(coverage
COMMAND
${GCOVR_EXECUTABLE}
--root=${PROJECT_SOURCE_DIR}/include/
--object-directory=${CMAKE_CURRENT_BINARY_DIR}
DEPENDS
check
)
elseif(MYLIB_COVERAGE AND NOT GCOVR_EXECUTABLE)
set(MYLIB_COVERAGE OFF)
message(WARNING "Koodikattuvuse mÔÔtmiseks on vajalik programm gcovr")
endif()
.
find_package(Doxygen)SeejĂ€rel kontrollime, kas kasutaja on mÀÀranud keele muutujat. Kui jah, siis ei muuda midagi; kui ei, siis valime vene. SeejĂ€rel seadistame Doxygen sĂŒsteemi failid. KĂ”ik vajalikud muutujad, sealhulgas keel, sisestatakse sinna seadistamise protsessi kĂ€igus (vt. ).
PĂ€rast seda loome sihte , mis kĂ€ivitab dokumentatsiooni genereerimise. Kuna dokumentatsiooni genereerimine ei ole arenduse kĂ€igus kĂ”ige hĂ€davajalikum, siis on eesmĂ€rk vaikesĂ€tte jĂ€rgi vĂ€lja lĂŒlitatud ja tuleb selgelt kĂ€ivitada.
if (Doxygen_FOUND)
if (NOT MYLIB_DOXYGEN_LANGUAGE)
set(MYLIB_DOXYGEN_LANGUAGE Estonian)
endif()
message(STATUS "Doxygen dokumentatsioon genereeritakse keeles ${MYLIB_DOXYGEN_LANGUAGE}")
configure_file(Doxyfile.in Doxyfile)
add_custom_target(doc COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
endif ()
Siin leiame kolmanda Pythoni ja loome eesmÀrgi , mis genereerib pÀringu, mis vastab teenuse API-le , ja saadab selle Àra. Vastuseks tuleb link valmis liivakasti.
find_program(PYTHON3_EXECUTABLE python3)
if(PYTHON3_EXECUTABLE)
set(WANDBOX_URL "https://wandbox.org/api/compile.json")
add_custom_target(wandbox
COMMAND
${PYTHON3_EXECUTABLE} wandbox.py mylib-example.cpp "${PROJECT_SOURCE_DIR}" include |
curl -H "Content-type: application/json" -d @- ${WANDBOX_URL}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
mylib-unit-tests
)
else()
message(WARNING "Veebipoli liivakasti loomiseks on vajalik 3. versiooni Python tÔlgendaja")
endif()
NĂŒĂŒd vaatame, kuidas kĂ”ike seda kasutada.
Selle projekti koostamine, nagu iga teise CMake'i koostamissĂŒsteemis, koosneb kahest etapist:
cmake -S tee/kallid -B tee/kallid/koostamisdirektorid [valikud ...]Kui eespool olev kÀsk ei töötanud vanema CMake'i versiooni tÔttu, proovige kirjutada
-S:cmake tee/kallid -B tee/kallid/koostamisdirektorid [valikud ...]
.
cmake --build tee/k/ehitamis/kaust.
cmake -S ... -B ... -DMYLIB_KATTESUS=ON [teised valikud ...]Sisaldab sihti , mille abil saab teha koodikattete mÔÔtmisi testide kaudu.
cmake -S ... -B ... -DMYLIB_TESTIMINE=OFF [teised valikud ...]Pakub vĂ”imalust vĂ€lja lĂŒlitada moodulitestide ehitus ja siht . SeetĂ”ttu lĂŒlitatakse vĂ€lja koodikattete mÔÔtmine (vt ).
Testimine lĂŒlitatakse automaatselt vĂ€lja ka siis, kui projekt lisatakse teise projekti alaprojektina kĂ€suga .
cmake -S ... -B ... -DMYLIB_DOXYGEN_LANGUAGE=English [teised valikud ...]LĂŒlitab dokumentatsiooni keele, mida siht genereerib mÀÀratletud keelele. Saadaval olevate keelte loetelu leiate .
Vaikimisi on lubatud vene keel.
cmake --build tee/k/ehitamis/kaust
cmake --build tee/k/ehitamis/kaust --target allKui siht pole mÀÀratud (mis on ekvivalentne sihiga all), ehitab kÔik saadaval olevad ja kutsub esile sihi .
cmake --build tee/k/ehitamis/kaust --target mylib-unit-testsKompileerib moodulitestid. Vaikimisi lubatud.
cmake --build tee/k/ehitamis/kaust --target checkKĂ€ivitab koostatud (ehitab, kui veel mitte) moodulitestid. Vaikimisi lubatud.
Vaata ka .
cmake --build tee/k/kokkglib/direktori --target coverageAnalĂŒĂŒsib kĂ€ivitatud (kĂ€ivitab, kui veel mitte) mooduliteste testika katte osas .
KattekÀive nÀeb vÀlja umbes nii:
------------------------------------------------------------------------------
GCC Koodi Katte Aruanne
Kataloog: /path/to/cmakecpptemplate/include/
------------------------------------------------------------------------------
Fail Read TĂ€itmine Katte Puudu
------------------------------------------------------------------------------
mylib/myfeature.hpp 2 2 100%
------------------------------------------------------------------------------
KOKKU 2 2 100%
------------------------------------------------------------------------------SihtmÀrk on saadaval ainult lubatud valiku korral .
Vaata ka .
cmake --build tee/k/kokkglib/direktori --target docKĂ€ivitab koodi dokumentatsiooni genereerimise sĂŒsteemi kaudu .
cmake --build tee/k/kokkglib/direktori --target wandboxTeenuse vastus nÀeb vÀlja umbes nii:
{
"permlink" : "QElvxuMzHgL9fqci",
"status" : "0",
"url" : "https://wandbox.org/permlink/QElvxuMzHgL9fqci"
}Selleks kasutatakse teenust . Ei tea, kui vastupidavad nende serverid on, kuid arvan, et selle vÔimaluse kuritarvitamine pole mÔistlik.
Projekt tuleb ĂŒles ehitada silumisreĆŸiimis katte mÔÔtmisega
cmake -S tee/ka/allikad -B tee/ka/ehitus/kaust -DCMAKE_BUILD_TYPE=Debug -DMYLIB_COVERAGE=ON
cmake --build tee/ka/ehitus/kaust --target coverage --parallel 16Projekti installimine ilma eelneva ehitamise ja testimiseta
cmake -S tee/ka/allikad -B tee/ka/ehitus/kaust -DMYLIB_TESTING=OFF -DCMAKE_INSTALL_PREFIX=tee/ka/installimise/kaust
cmake --build tee/ka/ehitus/kaust --target installEhitus vabastamise reĆŸiimis mÀÀratud kompilaatoriga
cmake -S tee/ka/allikad -B tee/ka/ehitus/kaust -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-8 -DCMAKE_PREFIX_PATH=tee/ka/kausta/kuhu/on/paigaldatud/sÔltuvused
cmake --build tee/ka/ehitus/kaust --parallel 4Dokumentatsiooni genereerimine inglise keeles
cmake -S tee/ka/allikad -B tee/ka/ehitus/kaust -DCMAKE_BUILD_TYPE=Release -DMYLIB_DOXYGEN_LANGUAGE=English
cmake --build tee/ka/ehitus/kaust --target doc
3.13
Tegelikult on CMake 3.13 versioon vajalik ainult mĂ”nede kĂ€surea kĂ€skude kĂ€ivitamiseks, mis on selles juhendis kirjeldatud. CMake-skriptide sĂŒntaksist piisab versiooni 3.8 kasutamisest, kui genereerimist kutsutakse muude viisidega.
Testimise raamatukogu
Testimise saab vĂ€lja lĂŒlitada (vt ).
Keele, millel dokumentatsioon genereeritakse, saab valida .
Programmeerimiskeelte tÔlgendus
Automaatseks genereerimiseks .
CMakeâi ja paar hea tööriista abil saab staatilise analĂŒĂŒsi teha minimaalse vaevaga.
Cppcheck
CMakeâis on sisseehitatud tugi staatilise analĂŒĂŒsi tööriistale .
Selleks tuleb kasutada valikut :
cmake -S tee/koodiallikatele -B tee/ehitustehnikate -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;-Itee/koodiallikate/include"PĂ€rast seda kĂ€ivitub staatiline analĂŒĂŒs automaatselt iga kord, kui kompileeritakse ja uuesti kompileeritakse lĂ€htekoodi. Ăkski lisategevus pole vajalik.
Clang
Kasutades imelist tööriista saab samuti staatilist analĂŒĂŒsi kiirelt kĂ€ivitada:
scan-build cmake -S tee/koodiallikatele -B tee/ehitustehnikate -DCMAKE_BUILD_TYPE=Debug
scan-build cmake --build tee/ehitustehnikateSiin, erinevalt Cppcheckist, on iga kord vajalik kÀivitada ehitus lÀbi scan-build.
CMake on vĂ€ga vĂ”imas ja paindlik sĂŒsteem, mis vĂ”imaldab realiseerida funktsionaalsust igasuguste soovide ja vajaduste jĂ€rgi. Ja kuigi sĂŒntaks jĂ€tab mĂ”nikord soovida, ei ole asi tegelikult nii hull, kui teda maalitakse. Kasutage CMakeâi koostesĂŒsteemi ĂŒhiskonna hĂŒvanguks ja oma tervise nimel.
â
Allikas: habr.com
