Dum evoluo, mi ŝatas ŝanĝi kompililojn, konstrui reĝimojn, dependecajn versiojn, fari statikan analizon, mezuri rendimenton, kolekti kovradon, generi dokumentadon ktp. Kaj mi vere amas CMake ĉar ĝi permesas al mi fari kion ajn mi volas.
Multaj riproĉas CMake, kaj ofte merite, sed se vi rigardas, ĝi ne estas tiel malbona, sed lastatempe tute ne malbone, kaj la direkto de evoluo estas sufiĉe pozitiva.
En ĉi tiu noto, mi volas diri al vi, kiom facile estas organizi C++-kapobibliotekon en sistemo CMake por akiri la sekvan funkcion:
Asembleo;
Aŭtorunaj provoj;
Mezurado de koda kovrado;
instalado;
Aŭtodokumentado;
Interreta sandbox-generacio;
Statika analizo.
Kiu jam komprenas la avantaĝojn kaj si-make povas nur elŝutu projekt-ŝablonon kaj komencu uzi ĝin.
Ĉi tio ĉefe koncentriĝos pri kiel organizi CMake-skriptojn, do ili estos detale analizitaj. La ceteraj dosieroj povas esti rigardataj rekte de iu ajn. sur la ŝablona projektpaĝo.
Antaŭ ĉio, vi devas peti la deziratan version de la sistemo CMake. CMake evoluas, komando subskriboj ŝanĝiĝas, konduto sub malsamaj kondiĉoj. Por ke CMake tuj komprenu, kion ni volas de ĝi, ni devas tuj ripari niajn postulojn por ĝi.
cmake_minimum_required(VERSION 3.13)
Tiam ni indikas nian projekton, ĝian nomon, version, uzatajn lingvojn ktp. команду project).
En ĉi tiu kazo, specifu la lingvon CXX (kio signifas C++) por ke CMake ne ĝenu serĉi C-kompililon (defaŭlte, du lingvoj estas inkluzivitaj en CMake: C kaj C++).
project(Mylib VERSION 1.0 LANGUAGES CXX)
Ĉi tie vi povas tuj kontroli ĉu nia projekto estas inkluzivita en alia projekto kiel subprojekto. Ĉi tio multe helpos estonte.
La unua opcio estas MYLIB_TESTING - malŝalti unutestojn. Ĉi tio povas esti necesa, se ni certas, ke ĉio estas en ordo kun la testoj, kaj ni volas, ekzemple, nur instali aŭ paki nian projekton. Aŭ nia projekto estas inkluzivita kiel subprojekto - en ĉi tiu kazo, la uzanto de nia projekto ne interesiĝas pri rulado de niaj testoj. Vi ne testas la dependecojn, kiujn vi uzas, ĉu?
Kompreneble, ni estas bonegaj pozitivaj programistoj, do ni volas la maksimuman nivelon de kompiltempaj diagnozoj de la kompililo. Ne unu muso trairos.
Nia biblioteko konsistas nur el kapdosieroj, kio signifas, ke ni havas neniun eliron en la formo de statikaj aŭ dinamikaj bibliotekoj. Aliflanke, por uzi nian bibliotekon de ekstere, vi devas instali ĝin, vi devas povi trovi ĝin en la sistemo kaj konekti ĝin al via projekto, kaj samtempe ankaŭ ĉi tiujn titolojn. kiel, eble, iuj pliaj ecoj.
Tiucele ni kreas interfacan bibliotekon.
add_library(mylib INTERFACE)
Ni ligas la kapliniojn al nia interfaca biblioteko.
Moderna, laŭmoda, juneca uzo de CMake signifas, ke kaplinioj, propraĵoj ktp. transdonita tra ununura celo. Do sufiĉas diri target_link_libraries(target PRIVATE dependency), kaj ĉiuj kaplinioj kiuj estas asociitaj kun la celo dependency, estos disponebla por fontoj apartenantaj al la celo target. Kaj vi ne bezonas [target_]include_directories. Ĉi tio estos montrita sube dum analizado CMake-skripto por unutestoj.
Ĉi tiu komando asocias la titolojn, kiujn ni bezonas kun nia interfaca biblioteko, kaj se nia biblioteko estas konektita al iu celo ene de la sama CMake-hierarkio, tiam la kaplinioj de la dosierujo estos asociitaj kun ĝi. ${CMAKE_CURRENT_SOURCE_DIR}/include, kaj se nia biblioteko estas instalita en la sistemo kaj konektita al alia projekto uzante la komandon find_package, tiam la kaplinioj de la dosierujo estos asociitaj kun ĝi include rilate al la instala dosierujo.
Agordu la lingvan normon. Kompreneble, la lasta. Samtempe ni ne nur inkluzivas la normon, sed ankaŭ distribuas ĝin al tiuj, kiuj uzos nian bibliotekon. Ĉi tio estas atingita havante la aran posedaĵon havas kategorion INTERFACE (vidu komando target_compile_features).
Ni ricevas kaŝnomon por nia biblioteko. Kaj por beleco, ĝi estos en speciala "nomspaco". Ĉi tio estos utila kiam malsamaj moduloj aperos en nia biblioteko, kaj ni iras por konekti ilin sendepende unu de la alia. Kiel en Busta, ekzemple.
Instalante niajn kapliniojn en la sistemon. Ĉio estas simpla ĉi tie. Ni diras, ke la dosierujo kun ĉiuj kaplinioj devas fali en la dosierujon include pri la loko de instalado.
La sekva sorĉo estas komprenenda tiel. Kiam en flanka projekto ni nomas la komandon find_package(Mylib 1.2.3 REQUIRED), kaj samtempe la vera versio de la instalita biblioteko estos nekongrua kun la versio 1.2.3, CMake aŭtomate generos eraron. Tio estas, vi ne bezonos konservi trakon de versioj permane.
Se testoj estas eksplicite malŝaltitaj kun responda opcio aŭ nia projekto estas subprojekto, tio estas, ĝi estas konektita al alia projekto CMake uzante la komandon add_subdirectory, ni ne iras pli malsupre en la hierarkio, kaj la skripto, kiu priskribas la komandojn por generi kaj ruli testojn, simple ne komenciĝas.
if(NOT MYLIB_TESTING)
message(STATUS "Тестирование проекта Mylib выключено")
elseif(IS_SUBPROJECT)
message(STATUS "Mylib не тестируется в режиме подмодуля")
else()
add_subdirectory(test)
endif()
Ni konektas dependecojn. Bonvolu noti, ke ni alfiksis nur la CMake-celojn, kiujn ni bezonis al nia binaro, kaj ne vokis la komandon target_include_directories. Titoloj el la testa kadro kaj el nia Mylib::mylib, same kiel konstruopcioj (en nia kazo, la C++-lingva normo) rampis kune kun ĉi tiuj celoj.
Fine, ni kreas imitan celon, kies "konstruo" estas ekvivalenta al rulado de testoj, kaj aldonas ĉi tiun celon al la defaŭlta konstruo (ĉi tio estas la respondeco de la atributo ALL). Ĉi tio signifas, ke la defaŭlta konstruo ekfunkciigos la testojn, kio signifas, ke ni neniam forgesos ruli ilin.
add_custom_target(check ALL COMMAND mylib-unit-tests)
Poste, ŝaltu mezuradon de koda kovrado, se la responda opcio estas agordita. Mi ne eniros la detalojn, ĉar ili estas pli rilataj al la priraporta mezura ilo ol al CMake. Gravas nur rimarki, ke la rezultoj kreos celon coverage, per kiu estas oportune komenci mezuri kovradon.
find_program(GCOVR_EXECUTABLE gcovr)
if(MYLIB_COVERAGE AND GCOVR_EXECUTABLE)
message(STATUS "Измерение покрытия кода тестами включено")
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 "Для замеров покрытия кода тестами требуется программа gcovr")
endif()
Poste, ni kontrolas ĉu la variablo kun la lingvo estas agordita de la uzanto. Se jes, tiam ni ne tuŝas ĝin, se ne, tiam ni prenas la rusan. Poste ni agordas la Doxygen-sistemajn dosierojn. Ĉiuj necesaj variabloj, inkluzive de la lingvo, atingas tie dum la agorda procezo (vidu. команду configure_file).
Tiam ni kreas celon doc, kiu komencos generi dokumentadon. Ĉar generi dokumentadon ne estas la plej granda bezono en la evoluprocezo, la celo ne estos inkluzivita defaŭlte, ĝi devos esti eksplicite funkciigata.
if (Doxygen_FOUND)
if (NOT MYLIB_DOXYGEN_LANGUAGE)
set(MYLIB_DOXYGEN_LANGUAGE Russian)
endif()
message(STATUS "Doxygen documentation will be generated in ${MYLIB_DOXYGEN_LANGUAGE}")
configure_file(Doxyfile.in Doxyfile)
add_custom_target(doc COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
endif ()
Ĉi tie ni trovas la trian Python kaj kreas celon wandbox, kiu generas peton respondan al la servo API Vergkesto, kaj sendas ĝin. En respondo, ligo al la finita sablokesto venas.
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 "Для создания онлайн-песочницы требуется интерпретатор ЯП python 3-й версии")
endif()
Provizas la eblon malŝalti unutestan konstruon kaj celon check. Kiel rezulto, la mezurado de koda kovrado per testoj estas malŝaltita (vidu MYLIB_COVERAGE).
Ankaŭ, testado estas aŭtomate malŝaltita se la projekto estas konektita al alia projekto kiel subprojekto uzante la komandon add_subdirectory.
Fakte, CMake-versio 3.13 estas bezonata nur por ruli iujn el la konzolaj komandoj priskribitaj en ĉi tiu helpo. El la vidpunkto de la sintakso de CMake-skriptoj, la versio 3.8 sufiĉas se la generacio estas vokita alimaniere.
CMake estas tre potenca kaj fleksebla sistemo, kiu ebligas al vi efektivigi funkciecon por ĉiu gusto kaj koloro. Kaj, kvankam la sintakso foje lasas multon por deziri, la diablo ankoraŭ ne estas tiel terura kiel li estas pentrita. Uzu la CMake konstrusistemon por la avantaĝo de socio kaj sano.