Fejlesztés közben szeretek fordítókat cserélni, építeni módokat, függőségi verziókat, statikus elemzést végezni, teljesítményt mérni, lefedettséget gyűjteni, dokumentációt generálni stb. És nagyon szeretem a CMake-et, mert lehetővé teszi, hogy mindent megtegyek, amit akarok.
Sokan kritizálják a CMake-et, és gyakran megérdemelten, de ha megnézzük, nem minden olyan rossz, és mostanában egyáltalán nem rossz, és a fejlődés iránya meglehetősen pozitív.
Ebben a megjegyzésben azt szeretném elmondani, hogyan lehet egyszerűen megszervezni egy fejléckönyvtárat C++ nyelven a CMake rendszerben, hogy a következő funkciókat kapja meg:
Összeszerelés;
Automatikus futási tesztek;
Kódlefedettség mérése;
Telepítés;
Auto-dokumentáció;
Online sandbox generálás;
Statikus elemzés.
Bárki, aki már érti az előnyöket és a C-make-et, egyszerűen megteheti projekt sablon letöltése és kezdje el használni.
Főleg a CMake szkriptek rendszerezéséről fogunk beszélni, így ezekről lesz szó részletesen. A többi fájlt bárki közvetlenül megtekintheti a projekt sablonoldalán.
Először is le kell kérni a CMake rendszer szükséges verzióját. A CMake fejlődik, a parancs aláírások és a viselkedés különböző körülmények között változik. Ahhoz, hogy a CMake azonnal megértse, mit akarunk tőle, azonnal rögzítenünk kell a vele szemben támasztott követelményeinket.
cmake_minimum_required(VERSION 3.13)
Ezután kijelöljük a projektünket, annak nevét, verzióját, a használt nyelveket stb. (lásd. команду project).
Ebben az esetben a nyelvet jelöljük CXX (és ez C++-t jelent), hogy a CMake ne feszüljön, és ne keressen C nyelvű fordítót (alapértelmezés szerint a CMake két nyelvet tartalmaz: C és C++).
project(Mylib VERSION 1.0 LANGUAGES CXX)
Itt azonnal ellenőrizheti, hogy projektünk alprojektként szerepel-e egy másik projektben. Ez sokat segít a jövőben.
Az első lehetőség az MYLIB_TESTING — az egységtesztek letiltásához. Erre akkor lehet szükség, ha biztosak vagyunk benne, hogy minden rendben van a tesztekkel, de csak például a projektünket szeretnénk telepíteni vagy csomagolni. Vagy a projektünk alprojektként szerepel – ebben az esetben a projektünk felhasználója nem érdekelt tesztjeink futtatásában. Ugye nem teszteled az általad használt függőségeket?
Ezen kívül külön opciót is készítünk MYLIB_COVERAGE kódlefedettség tesztekkel történő mérésére, de ehhez további eszközökre lesz szükség, ezért kifejezetten engedélyezni kell.
Természetesen hűvös plusz programozók vagyunk, ezért szeretnénk a fordítóprogramtól a maximális fordítási idejű diagnosztikát. Egy egér sem csúszik át rajta.
Könyvtárunk csak fejlécfájlokból áll, ami azt jelenti, hogy nincs kimerítésünk statikus vagy dinamikus könyvtárak formájában. Másrészt ahhoz, hogy a könyvtárunkat külsőleg használhassuk, telepíteni kell, a rendszerben észlelhetőnek kell lennie, és csatlakoznia kell a projekthez, és egyúttal ugyanazokat a fejléceket, esetleg néhány további fejlécet, tulajdonságok kapcsolódnak hozzá.
Ebből a célból létrehozunk egy interfész könyvtárat.
add_library(mylib INTERFACE)
A fejléceket az interfész könyvtárunkhoz kötjük.
A CMake modern, divatos, fiatalos használata azt jelenti, hogy a fejlécek, tulajdonságok stb. egyetlen célponton keresztül továbbítják. Szóval elég annyit mondani target_link_libraries(target PRIVATE dependency), és a célhoz társított összes fejléc dependency, elérhető lesz a célhoz tartozó források számára target. És nem kell semmi [target_]include_directories. Ezt az alábbiakban az elemzés bemutatja CMake szkript egységtesztekhez.
Ez a parancs társítja a szükséges fejléceket az interfész könyvtárunkhoz, és ha a könyvtárunk csatlakozik bármely célhoz ugyanazon a CMake hierarchián belül, akkor a könyvtár fejlécei hozzá lesznek rendelve. ${CMAKE_CURRENT_SOURCE_DIR}/include, és ha a könyvtárunk telepítve van a rendszerre, és a paranccsal csatlakozik egy másik projekthez find_package, akkor a címtár fejlécei hozzá lesznek rendelve include a telepítési könyvtárhoz képest.
Állítsunk be egy nyelvi szabványt. Természetesen a legutolsó. Ugyanakkor nemcsak a szabványt tartalmazzuk, hanem kiterjesztjük azokra is, akik használni fogják a könyvtárunkat. Ez annak köszönhető, hogy a beállított tulajdonságnak van kategóriája INTERFACE (Lásd. target_compile_features parancsot).
Hozzon létre egy álnevet a könyvtárunknak. Sőt, a szépség kedvéért egy speciális „névtérben” lesz. Ez akkor lesz hasznos, ha különböző modulok jelennek meg a könyvtárunkban, és ezeket egymástól függetlenül kötjük össze. Mint például Bustában.
Fejléceink telepítése a rendszerbe. Itt minden egyszerű. Azt mondjuk, hogy az összes fejlécet tartalmazó mappának a könyvtárba kell kerülnie include a telepítés helyéhez képest.
Ezután tájékoztatjuk az összeállítási rendszert, hogy meg akarjuk hívni a parancsot harmadik féltől származó projektekben find_package(Mylib) és kap egy gólt Mylib::mylib.
A következő varázslatot így kell érteni. Amikor egy harmadik féltől származó projektben meghívjuk a parancsot find_package(Mylib 1.2.3 REQUIRED), és a telepített könyvtár valós verziója nem lesz kompatibilis a verzióval 1.2.3A CMake automatikusan hibát generál. Vagyis nem kell manuálisan követnie a verziókat.
Ha a tesztek le vannak tiltva kifejezetten a használatával megfelelő opciót vagy a projektünk egy alprojekt, vagyis egy másik CMake projekthez kapcsolódik a paranccsal add_subdirectory, nem haladunk tovább a hierarchiában, és a tesztek generálására és futtatására szolgáló parancsokat leíró szkript egyszerűen nem fut le.
if(NOT MYLIB_TESTING)
message(STATUS "Тестирование проекта Mylib выключено")
elseif(IS_SUBPROJECT)
message(STATUS "Mylib не тестируется в режиме подмодуля")
else()
add_subdirectory(test)
endif()
Először is találunk egy csomagot a szükséges teszt keretrendszerrel (cserélje ki kedvencére).
find_package(doctest 2.3.3 REQUIRED)
Készítsük el a futtatható fájlunkat tesztekkel. Általában csak azt a fájlt adom hozzá közvetlenül a futtatható binárishoz, amely a függvényt tartalmazza main.
add_executable(mylib-unit-tests test_main.cpp)
És hozzáadok fájlokat, amelyekben magukat a teszteket később ismertetjük. De nem kell ezt tenned.
Összekapcsoljuk a függőségeket. Kérjük, vegye figyelembe, hogy csak a szükséges CMake célokat kapcsoltuk össze a binárisunkkal, és nem hívtuk meg a parancsot target_include_directories. Címsorok a teszt keretrendszerből és a miénkből Mylib::mylib, valamint az összeállítási paraméterek (esetünkben ez a C++ nyelvi szabvány) ezekkel a célokkal együtt bejöttek.
Végül létrehozunk egy dummy targetet, melynek „build”-je egyenértékű a tesztek futtatásával, és hozzáadjuk ezt a célt az alapértelmezett buildhez (az attribútum felelős ezért ALL). Ez azt jelenti, hogy az alapértelmezett build elindítja a tesztek futtatását, vagyis soha nem felejtjük el futtatni őket.
add_custom_target(check ALL COMMAND mylib-unit-tests)
Ezután engedélyezzük a kódlefedettség mérését, ha a megfelelő opció meg van adva. Nem megyek bele a részletekbe, mert ezek inkább egy lefedettségmérő eszközhöz kapcsolódnak, mint a CMake-hez. Csak azt fontos megjegyezni, hogy az eredmények alapján cél lesz coverage, amellyel kényelmesen el lehet kezdeni a lefedettség mérését.
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()
Ezután ellenőrizzük, hogy a felhasználó beállította-e a nyelvi változót. Ha igen, akkor nem nyúlunk hozzá, ha nem, akkor vegyünk oroszt. Ezután konfiguráljuk a Doxygen rendszerfájlokat. Az összes szükséges változó, beleértve a nyelvet is, odakerül a konfigurációs folyamat során (lásd. команду configure_file).
Aztán létrehozunk egy célt doc, amely megkezdi a dokumentáció generálását. Mivel nem a dokumentáció generálása a legnagyobb igény a fejlesztési folyamatban, a cél alapértelmezés szerint nem lesz engedélyezve, azt kifejezetten el kell indítani.
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 ()
Itt megtaláljuk a harmadik Python-t, és létrehozunk egy célt wandbox, amely a szolgáltatás API-nak megfelelő kérést generál Pálcadoboz, és elküldi. A válasz egy linket tartalmaz a kész homokozóra.
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()
Lehetővé teszi az egységteszt-felépítés és célzás letiltását check. Ennek eredményeként a kódlefedettség tesztekkel történő mérése kikapcsol (lásd. MYLIB_COVERAGE).
A tesztelés akkor is automatikusan letiltásra kerül, ha a projekt a paranccsal alprojektként kapcsolódik egy másik projekthez add_subdirectory.
A szolgáltatást erre használják Pálcadoboz. Nem tudom mennyire rugalmasak a szervereik, de úgy gondolom, hogy ezzel a lehetőséggel nem szabad visszaélni.
Valójában a CMake 3.13-as verziója csak néhány, ebben a súgóban leírt konzolparancs futtatásához szükséges. A CMake szkriptek szintaxisa szempontjából a 3.8-as verzió elegendő, ha a generálást más módon hívják.
Ezt követően a statikus elemzés automatikusan elindul minden alkalommal, amikor a forrás összeállításra és újrafordításra kerül. Nincs szükség további tennivalókra.
Csengés
Egy csodálatos eszköz segítségével scan-build A statikus elemzést is pillanatok alatt futtathatja:
A CMake egy nagyon erős és rugalmas rendszer, amely lehetővé teszi, hogy minden ízléshez és színhez funkcionalitást valósítson meg. És bár a szintaxis néha sok kívánnivalót hagy maga után, az ördög mégsem olyan szörnyű, mint ahogy lefestik. Használja a CMake build rendszert a társadalom és az egészség érdekében.