
Pandan devlopman, mwen renmen chanje konpilateur, bati mòd, vèsyon depandans, fè analiz estatik, mezire pèfòmans, kolekte pwoteksyon, jenere dokiman, elatriye. E mwen vrèman renmen CMake paske li pèmèt mwen fè tout sa mwen vle.
Anpil moun kritike CMake, e souvan merite sa, men si w gade li, se pa tout bagay ki tèlman mal, epi dènyèman. pa mal ditou, ak direksyon devlopman se byen pozitif.
Nan nòt sa a, mwen vle di ou ki jan yo tou senpleman òganize yon bibliyotèk header nan C ++ nan sistèm nan CMake pou jwenn fonksyonalite sa a:
- Asanble;
- Tès Autorun;
- Mezi kouvèti kòd;
- Enstalasyon;
- Oto-dokimantasyon;
- Jenerasyon sandbox sou entènèt;
- Analiz estatik.
Nenpòt moun ki deja konprann avantaj yo ak C-fè kapab tou senpleman epi kòmanse sèvi ak li.
Content
.
├── 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.cppNou pral sitou pale sou ki jan yo òganize scripts CMake, kidonk yo pral diskite an detay. Nenpòt moun ka wè rès fichye yo dirèkteman .
Premye a tout, ou bezwen mande vèsyon ki nesesè nan sistèm CMake la. CMake ap evolye, siyati kòmand ak konpòtman nan diferan kondisyon yo ap chanje. Nan lòd pou CMake imedyatman konprann sa nou vle soti nan li, nou bezwen imedyatman anrejistre kondisyon nou yo pou li.
cmake_minimum_required(VERSION 3.13)Lè sa a, nou pral deziyen pwojè nou an, non li, vèsyon, lang yo itilize, elatriye (gade. ).
Nan ka sa a nou endike lang lan CXX (e sa vle di C++) pou CMake pa souch epi chèche yon du lang C (pa default, CMake gen ladann de lang: C ak C++).
project(Mylib VERSION 1.0 LANGUAGES CXX)Isit la ou ka imedyatman tcheke si pwojè nou an enkli nan yon lòt pwojè kòm yon sou-pwojè. Sa a pral ede anpil nan tan kap vini an.
get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)
Nou pral bay de opsyon.
Premye opsyon a se — pou enfim tès inite yo. Sa a ka nesesè si nou sèten ke tout bagay an lòd ak tès yo, men nou sèlman vle, pou egzanp, enstale oswa pake pwojè nou an. Oswa pwojè nou an enkli kòm yon subproject - nan ka sa a, itilizatè a nan pwojè nou an pa enterese nan kouri tès nou yo. Ou pa teste depandans ou itilize yo, pa vre?
option(MYLIB_TESTING "Включить модульное тестирование" ON)Anplis de sa, nou pral fè yon opsyon separe pou mezire kouvèti kòd pa tès yo, men li pral mande pou zouti adisyonèl, kidonk li pral bezwen aktive klèman.
option(MYLIB_COVERAGE "Включить измерение покрытия кода тестами" OFF)
Natirèlman, nou se fre plis pwogramasyon, kidonk nou vle nivo maksimòm dyagnostik konpile-tan soti nan du a. Pa yon sèl sourit pral glise nan.
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
)Nou pral tou enfim ekstansyon yo nan lòd yo konplètman konfòme li avèk estanda lang C++ la. Yo aktive pa default nan CMake.
if(NOT CMAKE_CXX_EXTENSIONS)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
Bibliyotèk nou an konsiste sèlman de dosye header, ki vle di nou pa gen okenn echapman sou fòm bibliyotèk estatik oswa dinamik. Nan lòt men an, yo nan lòd yo sèvi ak bibliyotèk nou an deyò, li bezwen yo dwe enstale, li bezwen yo dwe detekte nan sistèm nan ak konekte ak pwojè ou a, ak an menm tan an menm en-tête sa yo, osi byen ke pètèt kèk lòt adisyonèl, yo tache ak li pwopriyete.
Pou rezon sa a, nou kreye yon bibliyotèk koòdone.
add_library(mylib INTERFACE)Nou mare headers nan bibliyotèk koòdone nou an.
Modèn, alamòd, itilizasyon jèn nan CMake implique ke headers, pwopriyete, elatriye. transmèt atravè yon sèl sib. Se konsa, li sifi pou di , ak tout headers ki asosye ak sib la dependency, yo pral disponib pou sous ki fè pati sib la target. Epi ou pa bezwen okenn [target_]include_directories. Sa a pral demontre anba a nan analiz la .
Li se tou vo peye atansyon sou sa yo rele an. .
Kòmandman sa a asosye tèt nou bezwen yo ak bibliyotèk koòdone nou an, epi si bibliyotèk nou an konekte ak nenpòt sib ki nan menm yerachi CMake la, Lè sa a, tèt yo ki soti nan anyè a pral asosye avèk li. ${CMAKE_CURRENT_SOURCE_DIR}/include, epi si bibliyotèk nou an enstale sou sistèm nan epi konekte ak yon lòt pwojè lè l sèvi avèk lòd la , Lè sa a, headers soti nan anyè a pral asosye ak li include parapò ak anyè enstalasyon an.
target_include_directories(mylib INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)Ann mete yon estanda lang. Natirèlman, yon sèl la trè dènye. An menm tan an, nou pa sèlman enkli estanda a, men tou, pwolonje li bay moun ki pral sèvi ak bibliyotèk nou an. Sa a se reyalize akòz lefèt ke pwopriyete a mete gen yon kategori INTERFACE (cm. ).
target_compile_features(mylib INTERFACE cxx_std_17)Ann kreye yon alyas pou bibliyotèk nou an. Anplis, pou bote, li pral nan yon espesyal "namespace". Sa a pral itil lè diferan modil parèt nan bibliyotèk nou an, epi nou ale nan konekte yo poukont youn ak lòt. .
add_library(Mylib::mylib ALIAS mylib)
Enstale headers nou yo nan sistèm lan. Tout bagay se senp isit la. Nou di ke katab la ak tout tèt yo ta dwe ale nan anyè a include parapò ak kote enstalasyon an.
install(DIRECTORY include/mylib DESTINATION include)Apre sa, nou enfòme sistèm nan bati ke nou vle pou kapab rele lòd la nan pwojè twazyèm pati find_package(Mylib) epi jwenn yon objektif Mylib::mylib.
install(TARGETS mylib EXPORT MylibConfig)
install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake)Pwochen eple a ta dwe konprann fason sa a. Lè nan yon pwojè twazyèm pati nou rele lòd la find_package(Mylib 1.2.3 REQUIRED), ak vèsyon reyèl la nan bibliyotèk la enstale yo pral enkonpatib ak vèsyon an 1.2.3CMake pral otomatikman jenere yon erè. Sa vle di, ou pa pral bezwen swiv vèsyon manyèlman.
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)
Si tès yo enfim klèman lè l sèvi avèk oswa pwojè nou an se yon sou-pwojè, se sa ki, li konekte ak yon lòt pwojè CMake lè l sèvi avèk lòd la , nou pa avanse pi lwen sou yerachi a, ak script la, ki dekri kòmandman yo pou jenere ak kouri tès, tou senpleman pa kouri.
if(NOT MYLIB_TESTING)
message(STATUS "Тестирование проекта Mylib выключено")
elseif(IS_SUBPROJECT)
message(STATUS "Mylib не тестируется в режиме подмодуля")
else()
add_subdirectory(test)
endif()
Dokimantasyon pa pral pwodwi tou nan ka a nan yon sou-pwojè.
if(NOT IS_SUBPROJECT)
add_subdirectory(doc)
endif()
Menm jan an tou, sou-pwojè a pa pral gen yon bwat sab sou entènèt tou.
if(NOT IS_SUBPROJECT)
add_subdirectory(online)
endif()
Premye a tout, nou jwenn yon pake ak fondasyon tès ki nesesè yo (ranplase ak youn pi renmen ou).
find_package(doctest 2.3.3 REQUIRED)Ann kreye dosye ègzèkutabl nou an ak tès yo. Anjeneral mwen ajoute dirèkteman nan binè a ègzèkutabl sèlman dosye a ki pral genyen fonksyon an main.
add_executable(mylib-unit-tests test_main.cpp)Apre sa, mwen ajoute dosye nan ki tès yo tèt yo dekri pita. Men, ou pa bezwen fè sa.
target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp)Nou konekte depandans. Tanpri sonje ke nou lye sèlman sib CMake nou te bezwen nan binè nou an epi yo pa t rele kòmandman an target_include_directories. Tit ki soti nan kad tès la ak nan pa nou an Mylib::mylib, osi byen ke bati paramèt (nan ka nou an, sa a se estanda lang C++) te vini ansanm ak objektif sa yo.
target_link_libraries(mylib-unit-tests
PRIVATE
Mylib::mylib
doctest::doctest
)Finalman, nou kreye yon sib enbesil, "konstriksyon an" ki ekivalan a kouri tès yo, epi ajoute sib sa a nan bati default la (atribi a responsab pou sa a. ALL). Sa vle di ke konstriksyon default la deklannche tès yo kouri, sa vle di nou p'ap janm bliye kouri yo.
add_custom_target(check ALL COMMAND mylib-unit-tests)
Apre sa, nou pèmèt mezi kouvèti kòd si opsyon ki apwopriye a espesifye. Mwen pa pral antre nan detay, paske yo gen rapò plis ak yon zouti pou mezire pwoteksyon pase CMake. Li enpòtan sèlman sonje ke baze sou rezilta yo pral kreye yon objektif , ak ki li se pratik yo kòmanse mezire pwoteksyon.
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)Apre sa, nou tcheke si itilizatè a te mete varyab lang nan. Si wi, Lè sa a, nou pa manyen li, si se pa, Lè sa a, nou pran Ris. Lè sa a, nou konfigirasyon dosye sistèm Doxygen yo. Tout varyab ki nesesè yo, ki gen ladan lang lan, ale la pandan pwosesis konfigirasyon an (gade. ).
Lè sa a, nou kreye yon objektif , ki pral kòmanse jenere dokiman. Piske jenere dokiman se pa pi gwo bezwen nan pwosesis devlopman an, sib la pa pral aktive pa default; li pral oblije lanse klèman.
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 ()
Isit la nou jwenn twazyèm Python la epi kreye yon sib , ki jenere yon demann ki koresponn ak API sèvis la , epi li voye l ale. Repons lan vini ak yon lyen ki mennen nan bwat sab la fini.
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()
Koulye a, kite a gade nan ki jan yo sèvi ak tout bagay sa yo.
Bati pwojè sa a, tankou nenpòt lòt pwojè sou sistèm konstriksyon CMake, gen de etap:
cmake -S путь/к/исходникам -B путь/к/сборочной/директории [опции ...]Si lòd ki anwo a pa t travay akòz yon ansyen vèsyon CMake, eseye omisyon
-S:cmake путь/к/исходникам -B путь/к/сборочной/директории [опции ...]
.
cmake --build путь/к/сборочной/директории [--target target].
cmake -S ... -B ... -DMYLIB_COVERAGE=ON [прочие опции ...]Gen ladan sib , ak ki ou ka kòmanse mezire kouvèti kòd pa tès yo.
cmake -S ... -B ... -DMYLIB_TESTING=OFF [прочие опции ...]Bay kapasite pou enfim bati tès inite ak sib . Kòm yon rezilta, mezi kouvèti kòd pa tès yo etenn (gade. ).
Tès la tou otomatikman enfim si pwojè a konekte ak yon lòt pwojè kòm yon sous-pwojè lè l sèvi avèk kòmandman an .
cmake -S ... -B ... -DMYLIB_DOXYGEN_LANGUAGE=English [прочие опции ...]Chanje lang nan dokiman an ke sib la jenere bay youn nan. Pou yon lis lang ki disponib, gade .
Larisi aktive pa default.
cmake --build path/to/build/directory
cmake --build path/to/build/directory --target allSi sib la pa espesifye (ki ekivalan a sib la all), kolekte tout sa li kapab, epi tou li rele sib la .
cmake --build path/to/build/directory --target mylib-unit-testsKonpile tès inite yo. Aktive pa default.
cmake --build путь/к/сборочной/директории --target checkKouri tès inite yo kolekte (kolekte, si se pa deja). Aktive pa default.
См. также .
cmake --build путь/к/сборочной/директории --target coverageAnalize kouri (kouri, si se pa deja) tès inite pou kouvèti kòd pa tès lè l sèvi avèk pwogram nan .
Echapman kouch la pral gade yon bagay tankou sa a:
------------------------------------------------------------------------------
GCC Code Coverage Report
Directory: /path/to/cmakecpptemplate/include/
------------------------------------------------------------------------------
File Lines Exec Cover Missing
------------------------------------------------------------------------------
mylib/myfeature.hpp 2 2 100%
------------------------------------------------------------------------------
TOTAL 2 2 100%
------------------------------------------------------------------------------Sib la disponib sèlman lè opsyon a pèmèt .
См. также .
cmake --build путь/к/сборочной/директории --target docKòmanse jenerasyon dokiman kòd lè l sèvi avèk sistèm nan .
cmake --build путь/к/сборочной/директории --target wandboxRepons nan sèvis la sanble yon bagay tankou sa a:
{
"permlink" : "QElvxuMzHgL9fqci",
"status" : "0",
"url" : "https://wandbox.org/permlink/QElvxuMzHgL9fqci"
}Se sèvis la itilize pou sa . Mwen pa konnen ki jan fleksib sèvè yo, men mwen panse ke opòtinite sa a pa ta dwe abize.
Bati pwojè a nan mòd debug ak mezi pwoteksyon
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug -DMYLIB_COVERAGE=ON
cmake --build путь/к/сборочной/директории --target coverage --parallel 16Enstale yon pwojè san yo pa asanble preliminè ak tès
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DMYLIB_TESTING=OFF -DCMAKE_INSTALL_PREFIX=путь/к/установойной/директории
cmake --build путь/к/сборочной/директории --target installBati nan mòd lage ak yon konpilatè bay yo
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-8 -DCMAKE_PREFIX_PATH=путь/к/директории/куда/установлены/зависимости
cmake --build путь/к/сборочной/директории --parallel 4Jenere dokiman an angle
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Release -DMYLIB_DOXYGEN_LANGUAGE=English
cmake --build путь/к/сборочной/директории --target doc
3.13
An reyalite, vèsyon 3.13 CMake sèlman oblije kouri kèk nan kòmandman konsole ki dekri nan èd sa a. Soti nan pwen de vi nan sentaks la nan scripts CMake, vèsyon 3.8 se ase si jenerasyon yo rele nan lòt fason.
Tès bibliyotèk
Tès yo ka enfim (gade ).
Pou chanje lang nan ki dokiman an pral pwodwi, yo bay yon opsyon .
Entèprèt lang
Pou jenerasyon otomatik .
Avèk CMake ak yon koup nan zouti bon, ou ka bay analiz estatik ak efò minim.
Cppcheck
CMake gen sipò entegre pou yon zouti analiz estatik .
Pou fè sa ou bezwen sèvi ak opsyon an :
cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;-Iпуть/к/исходникам/include"Apre sa, analiz estatik yo pral otomatikman lanse chak fwa sous la konpile ak rekonpile. Pa gen okenn nesesite pou fè anyen anplis.
sonnen
Avèk èd nan yon zouti bèl bagay Ou kapab tou kouri analiz estatik nan pa gen tan:
scan-build cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug
scan-build cmake --build путь/к/сборочной/директорииIsit la, kontrèman ak ka a ak Cppcheck, ou bezwen kouri bati a chak fwa nan scan-build.
CMake se yon sistèm trè pwisan ak fleksib ki pèmèt ou aplike fonksyonalite pou chak gou ak koulè. Epi, byenke sentaks la pafwa kite anpil yo dwe vle, dyab la toujou pa terib tankou li pentire. Sèvi ak sistèm CMake build la pou benefis sosyete a ak sante.
→
Sous: www.habr.com
