
Arendusprotsessis meeldib mulle vahetada kompilaatorite, kogumise reĆŸiimide, sĂ”ltuvuste versioonide vahel, teha staatilist analĂŒĂŒsi, mÔÔta jĂ”udlust, koguda katvust, genereerida dokumentatsiooni jne. Ja mulle meeldib vĂ€ga CMake, sest see vĂ”imaldab mul teha kĂ”ike, mida ma tahan.
Paljud inimesed kritiseerivad CMake'i ning tihti on see Ă”igustatud, kuid kui asja lĂ€hemalt uurida, pole asi ĂŒldse nii halb, ja viimase ajal on see isegi pĂ€ris hĂ€sti edenenud, ning areng suund on tĂ€iesti positiivne.
Selles mĂ€rkuses soovin rÀÀkida sellest, kuidas on ĂŒsna lihtne organiseerida C++ peaaguplokki CMake sĂŒsteemis, et saavutada jĂ€rgmine funktsionaalsus:
- Kogumine;
- Automaatne testide kÀivitamine;
- Koodikatvuse mÔÔtmine;
- Paigaldamine;
- Automaatne dokumenteerimine;
- Online-keskkonna genereerimine;
- Staatiline analĂŒĂŒs.
Kes juba teab Plusidest ja CMake'ist, vÔib lihtsalt ja hakkata seda kasutama.
Sisukord
.
âââ 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.cppPĂ”hiliselt rÀÀgime sellest, kuidas organiseerida CMake skripte, seetĂ”ttu kĂ€sitletakse neid pĂ”hjalikult. ĂlejÀÀnud faile saab iga soovija vaadata otse .
Esiteks tuleb kĂŒsida vajalikku versiooni CMake sĂŒsteemist. CMake areneb, kĂ€skude allkirjad ja kĂ€itumine erinevates tingimustes muutuvad. Et CMake kohe mĂ”istaks, mida me temalt ootame, tuleb kohe fikseerida meie ehk nĂ”udmised.
cmake_minimum_required(VERSION 3.13)SeejÀrel tÀhistame oma projekti, selle nime, versiooni, kasutatavad keeled ja muud (vt. ).
Sel juhul mÀÀrame keele CXX (see tĂ€hendab C++), et CMake ei pingutaks ja ei otsiks C keele kompilaatorit (CMake'is on vaikimisi sisse lĂŒlitatud kaks keelt: C ja C++).
project(Mylib VERSION 1.0 LANGUAGES CXX)Siin on vÔimalik kohe kontrollida, kas meie projekt on teises projektis alaprojektina kaasatud. See aitab meid tulevikus oluliselt.
get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)
Kaalume kahte valikut.
Esimene valik â â modulaarsete testide vĂ€ljalĂŒlitamine. See vĂ”ib olla vajalik, kui oleme kindlad, et testidega on kĂ”ik korras, kuid soovime nĂ€iteks oma projekti ainult installida vĂ”i pakkida. VĂ”i on meie projekt kaasatud alaprojektina â sellisel juhul pole meie projekti kasutajale huvi meie teste kĂ€ivitada. Kas te testite sĂ”ltuvusi, mida kasutate?
option(MYLIB_TESTING "Luba modulaarne testimine" ON)Lisaks teeme eraldi valiku kattuvuse mÔÔtmiseks testidega, kuid see vajab tÀiendavaid tööriistu, seega tuleb see selgelt lubada.
option(MYLIB_COVERAGE "Luba testidega kattuvuse mÔÔtmine" OFF)
Muidugi oleme me Ă€gedad C++ programmeerijad ja seetĂ”ttu tahame kompilaatori poolt maksimaalset kompileerimise aja diagnostikat. Ăkski hiir ei lipsa 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
)Samuti keelame laiendused, et tÀielikult vastata C++ keele standardile. CMake'is on need vaikimisi lubatud.
if(NOT CMAKE_CXX_EXTENSIONS)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
Meie teek koosneb ainult pealkirjafailidest, mistĂ”ttu meil ei ole mingit vĂ€ljundit staatiliste vĂ”i dĂŒnaamiliste teekide nĂ€ol. Teisest kĂŒljest, et meie teeki vĂ€ljastpoolt kasutada, tuleb see installida, et seda saaks sĂŒsteemis avastada ja oma projekti lisada, ning sellega peavad olema koos need sama pealkirjad, samuti vĂ”imalikud tĂ€iendavad omadused.
Selle eesmÀrgi saavutamiseks loome liidese teegi.
add_library(mylib INTERFACE)Seome pealkirjad meie liidese teegiga.
Kaasaegne, trendikas ja nooruslik CMake'i kasutamine eeldab, et pealkirjad, omadused jne edastatakse lĂ€bi ĂŒheainsa sihtmĂ€rk. , ja kĂ”ik pealkirjad, mis on seotud sihtmĂ€rgiga dependency, on saadaval sihtmĂ€rgi kuuluvatele lĂ€htekoodidele target. Ja ei ole vaja mingit [target_]include_directories. See this demonstrated below during the breakdown .
It is also worth noting the so-called .
This command associates the necessary headers with our interface library, and if our library is linked to any target within the same CMake hierarchy, it will be associated with headers from the directory ${CMAKE_CURRENT_SOURCE_DIR}/include, and if our library is installed in the system and linked in another project using the command , it will be associated with headers from the directory include relative to the installation directory.
target_include_directories(mylib INTERFACE
$
$
)Set the language standard. Of course, the latest one. Moreover, we not only include the standard but also extend it to those who will use our library. This is achieved by the installed property having the category INTERFACE (vt. ).
target_compile_features(mylib INTERFACE cxx_std_17)Create an alias for our library. For aesthetics, it will be in a special "namespace". This will be useful when different modules appear in our library, and we want to connect them independently of each other. .
add_library(Mylib::mylib ALIAS mylib)
Installing our headers to the system. It's simple. We specify that the folder with all the headers should go to the directory include relative to the installation location.
install(DIRECTORY include/mylib DESTINATION include)Next, we inform the build system that we want to be able to call the command in external projects find_package(Mylib) and obtain the target Mylib::mylib.
install(TARGETS mylib EXPORT MylibConfig)
install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake)The next spell should be understood this way. When in an external project we call the command find_package(Mylib 1.2.3 REQUIRED), and the actual version of the installed library turns out to be incompatible with the version 1.2.3, CMake will automatically generate an error. This means there is no need to manually track versions.
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)
If the tests are explicitly disabled with the vĂ”i meie projekt on alamprojekt, see tĂ€hendab, et see on ĂŒhendatud teise CMake projekti kaudu kĂ€su , me ei liigu hierarhias edasi ja skript, milles on kirjeldatud kĂ€sud testide genereerimiseks ja kĂ€ivitamiseks, lihtsalt ei kĂ€ivitu.
if(NOT MYLIB_TESTING)
message(STATUS "Mylibi projekti testimine on keelatud")
elseif(IS_SUBPROJECT)
message(STATUS "Mylibi ei testita alammodulina")
else()
add_subdirectory(test)
endif()
Dokumentatsiooni ei genereerita ka alamprojekti puhul.
if(NOT IS_SUBPROJECT)
add_subdirectory(doc)
endif()
Sarnaselt ei ole alamprojekti juhul ka veebiliivakaste.
if(NOT IS_SUBPROJECT)
add_subdirectory(online)
endif()
Esiteks otsime paketti vajaliku testimisraamistiku jaoks (asendage oma lemmikuga).
find_package(doctest 2.3.3 REQUIRED)Loome oma kÀivitatava faili testide jaoks. Tavaline on, et kÀivitatavasse binaari lisan ainult faili, kus on funktsioon main.
add_executable(mylib-unit-tests test_main.cpp)Ja failid, kus on kirja pandud testid, lisan hiljem. Kuid nii teha ei ole vajalik.
target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp)Seome sĂ”ltuvused. Pange tĂ€hele, et meie binaariga seostasime ainult vajalikud CMake eesmĂ€rgid ega kutsunud ĂŒles kĂ€sku target_include_directories. Testimisraamistiku pealkirjad ja meie Mylib::mylib, samuti kogumise parameetrid (meie juhul on see C++ keele standard) lĂ€ksid koos nende eesmĂ€rkidega lĂ€bi.
target_link_libraries(mylib-unit-tests
PRIVATE
Mylib::mylib
doctest::doctest
)LÔpuks loome vale eesmÀrgi, mille "kogumine" on vÔrdne testide kÀitamisega, ja lisame selle doelame standardkogumisse (seda juhib atribuut , vÔi). See tÀhendab, et vaikimisi kogumine kÀivitab testide kÀitamist, seega me kunagi ei unusta neid kÀivitada.
add_custom_target(check ALL COMMAND mylib-unit-tests)
SeejĂ€rel aktiveerime koodikatvuse mÔÔtmise, kui vastav valik on mÀÀratud. SĂŒgavale detailidesse ei lĂ€he, kuna need kuuluvad rohkem katvuse mÔÔtamisseadmesse kui CMake'ile. Oluline on mĂ€rkida ainult, et tulemuste pĂ”hjal luuakse eesmĂ€rk , millega on mugav kĂ€ivitada katvuse mÔÔtmine.
find_program(GCOVR_EXECUTABLE gcovr)
if(MYLIB_COVERAGE AND GCOVR_EXECUTABLE)
message(STATUS "Koodikatse katvuse 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 "Koodikatse katvuse mÔÔtmiseks on vajalik programm gcovr")
endif()
.
find_package(Doxygen)Edasi kontrollime, kas kasutaja on mÀÀranud keelemuutuja. Kui jah, siis ei puutu sellesse, kui ei, siis vĂ”tame vene. SeejĂ€rel konfigureerime Doxygen sĂŒsteemi failid. KĂ”ik vajalikud muutujad, sealhulgas keel, saadakse konfiguratsiooni kĂ€igus (vt. ).
Peale seda loome sihiks , mis kĂ€ivitab dokumentatsiooni genereerimise. Kuna dokumentatsiooni genereerimine ei ole arenduse kĂ€igus kĂ”ige tĂ€htsam vajadus, siis ei ole siht vaikimisi sisse lĂŒlitatud, see tuleb kĂ€ivitada selgelt.
if (Doxygen_FOUND)
if (NOT MYLIB_DOXYGEN_LANGUAGE)
set(MYLIB_DOXYGEN_LANGUAGE Vene)
endif()
message(STATUS "Doxygeni 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 Python'i ja loome sihiks , mis genereerib pÀringu, mis vastab teenuse API-le , ja saadab selle. Vastuseks tulevad valmis liivakasti link.
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 "Veebiliivakasti loomiseks on vajalik Python 3 interpreteur")
endif()
NĂŒĂŒd vaatame, kuidas seda kĂ”ike kasutada.
Selle projekti koostamine, nagu ka iga teise CMake sĂŒsteemi projekti puhul, koosneb kahest etapist:
cmake -S tee\/kallid -B tee\/kogumiskohta [valikud ...]Kui ĂŒlemine kĂ€sk ei toiminud vanema CMake versiooni tĂ”ttu, proovige jĂ€tta vĂ€lja
-S:cmake tee\/kallid -B tee\/kogumiskohta [valikud ...]
.
cmake --build tee\/kogumiskohta [--target siht].
cmake -S ... -B ... -DMYLIB_COVERAGE=ON [teised valikud ...]LĂŒlitab sihi sisse , mille on vĂ”imalik kĂ€ivitada koodikatvuse mÔÔtmine testide kaudu.
cmake -S ... -B ... -DMYLIB_TESTING=OFF [muud seaded ...]Pakub vĂ”imalusi moodulite testimise ja eesmĂ€rgi vĂ€ljalĂŒlitamiseks. . Selle tulemusena lĂŒlitatakse koodikatvuse mÔÔtmine testide kaudu vĂ€lja (vt. ).
Samuti lĂŒlitatakse testimine automaatselt vĂ€lja, kui projekt lisatakse teise projekti alaprojektina kĂ€su abil .
cmake -S ... -B ... -DMYLIB_DOXYGEN_LANGUAGE=English [muud seaded ...]Vahetab dokumentatsiooni keele, mille genereerib eesmÀrk mugandatuks. Saadaval olevate keelte loetelu leiate .
Vaikimisi on keel vene.
cmake --build path/to/build/directory
cmake --build path/to/build/directory --target allKui eesmĂ€rki ei ole mÀÀratud (mis on samavÀÀrne eesmĂ€rgiga all), kogub kĂ”ik, mis on vĂ”imalik, ning kutsub ĂŒles eesmĂ€rki. .
cmake --build path/to/build/directory --target mylib-unit-testsKompileerib moodulitestide. Vaikimisi on see sisse lĂŒlitatud.
cmake --build tee/ehituskausta --target checkKĂ€ivitab koostatud (kogub, kui veel mitte) moodulitestid. Vaikimisi on see sisse lĂŒlitatud.
Vaata ka .
cmake --build tee/ehituskausta --target coverageAnalĂŒĂŒsib kĂ€ivitatud (kĂ€ivitab, kui veel mitte) moodulitestid koodikatvuse osas testimise ajal programmi .
Katvuse vÀljund nÀeb vÀlja selline:
------------------------------------------------------------------------------
GCC Koodikatvuse Aruanne
Kaust: /path/to/cmakecpptemplate/include/
------------------------------------------------------------------------------
Fail Read TĂ€itmine Katvus Puuduvad
------------------------------------------------------------------------------
mylib/myfeature.hpp 2 2 100%
------------------------------------------------------------------------------
TOTAL 2 2 100%
------------------------------------------------------------------------------EesmĂ€rk on saadaval ainult, kui valik on sisse lĂŒlitatud. .
Vaata ka .
cmake --build tee/ehituskausta --target docKĂ€ivitab dokumentatsiooni genereerimise koodi jaoks Doxygen sĂŒsteemi abil. .
cmake --build tee/ehituskausta --target wandboxTeenuse vastus nÀeb vÀlja selline:
{
"permlink" : "QElvxuMzHgL9fqci",
"status" : "0",
"url" : "https://wandbox.org/permlink/QElvxuMzHgL9fqci"
}Selleks kasutatakse teenust . Ma ei tea, kui paindlikud nende serverid on, kuid ma arvan, et seda vÔimalust ei tasu kuritarvitada.
Projekti ĂŒlesehitus tĂ”rkeotsingu reĆŸiimis koodikatvuse mÔÔtmisega.
cmake -S tee/komplekt/dokumendid -B tee/ehituskausta -DCMAKE_BUILD_TYPE=Debug -DMYLIB_COVERAGE=ON
cmake --build tee/ehituskausta --target coverage --parallel 16Projekti paearendust ja testimist
cmake -S tee/koodifailid -B tee/ehituskaust -DMYLIB_TESTING=OFF -DCMAKE_INSTALL_PREFIX=tee/paigalduskaust
cmake --build tee/ehituskaust --target installEhitus vabastamisreĆŸiimis mÀÀratud kompilaatoriga
cmake -S tee/koodifailid -B tee/ehituskaust -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-8 -DCMAKE_PREFIX_PATH=tee/kaust/kuhu/paigaldatud/sÔltuvused
cmake --build tee/ehituskaust --parallel 4Dokumentatsiooni genereerimine inglise keeles
cmake -S tee/koodifailid -B tee/ehituskaust -DCMAKE_BUILD_TYPE=Release -DMYLIB_DOXYGEN_LANGUAGE=English
cmake --build tee/ehituskaust --target doc
3.13
Tegelikult vajatakse CMake versiooni 3.13 ainult teatud konsolikomandide kĂ€ivitamiseks, mis on kirjeldatud antud juhendis. CMake-skriptide sĂŒntaksiks piisab versioonist 3.8, kui genereerimist kutsuda vĂ€lja muude viiside kaudu.
Testimise raamatukogu
Testimist saab keelduda (vt. ).
Dokumentatsioonikeele vahetamiseks on olemas valik .
TÔlkija YP
Automaatseks genereerimiseks .
CMake ja paar head tööriista vĂ”ivad hĂ”lpsasti tagada staatilise analĂŒĂŒsi minimaalse vaevaga.
Cppcheck
CMake'is on sisseehitatud tugi staatilise analĂŒĂŒsi tööriistale .
Selleks tuleb kasutada valikut :
cmake -S tee/koodifailid -B tee/ehituskaust -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;-Itee/koodifailid/include"PĂ€rast seda kĂ€ivitatakse staatiline analĂŒĂŒs automaatselt iga kord, kui lĂ€htefaile kompileeritakse ja uuesti kompileeritakse. Ei ole vaja midagi lisada.
Clang
Imekauni tööriista abil saab samuti staatilist analĂŒĂŒsi kiiresti kĂ€ivitada:
scan-build cmake -S tee/koodifailid -B tee/ehituskaust -DCMAKE_BUILD_TYPE=Debug
scan-build cmake --build tee/ehituskaustSiin on vastupidiselt Cppcheck'ile vajalik igakordselt kÀivitada ehitus scan-build.
CMake on vĂ€ga vĂ”imas ja paindlik sĂŒsteem, mis vĂ”imaldab realiseerida igasugust funktsionaalsust. Ja kuigi sĂŒntaks jĂ€tab vahel soovida, ei ole see nii hirmus, kui teda maalitakse. Kasutage CMake ehitussĂŒsteemi ĂŒhiskonna hĂŒvanguks ja enda terviseks.
â
Allikas: habr.com
