C++ un CMake - brāļi uz visiem laikiem, II daļa

C++ un CMake - brāļi uz visiem laikiem, II daļa

Iepriekšējā daļā Šis izklaidējošais stāsts runāja par galvenes bibliotēkas organizēšanu CMake build sistēmas ģeneratorā.

Šoreiz mēs tai pievienosim apkopotu bibliotēku, kā arī runāsim par moduļu sasaisti savā starpā.

Tāpat kā iepriekš, tie, kas ir nepacietīgi, var nekavējoties dodieties uz atjaunināto repozitoriju un pieskaries visam ar savām rokām.


saturs

  1. Sadaliet
  2. Iekarot

Sadaliet

Pirmā lieta, kas mums jādara, lai sasniegtu mūsu augsto mērķi, ir sadalīt mūsu izstrādāto programmatūru universālos, izolētos blokos, kas ir vienādi no lietotāja viedokļa.

Pirmajā daļā tika aprakstīts šāds standarta bloks - projekts ar galvenes bibliotēku. Tagad pievienosim mūsu projektam apkopotu bibliotēku.

Lai to izdarītu, izņemsim funkcijas ieviešanu myfunc atsevišķā .cpp-fails:

diff --git a/include/mylib/myfeature.hpp b/include/mylib/myfeature.hpp
index 43db388..ba62b4f 100644
--- a/include/mylib/myfeature.hpp
+++ b/include/mylib/myfeature.hpp
@@ -46,8 +46,5 @@ namespace mylib

         ~  see mystruct
      */
-    inline bool myfunc (mystruct)
-    {
-        return true;
-    }
+    bool myfunc (mystruct);
 }
diff --git a/src/mylib/myfeature.cpp b/src/mylib/myfeature.cpp
new file mode 100644
index 0000000..abb5004
--- /dev/null
+++ b/src/mylib/myfeature.cpp
@@ -0,0 +1,9 @@
+#include <mylib/myfeature.hpp>
+
+namespace mylib
+{
+    bool myfunc (mystruct)
+    {
+        return true;
+    }
+}

Pēc tam mēs definējam kompilējamo bibliotēku (myfeature), kas sastāvēs no iepriekšējā darbībā iegūtā .cpp- fails. Jaunajai bibliotēkai acīmredzami ir vajadzīgas esošās galvenes, un, lai to nodrošinātu, to var un vajadzētu piesaistīt esošajam mērķim mylib. Turklāt savienojums starp tiem ir publisks, kas nozīmē, ka viss, ar ko tiks savienots mērķis myfeature, automātiski saņems slodzi un mērķi mylib (vairāk par adīšanas metodēm).

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 108045c..0de77b8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,6 +64,17 @@ target_compile_features(mylib INTERFACE cxx_std_17)

 add_library(Mylib::mylib ALIAS mylib)

+###################################################################################################
+##
+##      Компилируемая библиотека
+##
+###################################################################################################
+
+add_library(myfeature src/mylib/myfeature.cpp)
+target_link_libraries(myfeature PUBLIC mylib)
+
+add_library(Mylib::myfeature ALIAS myfeature)
+

Tālāk mēs pārliecināsimies, ka sistēmā ir instalēta arī jaunā bibliotēka:

@@ -72,7 +83,7 @@ add_library(Mylib::mylib ALIAS mylib)

 install(DIRECTORY include/mylib DESTINATION include)

-install(TARGETS mylib EXPORT MylibConfig)
+install(TARGETS mylib myfeature EXPORT MylibConfig)
 install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake)

 include(CMakePackageConfigHelpers)

Jāatzīmē, ka šim nolūkam myfeature, kas attiecas uz mylib tika izveidots aizstājvārds ar prefiksu Mylib::. Tas pats ir rakstīts abiem mērķiem, eksportējot tos instalēšanai sistēmā. Tas ļauj vienmērīgi strādāt ar mērķiem jebkuram saistošā shēma.

Pēc tam atliek vien saistīt vienību testus ar jauno bibliotēku (funkcija myfunc izņemts no virsraksta, tāpēc tagad jums ir jāsaista):

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5620be4..bc1266c 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -4,7 +4,7 @@ add_executable(mylib-unit-tests test_main.cpp)
 target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp)
 target_link_libraries(mylib-unit-tests
     PRIVATE
-        Mylib::mylib
+        Mylib::myfeature
         doctest::doctest
 )

Virsraksti (Mylib::mylib) tagad jums nav nepieciešams atsevišķi izveidot savienojumu, jo, kā jau minēts, tie tiek automātiski savienoti kopā ar bibliotēku (Mylib::myfeature).

Un pievienosim dažas nianses, lai nodrošinātu pārklājuma mērījumus, ņemot vērā tikko ienākošo bibliotēku:

@@ -15,11 +15,16 @@ if(MYLIB_COVERAGE AND GCOVR_EXECUTABLE)
     target_compile_options(mylib-unit-tests PRIVATE --coverage)
     target_link_libraries(mylib-unit-tests PRIVATE gcov)

+    target_compile_options(myfeature PRIVATE --coverage)
+    target_link_libraries(myfeature PRIVATE gcov)
+
     add_custom_target(coverage
         COMMAND
             ${GCOVR_EXECUTABLE}
-                --root=${PROJECT_SOURCE_DIR}/include/
-                --object-directory=${CMAKE_CURRENT_BINARY_DIR}
+                --root=${PROJECT_SOURCE_DIR}/
+                --filter=${PROJECT_SOURCE_DIR}/include
+                --filter=${PROJECT_SOURCE_DIR}/src
+                --object-directory=${PROJECT_BINARY_DIR}
         DEPENDS
             check
     )

Varat pievienot vairāk bibliotēku, izpildāmos failus utt. Nav svarīgi, cik precīzi tie ir saistīti viens ar otru projekta ietvaros. Vienīgais svarīgais ir tas, kuri mērķi ir mūsu moduļa saskarne, tas ir, tie izceļas.

Iekarot

Tagad mums ir standarta bloku moduļi, un mēs varam tajos dominēt: izveidot tos jebkuras sarežģītības struktūrā, instalējot tos sistēmā vai savienojot tos vienā montāžas sistēmā.

Uzstādīšana sistēmā

Viena no moduļa izmantošanas iespējām ir mūsu moduļa instalēšana sistēmā.

cmake --build путь/к/сборочной/директории --target install

Pēc tam tas tiek savienots ar jebkuru citu projektu, izmantojot komandu find_package.

find_package(Mylib 1.0 REQUIRED)

Savienojums kā apakšmodulis

Vēl viena iespēja ir savienot mapi ar mūsu projektu ar citu projektu kā apakšmoduli, izmantojot komandu add_subdirectory.

Izmantot

Iesiešanas metodes ir dažādas, bet rezultāts ir vienāds. Abos gadījumos mērķi būs pieejami projektā, izmantojot mūsu moduli Mylib::myfeature и Mylib::mylib, ko var izmantot, piemēram, šādi:

add_executable(some_executable some.cpp sources.cpp)
target_link_libraries(some_executable PRIVATE Mylib::myfeature)

Konkrēti mūsu gadījumā — bibliotēka Mylib::myfeature jābūt savienotam, ja nepieciešams izveidot saiti ar bibliotēku libmyfeature. Ja galvenes ir pietiekami daudz, tad ir vērts izmantot bibliotēku Mylib::mylib.

CMake mērķi var būt sarežģīti, piemēram, paredzēti tikai dažu rekvizītu, atkarību utt. pārsūtīšanai. Tajā pašā laikā darbs ar viņiem notiek tādā pašā veidā.

Tas ir tas, ko mums vajadzēja iegūt.

Avots: www.habr.com

Pievieno komentāru