Өнүктүрүү учурунда мен компиляторлорду өзгөртүүнү, режимдерди курууну, көз карандылык версияларын, статикалык анализди жүргүзүүнү, өндүрүмдүүлүктү өлчөөнү, камтууларды чогултууну, документтерди түзүүнү ж. Жана мен чындап эле CMakeди жакшы көрөм, анткени ал мага каалаган нерсени жасоого мүмкүндүк берет.
Көптөгөн адамдар CMakeди сындашат жана көп учурда татыктуу, бирок аны карасаңыз, баары жаман эмес жана жакында такыр жаман эмес, жана өнүгүү багыты кыйла оң.
Бул эскертүүдө, мен сизге CMake системасында C++ тилинде баш китепкананы кантип уюштурууну айткым келет, бул төмөнкү функцияларды алуу үчүн:
Ассамблея;
Autorun тесттери;
Код камтуу өлчөө;
Орнотуу;
Автодокументтер;
Онлайн кумдуу чөйрөнү түзүү;
Статикалык анализ.
Артыкчылыктарды түшүнгөн жана C-жасаган адам жөн гана жасай алат долбоордун үлгүсүн жүктөп алуу жана аны колдоно баштаңыз.
Биз негизинен CMake скрипттерин кантип уюштуруу керектиги жөнүндө сүйлөшөбүз, ошондуктан алар кеңири талкууланат. Калган файлдарды каалаган адам түздөн-түз көрө алат шаблон долбоору бетинде.
Биринчиден, сиз CMake системасынын талап кылынган версиясын талап кылышыңыз керек. CMake өнүгүп жатат, буйрук кол тамгалары жана ар кандай шарттарда жүрүм-туруму өзгөрүүдө. CMake биз андан эмнени каалап жатканыбызды дароо түшүнүшү үчүн, биз ага болгон талаптарыбызды дароо жазышыбыз керек.
cmake_minimum_required(VERSION 3.13)
Андан кийин биз долбоорбузду, анын атын, версиясын, колдонулган тилдерди ж.б. белгилейбиз (кара. команду project).
Бул учурда биз тилди көрсөтөбүз CXX (жана бул C++ дегенди билдирет), андыктан CMake С тилинин компиляторун издебейт жана издебейт (демейки боюнча, CMake эки тилди камтыйт: C жана C++).
project(Mylib VERSION 1.0 LANGUAGES CXX)
Бул жерден биздин долбоордун башка долбоорго кичи проект катары киргендигин дароо текшере аласыз. Бул келечекте көп жардам берет.
Биринчи вариант MYLIB_TESTING — бирдик сыноолорун өчүрүү. Эгер биз сыноолордо бардыгы туура экенине ишенсек, бул зарыл болушу мүмкүн, бирок биз, мисалы, биздин долбоорду орнотууну же пакеттөөнү гана каалайбыз. Же биздин долбоор чакан долбоор катары киргизилген - бул учурда биздин долбоордун колдонуучусу биздин тесттерди жүргүзүүгө кызыкдар эмес. Сиз колдонгон көз карандылыктарды сынабайсыз, туурабы?
Андан сырткары өзүнчө вариант жасайбыз MYLIB_COVERAGE тесттер менен коддун камтылышын өлчөө үчүн, бирок ал кошумча куралдарды талап кылат, ошондуктан аны ачык иштетүү керек.
Албетте, биз сонун плюс программисттербиз, ошондуктан компилятордон компиляция убактысынын диагностикасынын максималдуу деңгээлин каалайбыз. Бир да чычкан өтүп кетпейт.
Биздин китепкана баш файлдардан гана турат, демек, бизде статикалык же динамикалык китепканалар түрүндө эч кандай түтүк жок. Башка жагынан алып караганда, китепканабызды сырттан колдонуу үчүн, аны орнотуу керек, ал системада аныкталып, сиздин долбооруңузга туташып, ошол эле учурда ушул эле аталыштар, ошондой эле кээ бир кошумчалары болушу керек. ага касиеттери тиркелет.
Бул үчүн биз интерфейс китепканасын түзөбүз.
add_library(mylib INTERFACE)
Биз аталыштарды интерфейс китепканабызга байлайбыз.
Заманбап, модалуу, жаштардын CMake колдонуусу деген аталыштарды, касиеттерди ж.б. бир максат аркылуу берилет. Ошондуктан айтсам жетиштүү target_link_libraries(target PRIVATE dependency), жана максат менен байланышкан бардык аталыштар dependency, максатка тиешелүү булактар үчүн жеткиликтүү болот target. А сизге эч кандай кереги жок [target_]include_directories. Бул талдоо төмөндө көрсөтүлөт CMake скрипти бирдик сыноолору үчүн.
Бул буйрук бизге керектүү аталыштарды биздин интерфейс китепканабыз менен байланыштырат жана эгерде биздин китепкана бир эле CMake иерархиясынын ичиндеги каалаган максатка туташкан болсо, анда каталогдун аталыштары аны менен байланыштырылат. ${CMAKE_CURRENT_SOURCE_DIR}/include, жана биздин китепкана системага орнотулган болсо жана буйрукту колдонуу менен башка долбоорго туташкан болсо find_package, анда каталогдогу баштар аны менен байланыштырылат include орнотуу каталогуна салыштырмалуу.
Келгиле, тил стандартын белгилейли. Албетте, эң акыркысы. Ошол эле учурда стандартты киргизип эле койбостон, биздин китепкананы колдоно тургандарга да жайылтабыз. Бул белгиленген касиет категорияга ээ болгондугунун эсебинен жетишилет INTERFACE (Cm. target_compile_features буйругу).
Келиңиздер, китепканабызга лакап ат түзөлү. Мындан тышкары, сулуулук үчүн, ал атайын "ат мейкиндигинде" болот. Бул биздин китепканада ар кандай модулдар пайда болгондо пайдалуу болот жана биз аларды бири-биринен көз карандысыз туташтырабыз. Мисалы, Бустадагыдай.
Биздин баштарыбызды системага орнотуу. Бул жерде баары жөнөкөй. Биз бардык баш аты бар папка каталогго кириши керек деп айтабыз include орнотуу ордуна салыштырмалуу.
Андан кийин, биз үчүнчү тараптын долбоорлорунда команданы чакыра алгыбыз келген куруу тутумуна кабарлайбыз find_package(Mylib) жана максатка жет Mylib::mylib.
Кийинки сыйкырды ушинтип түшүнүү керек. Үчүнчү тараптын долбоорунда биз команданы чакырабыз find_package(Mylib 1.2.3 REQUIRED), жана орнотулган китепкананын чыныгы версиясы версия менен шайкеш келбейт 1.2.3CMake автоматтык түрдө ката жаратат. Башкача айтканда, версияларды кол менен көзөмөлдөөнүн кереги жок.
тесттер ачык-айкын колдонуу менен өчүрүлгөн болсо тиешелүү вариант же биздин долбоор подпроект болуп саналат, башкача айтканда, ал команда аркылуу башка CMake долбооруна туташтырылган add_subdirectory, биз иерархия боюнча мындан ары жылбайбыз жана тесттерди түзүү жана иштетүү үчүн буйруктарды сүрөттөгөн скрипт жөн эле иштебейт.
if(NOT MYLIB_TESTING)
message(STATUS "Тестирование проекта Mylib выключено")
elseif(IS_SUBPROJECT)
message(STATUS "Mylib не тестируется в режиме подмодуля")
else()
add_subdirectory(test)
endif()
Биз көз карандылыкты бириктиребиз. Биз өзүбүзгө керектүү CMake максаттарын гана бинардык менен байланыштырганыбызды жана буйрукту чакырбаганыбызды эске алыңыз target_include_directories. Сыноо алкагындагы жана биздин рубрикалар Mylib::mylib, ошондой эле куруу параметрлери (биздин учурда, бул C++ тил стандарты) ушул максаттар менен бирге келди.
Акыр-аягы, биз жасалма максатты түзөбүз, анын "түзүлүшү" иштеп жаткан тесттерге барабар жана бул максатты демейки түзүлүшкө кошобуз (атрибут бул үчүн жооптуу ALL). Бул демейки түзүлүш сыноолорду ишке киргизет, демек, биз аларды иштетүүнү эч качан унутпайбыз.
add_custom_target(check ALL COMMAND mylib-unit-tests)
Андан кийин, эгерде тиешелүү вариант көрсөтүлсө, биз коддун камтылышын өлчөөнү иштетебиз. Мен майда-чүйдөсүнө чейин кирбейм, анткени алар CMakeге караганда камтууну өлчөөчү куралга көбүрөөк тиешелүү. Бул жыйынтыктардын негизинде максат түзүлө турганын белгилей кетүү маанилүү coverage, анын жардамы менен жабууну өлчөөнү баштоо ыңгайлуу.
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()
Андан кийин, колдонуучу тил өзгөрмөсүн орноткондугун текшеребиз. Ооба болсо, анда тийбейбиз, жок болсо, орусча алабыз. Андан кийин биз Doxygen системалык файлдарын конфигурациялайбыз. Бардык керектүү өзгөрмөлөр, анын ичинде тил, конфигурациялоо процессинде ошол жерге барышат (караңыз. команду configure_file).
Андан кийин биз максат түзөбүз doc, ал документтерди түзө баштайт. Документтерди түзүү иштеп чыгуу процессинде эң чоң муктаждык болбогондуктан, максат демейки боюнча иштетилбейт; аны ачык түрдө ишке киргизүү керек.
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 ()
Бул жерде биз үчүнчү Python табабыз жана максаттуу түзөбүз wandbox, API кызматына ылайыктуу суроону жаратат Таякча кутусу, жана аны узатат. Жооп даяр кумкоргонго шилтеме менен келет.
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()
Бул үчүн кызмат колдонулат Таякча кутусу. Мен алардын серверлери канчалык ийкемдүү экенин билбейм, бирок бул мүмкүнчүлүктү кыянаттык менен пайдаланбоо керек деп ойлойм.
Чынында, CMake 3.13 версиясы бул жардамда сүрөттөлгөн консолдук буйруктардын айрымдарын иштетүү үчүн гана талап кылынат. CMake скрипттеринин синтаксисинин көз карашынан алганда, 3.8 версиясы генерацияны башка жолдор менен чакырса жетиштүү.
CMake - бул ар бир даамы жана түсү үчүн функцияларды ишке ашырууга мүмкүндүк берген абдан күчтүү жана ийкемдүү система. Жана, синтаксис кээде көп нерсени каалагандай калтырса да, шайтан дагы эле ал боёгондой коркунучтуу эмес. CMake куруу системасын коомдун жана ден соолуктун жыргалчылыгы үчүн колдонуңуз.