
Ҳангоми таҳия, ман дӯст медорам, ки компиляторҳоро тағир диҳам, режимҳо созам, версияҳои вобастагӣ, анҷом додани таҳлили статикӣ, чен кардани кор, ҷамъоварии фарогирӣ, тавлиди ҳуҷҷатҳо ва ғайра. Ва ман дар ҳақиқат CMake-ро дӯст медорам, зеро он ба ман имкон медиҳад, ки ҳама чизеро, ки ман мехоҳам, иҷро кунам.
Бисёр одамон CMake-ро танқид мекунанд ва аксар вақт сазоворанд, аммо агар шумо ба он нигоҳ кунед, на ҳама чиз он қадар бад аст ва ба наздикӣ тамоман бад нест, ва самти тараккиёт тамоман мусбат аст.
Дар ин ёддошт, ман мехоҳам ба шумо бигӯям, ки чӣ тавр ба таври оддӣ китобхонаи сарлавҳаро дар C++ дар системаи CMake ташкил кардан лозим аст, то ин ки функсияҳои зеринро ба даст оред:
- Маҷлис;
- Санҷишҳои автоматӣ;
- Андозаи фарогирии код;
- насб;
- Ҳуҷҷати автоматӣ;
- Насли қуттии онлайн;
- Таҳлили статикӣ.
Ҳар касе, ки аллакай афзалиятҳо ва C-ро дарк мекунад, метавонад ба осонӣ ва ба истифодаи он шурӯъ кунед.
Мундариҷа
.
├── 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.cppМо асосан дар бораи чӣ гуна ташкил кардани скриптҳои CMake сӯҳбат хоҳем кард, бинобар ин онҳо ба таври муфассал баррасӣ хоҳанд шуд. Ҳар кас метавонад боқимондаи файлҳоро мустақиман бубинад .
Пеш аз ҳама, шумо бояд версияи зарурии системаи CMake-ро дархост кунед. CMake инкишоф меёбад, имзоҳои фармон ва рафтор дар шароитҳои гуногун тағйир меёбанд. Барои он ки CMake фавран бифаҳмад, ки мо аз он чӣ мехоҳем, мо бояд фавран талаботҳои худро барои он сабт кунем.
cmake_minimum_required(VERSION 3.13)Сипас, мо лоиҳаи худро, ном, версияи он, забонҳои истифодашаванда ва ғайраро таъин мекунем (ниг. ).
Дар ин ҳолат мо забонро нишон медиҳем CXX (ва ин маънои C++-ро дорад) то ки CMake як компилятори забони C-ро ҷӯё нашавад (бо нобаёнӣ, CMake ду забонро дар бар мегирад: C ва C++).
project(Mylib VERSION 1.0 LANGUAGES CXX)Дар ин ҷо шумо метавонед фавран тафтиш кунед, ки оё лоиҳаи мо ба лоиҳаи дигар ҳамчун зерлоиҳа дохил карда шудааст. Ин дар оянда ёрии калон мерасонад.
get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)
Мо ду вариантро пешниҳод мекунем.
Варианти аввал аст — барои хомӯш кардани санҷишҳои воҳид. Ин метавонад зарур бошад, агар мо боварӣ дошта бошем, ки ҳама чиз бо санҷишҳо мувофиқ аст, аммо мо танҳо мехоҳем, масалан, лоиҳаи худро насб ё бастабандӣ кунем. Ё лоиҳаи мо ҳамчун зерлоиҳа дохил карда шудааст - дар ин ҳолат, корбари лоиҳаи мо ба гузаронидани санҷишҳои мо манфиатдор нест. Шумо вобастагиҳоеро, ки шумо истифода мебаред, озмоиш намекунед, ҳамин тавр не?
option(MYLIB_TESTING "Включить модульное тестирование" ON)Илова бар ин, мо як варианти алоҳида хоҳем дод барои чен кардани фарогирии код тавассути санҷишҳо, аммо он асбобҳои иловагиро талаб мекунад, бинобар ин он бояд ба таври возеҳ фаъол карда шавад.
option(MYLIB_COVERAGE "Включить измерение покрытия кода тестами" OFF)
Албатта, мо барномасозони олиҷаноб ҳастем, аз ин рӯ мо мехоҳем, ки сатҳи максималии ташхиси вақти компилятсионӣ аз компилятор дошта бошад. Ягон муши парешон намегузарад.
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
)Мо инчунин васеъкуниро ғайрифаъол хоҳем кард, то ба стандарти забони C++ пурра мувофиқат кунем. Онҳо бо нобаёнӣ дар CMake фаъол карда шудаанд.
if(NOT CMAKE_CXX_EXTENSIONS)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
Китобхонаи мо танҳо аз файлҳои сарлавҳа иборат аст, ки маънои онро дорад, ки мо дар шакли китобхонаҳои статикӣ ё динамикӣ ягон ихроҷ надорем. Аз тарафи дигар, барои истифодаи берунаи китобхонаи мо, он бояд насб карда шавад, он бояд дар система ошкор карда шавад ва ба лоиҳаи шумо пайваст шавад ва дар айни замон ин сарлавҳаҳо, инчунин эҳтимолан баъзе сарлавҳаҳои иловагӣ, ба он хосиятҳо пайваст карда мешаванд.
Бо ин мақсад мо китобхонаи интерфейси эҷод мекунем.
add_library(mylib INTERFACE)Мо сарлавҳаҳоро ба китобхонаи интерфейси худ мепайвандем.
Истифодаи муосир, муд ва ҷавонони CMake маънои онро дорад, ки сарлавҳаҳо, хосиятҳо ва ғайра. тавассути як ҳадаф интиқол дода мешавад. Пас гуфтан кифоя аст , ва ҳама сарлавҳаҳое, ки бо ҳадаф алоқаманданд dependency, барои манбаъҳои марбут ба ҳадаф дастрас хоҳад буд target. Ва ба шумо ҳеҷ чиз лозим нест [target_]include_directories. Ин дар зер дар таҳлил нишон дода мешавад .
Инчунин ба ном диққат додан лозим аст. .
Ин фармон сарлавҳаҳои ба мо лозимиро бо китобхонаи интерфейси мо алоқаманд мекунад ва агар китобхонаи мо ба ягон ҳадаф дар як иерархияи CMake пайваст бошад, сарлавҳаҳои директория бо он алоқаманд хоҳанд буд ${CMAKE_CURRENT_SOURCE_DIR}/include, ва агар китобхонаи мо дар система насб карда шуда бошад ва бо истифода аз фармон ба лоиҳаи дигар пайваст карда шавад , пас сарлавҳаҳои директория бо он алоқаманд хоҳанд шуд include нисбат ба директорияи насбкунӣ.
target_include_directories(mylib INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)Биёед стандарти забонро муқаррар кунем. Албатта, охиринаш. Дар баробари ин, мо на танҳо стандартро дохил мекунем, балки онро ба онҳое, ки аз китобхонаи мо истифода мебаранд, паҳн мекунем. Ин ба туфайли он ба даст оварда мешавад, ки моликияти муқарраршуда категория дорад INTERFACE (ниг. банди. ).
target_compile_features(mylib INTERFACE cxx_std_17)Биёед барои китобхонаи худ тахаллус эҷод кунем. Гузашта аз ин, барои зебоӣ, он дар "фазои ном" махсус хоҳад буд. Ин вақте муфид хоҳад буд, ки модулҳои гуногун дар китобхонаи мо пайдо мешаванд ва мо онҳоро новобаста аз ҳамдигар пайваст мекунем. .
add_library(Mylib::mylib ALIAS mylib)
Насб кардани сарлавҳаҳои мо дар система. Дар ин ҷо ҳама чиз оддӣ аст. Мо мегӯем, ки папка бо ҳама сарлавҳаҳо бояд ба директория ворид шавад include нисбат ба ҷойгиршавии насб.
install(DIRECTORY include/mylib DESTINATION include)Баъдан, мо ба системаи сохтмон хабар медиҳем, ки мо мехоҳем фармонро дар лоиҳаҳои тарафи сеюм даъват кунем find_package(Mylib) ва ба даст овардани ҳадаф Mylib::mylib.
install(TARGETS mylib EXPORT MylibConfig)
install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake)Имлои навбатиро бояд ҳамин тавр фаҳмид. Вақте ки дар лоиҳаи тарафи сеюм мо фармонро даъват мекунем find_package(Mylib 1.2.3 REQUIRED), ва версияи воқеии китобхонаи насбшуда бо версия номувофиқ хоҳад буд 1.2.3CMake ба таври худкор хато эҷод мекунад. Яъне, ба шумо лозим нест, ки версияҳоро дастӣ пайгирӣ кунед.
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)
Агар санҷишҳо ғайрифаъол ба таври ошкоро истифода ё лоиҳаи мо зерлоиҳа аст, яъне бо истифода аз фармон ба лоиҳаи дигари CMake пайваст мешавад , мо дар баробари иерархия минбаъд ҳаракат намекунем ва скрипт, ки фармонҳоро барои тавлид ва иҷро кардани санҷишҳо тавсиф мекунад, танҳо иҷро намешавад.
if(NOT MYLIB_TESTING)
message(STATUS "Тестирование проекта Mylib выключено")
elseif(IS_SUBPROJECT)
message(STATUS "Mylib не тестируется в режиме подмодуля")
else()
add_subdirectory(test)
endif()
Дар мавриди зерлоиҳа ҳуҷҷатгузорӣ низ таҳия карда намешавад.
if(NOT IS_SUBPROJECT)
add_subdirectory(doc)
endif()
Ба ҳамин монанд, зерлоиҳа низ қуттии онлайн нахоҳад дошт.
if(NOT IS_SUBPROJECT)
add_subdirectory(online)
endif()
Пеш аз ҳама, мо бастаеро бо чаҳорчӯбаи санҷиши лозима пайдо мекунем (бо яки дӯстдоштаатон иваз кунед).
find_package(doctest 2.3.3 REQUIRED)Биёед файли иҷрошавандаи худро бо санҷишҳо созем. Одатан ман мустақиман ба бинарии иҷрошаванда танҳо файлеро илова мекунам, ки функсияро дар бар мегирад main.
add_executable(mylib-unit-tests test_main.cpp)Ва ман файлҳоеро илова мекунам, ки дар онҳо худи санҷишҳо баъдтар тавсиф карда мешаванд. Аммо ба шумо лозим нест, ки ин корро кунед.
target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp)Мо вобастагиҳоро пайваст мекунем. Лутфан қайд кунед, ки мо танҳо ҳадафҳои CMake-ро, ки ба мо лозим буд, ба бинарии худ пайваст кардем ва фармонро даъват накардем target_include_directories. Сарлавҳаҳо аз чаҳорчӯбаи санҷиш ва аз мо Mylib::mylib, инчунин параметрҳои сохтан (дар ҳолати мо, ин стандарти забони C++ аст) дар баробари ин ҳадафҳо гузаштанд.
target_link_libraries(mylib-unit-tests
PRIVATE
Mylib::mylib
doctest::doctest
)Ниҳоят, мо як ҳадафи ғайриоддӣ месозем, ки “сохт”-и он ба санҷишҳои иҷрошаванда баробар аст ва ин ҳадафро ба сохтани пешфарз илова мекунем (атрибут барои ин масъул аст. ALL). Ин маънои онро дорад, ки сохтани пешфарз санҷишҳоро барои иҷро кардан бармеангезад, яъне мо ҳеҷ гоҳ иҷро кардани онҳоро фаромӯш нахоҳем кард.
add_custom_target(check ALL COMMAND mylib-unit-tests)
Баъдан, мо ченкунии фарогирии кодро фаъол мекунем, агар варианти мувофиқ муайян карда шавад. Ман ба тафсилот намеравам, зеро онҳо нисбат ба CMake бештар ба асбоби ченкунии фарогирӣ алоқаманданд. Танҳо қайд кардан муҳим аст, ки дар асоси натиҷаҳо ҳадаф эҷод карда мешавад , ки бо он оғоз кардани ченкунии фарогирӣ қулай аст.
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()
.
find_package(Doxygen)Баъдан, мо тафтиш мекунем, ки оё корбар тағирёбандаи забонро муқаррар кардааст. Агар ҳа, пас мо ба он даст намезанем, агар не, мо русиро мегирем. Сипас, мо файлҳои системаи Doxygen-ро танзим мекунем. Ҳама тағирёбандаҳои зарурӣ, аз ҷумла забон, дар ҷараёни конфигуратсия ба он ҷо мераванд (ниг. ).
Он гоҳ мо ҳадаф эҷод мекунем , ки ба тавлиди ҳуҷҷатҳо шурӯъ мекунад. Азбаски тавлиди ҳуҷҷатҳо эҳтиёҷоти калонтарин дар раванди таҳия нест, ҳадаф ба таври нобаёнӣ фаъол карда намешавад; он бояд ба таври возеҳ оғоз карда шавад.
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 сеюмро пайдо мекунем ва ҳадаф эҷод мекунем , ки дархости мувофиқи 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, аз ду марҳила иборат аст:
cmake -S путь/к/исходникам -B путь/к/сборочной/директории [опции ...]Агар фармони дар боло овардашуда бо сабаби версияи кӯҳнаи CMake кор накунад, кӯшиш кунед, ки онро тарк кунед
-S:cmake путь/к/исходникам -B путь/к/сборочной/директории [опции ...]
.
cmake --build путь/к/сборочной/директории [--target target].
cmake -S ... -B ... -DMYLIB_COVERAGE=ON [прочие опции ...]Ҳадафро дар бар мегирад , ки бо он шумо метавонед ченкунии фарогирии кодро тавассути санҷишҳо оғоз кунед.
cmake -S ... -B ... -DMYLIB_TESTING=OFF [прочие опции ...]Қобилияти ғайрифаъол кардани сохтори санҷиши воҳид ва ҳадафро фароҳам меорад . Дар натиҷа, андозагирии фарогирии кодҳо аз рӯи санҷишҳо хомӯш карда мешавад (ниг. ).
Санҷиш инчунин ба таври худкор ғайрифаъол мешавад, агар лоиҳа ба лоиҳаи дигар ҳамчун зерлоиҳа бо истифода аз фармон пайваст шавад .
cmake -S ... -B ... -DMYLIB_DOXYGEN_LANGUAGE=English [прочие опции ...]Забони ҳуҷҷатҳоеро, ки ҳадаф тавлид мекунад, иваз мекунад ба додашуда. Барои рӯйхати забонҳои дастрас нигаред .
Забони русӣ бо нобаёнӣ фаъол аст.
cmake --build path/to/build/directory
cmake --build path/to/build/directory --target allАгар ҳадаф муайян карда нашавад (ки ба ҳадаф баробар аст all), ҳама чизро ҷамъоварӣ мекунад ва инчунин ҳадафро даъват мекунад .
cmake --build path/to/build/directory --target mylib-unit-testsСанҷишҳои воҳидиро тартиб медиҳад. Бо нобаёнӣ фаъол карда шудааст.
cmake --build путь/к/сборочной/директории --target checkСанҷишҳои воҳиди ҷамъшударо (агар ҷамъоварӣ нашуда бошад) иҷро мекунад. Бо нобаёнӣ фаъол карда шудааст.
Ҳамчунин нигаред .
cmake --build путь/к/сборочной/директории --target coverageСанҷишҳои воҳиди иҷрошударо (агар иҷро нашуда бошад) барои фарогирии код тавассути санҷишҳо бо истифода аз барнома таҳлил мекунад .
Ихроҷи пӯшиш чунин хоҳад буд:
------------------------------------------------------------------------------
GCC Code Coverage Report
Directory: /path/to/cmakecpptemplate/include/
------------------------------------------------------------------------------
File Lines Exec Cover Missing
------------------------------------------------------------------------------
mylib/myfeature.hpp 2 2 100%
------------------------------------------------------------------------------
TOTAL 2 2 100%
------------------------------------------------------------------------------Ҳадаф танҳо вақте дастрас аст, ки интихоб фаъол карда мешавад .
Ҳамчунин нигаред .
cmake --build путь/к/сборочной/директории --target docБо истифода аз система тавлиди ҳуҷҷатҳои кодиро оғоз мекунад .
cmake --build путь/к/сборочной/директории --target wandboxҶавоб аз хидмат чунин ба назар мерасад:
{
"permlink" : "QElvxuMzHgL9fqci",
"status" : "0",
"url" : "https://wandbox.org/permlink/QElvxuMzHgL9fqci"
}Барои ин хидмат истифода мешавад . Ман намедонам, ки серверҳои онҳо то чӣ андоза чандир мебошанд, аммо ман фикр мекунам, ки аз ин имконият набояд суиистифода шавад.
Лоиҳаро дар реҷаи дебаг бо андозагирии фарогирӣ созед
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug -DMYLIB_COVERAGE=ON
cmake --build путь/к/сборочной/директории --target coverage --parallel 16Ҷойгир кардани лоиҳа бе васлкунӣ ва санҷиши пешакӣ
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DMYLIB_TESTING=OFF -DCMAKE_INSTALL_PREFIX=путь/к/установойной/директории
cmake --build путь/к/сборочной/директории --target installБо компилятори додашуда дар реҷаи озод созед
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-8 -DCMAKE_PREFIX_PATH=путь/к/директории/куда/установлены/зависимости
cmake --build путь/к/сборочной/директории --parallel 4Таҳияи ҳуҷҷатҳо бо забони англисӣ
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Release -DMYLIB_DOXYGEN_LANGUAGE=English
cmake --build путь/к/сборочной/директории --target doc
3.13
Дар асл, версияи CMake 3.13 танҳо барои иҷро кардани баъзе фармонҳои консол, ки дар ин кӯмак тавсиф шудаанд, лозим аст. Аз нуқтаи назари синтаксиси скриптҳои CMake, версияи 3.8 кифоя аст, агар тавлид бо роҳҳои дигар даъват карда шавад.
Китобхонаи санҷишӣ
Санҷишро ғайрифаъол кардан мумкин аст (ниг ).
Барои иваз кардани забоне, ки ҳуҷҷатҳо дар он тавлид мешаванд, вариант пешниҳод карда мешавад .
Тарҷумони забон
Барои тавлиди автоматӣ .
Бо CMake ва якчанд асбобҳои хуб, шумо метавонед таҳлили статикиро бо кӯшиши ҳадди ақал таъмин кунед.
Cppcheck
CMake дорои як абзори таҳлили статикӣ мебошад .
Барои ин шумо бояд интихобро истифода баред :
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;-Iпуть/к/исходникам/include"Пас аз ин, таҳлили статикӣ ба таври худкор ҳар боре, ки манбаъ тартиб дода мешавад ва аз нав тартиб дода мешавад. Ҳеҷ чизи иловагӣ лозим нест.
Занг
Бо ёрии асбоби ачоиб Шумо инчунин метавонед дар ҳеҷ вақт таҳлили статикиро иҷро кунед:
scan-build cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug
scan-build cmake --build путь/к/сборочной/директорииДар ин ҷо, бар хилофи парвандаи Cppcheck, шумо бояд ҳар дафъа сохтмонро иҷро кунед scan-build.
CMake як системаи хеле пурқувват ва чандир аст, ки ба шумо имкон медиҳад, ки функсияҳоро барои ҳар завқ ва ранг амалӣ кунед. Ва, гарчанде ки синтаксис баъзан чизҳои дилхоҳро тарк мекунад, иблис ҳанӯз он қадар даҳшатнок нест, ки ӯ ранг карда шудааст. Системаи сохтани CMake -ро барои манфиати ҷомеа ва саломатӣ истифода баред.
→
Манбаъ: will.com
