Wärend der Entwécklung hunn ech gär Compiler änneren, Modi bauen, Ofhängegkeetsversioune, statesch Analyse ausféieren, Leeschtung moossen, Ofdeckung sammelen, Dokumentatioun generéieren, etc. An ech hunn CMake wierklech gär well et mir erlaabt alles ze maachen wat ech wëll.
Vill Leit kritiséieren CMake, an dacks verdéngt, awer wann Dir et kuckt, ass net alles sou schlecht, a viru kuerzem guer net schlecht, an d'Richtung vun der Entwécklung ass ganz positiv.
An dëser Notiz wëll ech Iech soen wéi Dir einfach eng Headerbibliothéik an C ++ am CMake System organiséiert fir déi folgend Funktionalitéit ze kréien:
Assemblée;
Autorun Tester;
Code Ofdeckung Miessung;
Installatioun;
Auto Dokumentatioun;
Online Sandkëscht Generatioun;
Statesch Analyse.
Jiddereen deen schonn d'Virdeeler an C-Make versteet kann einfach download Projet Schabloun an ufänken et ze benotzen.
Mir schwätzen haaptsächlech iwwer wéi CMake Scripten organiséiert ginn, sou datt se am Detail diskutéiert ginn. Jiddereen kann de Rescht vun de Fichieren direkt gesinn op der Schablounprojet Säit.
Als éischt musst Dir déi erfuerderlech Versioun vum CMake System ufroen. CMake entwéckelt sech, Kommando Ënnerschrëften a Verhalen a verschiddene Konditiounen änneren. Fir datt CMake direkt versteet wat mir dovunner wëllen, musse mir direkt eis Ufuerderungen dofir notéieren.
cmake_minimum_required(VERSION 3.13)
Da bezeechnen mir eise Projet, säin Numm, Versioun, benotzte Sproochen, asw. (kuckt. команду project).
An dësem Fall weisen mir d'Sprooch un CXX (an dat heescht C ++) sou datt CMake net belaascht a sicht no engem C Sprooche-Compiler (par défaut enthält CMake zwou Sproochen: C an C ++).
project(Mylib VERSION 1.0 LANGUAGES CXX)
Hei kënnt Dir direkt kucken ob eise Projet an engem anere Projet als Ënnerprojet mat abegraff ass. Dëst wäert an Zukunft vill hëllefen.
Déi éischt Optioun ass MYLIB_TESTING - Eenheetstester auszeschalten. Dëst kann néideg sinn wa mir sécher sinn datt alles an der Rei ass mat den Tester, awer mir wëllen nëmmen zum Beispill eise Projet installéieren oder packen. Oder eise Projet ass als Ënnerprojet abegraff - an dësem Fall ass de Benotzer vun eisem Projet net interesséiert fir eis Tester auszeféieren. Dir testt d'Ofhängegkeeten net déi Dir benotzt, oder?
Zousätzlech wäerte mir eng separat Optioun maachen MYLIB_COVERAGE fir d'Codedeckung duerch Tester ze moossen, awer et erfuerdert zousätzlech Tools, also muss et explizit aktivéiert ginn.
Natierlech si mir cool Plus Programméierer, also wëlle mir de maximalen Niveau vun der Compile-Zäit Diagnostik vum Compiler. Net eng eenzeg Maus rutscht duerch.
Eis Bibliothéik besteet nëmmen aus Headerdateien, dat heescht datt mir keen Auspuff a Form vu statesche oder dynamesche Bibliothéiken hunn. Op der anerer Säit, fir eis Bibliothéik extern ze benotzen, muss se installéiert ginn, et muss am System festgestallt ginn a mat Ärem Projet verbonne sinn, a gläichzäiteg déiselwecht Header, wéi och eventuell e puer zousätzlech, sinn un et Eegeschafte verbonnen.
Fir dësen Zweck erstellen mir eng Interfacebibliothéik.
add_library(mylib INTERFACE)
Mir binden Header un eis Interfacebibliothéik.
Modern, modesch, Jugend Notzung vu CMake implizéiert datt Header, Eegeschaften, asw. duerch een eenzegt Zil iwwerdroen. Also ass et genuch ze soen target_link_libraries(target PRIVATE dependency), an all Header déi mam Zil verbonne sinn dependency, wäert verfügbar sinn fir Quellen déi zum Zil gehéieren target. An Dir braucht keng [target_]include_directories. Dëst wäert ënnen an der Analyse bewisen ginn CMake Skript fir Eenheetstester.
Dëse Kommando assoziéiert d'Header déi mir brauchen mat eiser Interfacebibliothéik, a wann eis Bibliothéik mat engem Zil an der selwechter CMake Hierarchie verbonnen ass, da ginn d'Header aus dem Verzeechnes mat deem verbonnen. ${CMAKE_CURRENT_SOURCE_DIR}/include, a wann eis Bibliothéik um System installéiert ass a mat engem anere Projet mat dem Kommando verbonnen ass find_package, da ginn Header aus dem Verzeichnis domat verbonnen include relativ zum Installatiounsverzeichnis.
Loosst eis e Sproochestandard setzen. Natierlech, déi lescht. Zur selwechter Zäit enthalen mir net nëmmen de Standard, mee verlängeren se och op déi, déi eis Bibliothéik benotzen. Dëst gëtt erreecht wéinst der Tatsaach datt d'Set Immobilie eng Kategorie huet INTERFACE (cm. target_compile_features Kommando).
Loosst eis en Alias fir eis Bibliothéik erstellen. Ausserdeem, fir Schéinheet, wäert et an engem speziellen "Namespace" sinn. Dëst wäert nëtzlech sinn wann verschidde Moduler an eiser Bibliothéik erschéngen, a mir gi se onofhängeg vuneneen verbannen. Wéi zum Beispill zu Busta.
Installéiere vun eise Header an de System. Alles ass einfach hei. Mir soen datt den Dossier mat all den Header an den Dossier sollt goen include relativ zu der Installatioun Plaz.
Als nächst informéiere mir de Build-System datt mir de Kommando an Drëtt-Partei-Projeten ruffen wëllen find_package(Mylib) a kritt e Goal Mylib::mylib.
Déi nächst Zauber soll esou verstane ginn. Wann an engem Drëtte-Partei Projet ruffe mir de Kommando find_package(Mylib 1.2.3 REQUIRED), an déi richteg Versioun vun der installéierter Bibliothéik wäert mat der Versioun inkompatibel sinn 1.2.3CMake generéiert automatesch e Feeler. Dat ass, Dir braucht keng Versiounen manuell ze verfollegen.
Wann Tester behënnert explizit benotzt entspriechend Optioun oder eise Projet ass en Ënnerprojet, dat heescht, et ass mat engem anere CMake Projet verbonne mat dem Kommando add_subdirectory, mir réckelen net weider laanscht d'Hierarchie, an de Skript, deen d'Befehle beschreift fir Tester ze generéieren an ze lafen, leeft einfach net.
if(NOT MYLIB_TESTING)
message(STATUS "Тестирование проекта Mylib выключено")
elseif(IS_SUBPROJECT)
message(STATUS "Mylib не тестируется в режиме подмодуля")
else()
add_subdirectory(test)
endif()
Als éischt fanne mir e Package mat dem erfuerderlechen Testkader (ersetzen duerch Äre Liiblings).
find_package(doctest 2.3.3 REQUIRED)
Loosst eis eis ausführbar Datei mat Tester erstellen. Normalerweis fügen ech direkt un den ausführbare Binär nëmmen d'Datei déi d'Funktioun enthält main.
add_executable(mylib-unit-tests test_main.cpp)
An ech addéieren Dateien an deenen d'Tester selwer spéider beschriwwe ginn. Awer Dir musst dat net maachen.
Mir verbannen Ofhängegkeeten. Notéiert w.e.g. datt mir nëmmen déi CMake Ziler verbonnen hunn, déi mir gebraucht hunn, un eis Binär an hunn de Kommando net genannt target_include_directories. Rubriken aus dem Test Kader an aus eisem Mylib::mylib, souwéi Bauparameter (an eisem Fall ass dëst de C++ Sproochestandard) mat dësen Ziler duerchkomm.
Schlussendlech kreéiere mir en Dummy-Zil, de "Build" vun deem entsprécht Tester lafen, a füügt dëst Zil un de Standardbau (d'Attribut ass verantwortlech fir dëst ALL). Dëst bedeit datt de Standardbau d'Tester ausléist fir ze lafen, dat heescht datt mir ni vergiessen se ze lafen.
add_custom_target(check ALL COMMAND mylib-unit-tests)
Als nächst aktivéiere mir Code Ofdeckungsmessung wann déi entspriechend Optioun uginn ass. Ech ginn net an d'Detailer, well se méi mat engem Tool fir d'Ofdeckung ze moossen bezéien wéi op CMake. Et ass nëmme wichteg ze bemierken datt op Basis vun de Resultater en Zil erstallt gëtt coverage, mat deem et bequem ass d'Ofdeckung ze moossen.
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()
Als nächst kucken mir ob de Benotzer d'Sproochvariabel gesat huet. Wann jo, da beréieren mir et net, wann net, da huelen mir Russesch. Da konfiguréiere mir d'Doxygen Systemdateien. All déi néideg Variabelen, och d'Sprooch, ginn do wärend dem Konfiguratiounsprozess (kuckt. команду configure_file).
Da kreéiere mir e Goal doc, déi fänkt un d'Dokumentatioun ze generéieren. Zënter datt d'Dokumentatioun net de gréisste Bedierfnes am Entwécklungsprozess ass, gëtt d'Zil net als Standard aktivéiert; et muss explizit lancéiert ginn.
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 ()
Hei fanne mir den drëtten Python a kreéieren en Zil wandbox, déi eng Demande generéiert entsprécht dem Service API Wandbox, a schéckt hien ewech. D'Äntwert kënnt mat engem Link op déi fäerdeg Sandkëscht.
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()
Bitt d'Fähigkeit fir Eenheetstestbau an Zil auszeschalten check. Als Resultat gëtt d'Messung vun der Codeofdeckung duerch Tester ausgeschalt (kuckt. MYLIB_COVERAGE).
Testen ass och automatesch deaktivéiert wann de Projet mat engem anere Projet als Ënnerprojet mam Kommando verbonnen ass add_subdirectory.
Tatsächlech ass CMake Versioun 3.13 nëmmen erfuerderlech fir e puer vun de Konsolbefehle ze lafen, déi an dëser Hëllef beschriwwe ginn. Aus der Siicht vun der Syntax vu CMake Scripten ass d'Versioun 3.8 genuch wann d'Generatioun op aner Manéier genannt gëtt.
Duerno gëtt d'statesch Analyse automatesch gestart all Kéier wann d'Quell kompiléiert an nei kompiléiert gëtt. Et ass net néideg eppes zousätzlech ze maachen.
Kleng
Mat der Hëllef vun engem wonnerbar Outil scan-build Dir kënnt och statesch Analyse a kuerzer Zäit lafen:
CMake ass e ganz mächtegen a flexibele System deen Iech erlaabt Funktionalitéit fir all Goût a Faarf ëmzesetzen. An och wann d'Syntax heiansdo vill ze Wënsch léisst, ass den Däiwel nach ëmmer net esou schrecklech wéi hien gemoolt ass. Benotzt de CMake Build System fir de Virdeel vun der Gesellschaft a Gesondheet.