C++ și CMake – frați pentru totdeauna, partea II

C++ și CMake – frați pentru totdeauna, partea II

În partea anterioară Această poveste captivantă vorbește despre organizarea unei biblioteci de antet în cadrul generatorului de sisteme de construcție CMake.

De data aceasta, vom adăuga o bibliotecă compilabilă și vom discuta despre conectarea modulelor între ele.

Ca și înainte, cei care nu pot aștepta pot trece imediat la repozitorul actualizat și să experimenteze totul pe cont propriu.


Cuprins

  1. Separați
  2. Dominați

Separați

Primul lucru pe care trebuie să-l facem pentru a atinge obiectivul nostru înalt este să separăm software-ul dezvoltat în blocuri universale izolate, uniforme din punct de vedere al utilizatorului.

În prima parte a fost descris un astfel de bloc standard — un proiect cu bibliotecă de antet. Acum vom adăuga o bibliotecă compilabilă în proiectul nostru.

Pentru aceasta, vom scoate implementarea funcției myfunc într-un .cpp-fișier:

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

         ~  vezi 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 
+
+namespace mylib
+{
+    bool myfunc (mystruct)
+    {
+        return true;
+    }
+}

Apoi, vom defini biblioteca compilabilă (myfeature), care va consta din fișierul obținut la pasul anterior. Noua bibliotecă necesită, evident, antetele deja existente, iar pentru a asigura acest lucru, trebuie să o conectăm cu utilizarea existentă .cppmylib . De asemenea, legătura dintre ele este publică, ceea ce înseamnă că tot ceea ce va fi conectat la țintă, va obține automat și ținta myfeaturedetalii despre metodele de conectare . De asemenea, legătura dintre ele este publică, ceea ce înseamnă că tot ceea ce va fi conectat la țintă (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)+################################################################################################### +## +## Biblioteca compilabilă +## +################################################################################################### + +add_library(myfeature src/mylib/myfeature.cpp) +target_link_libraries(myfeature PUBLIC mylib) + +add_library(Mylib::myfeature ALIAS myfeature) +).

Apoi, vom face ca noua bibliotecă să fie instalată și în sistem:

@@ -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)

Trebuie să subliniem că pentru țintă

, la fel ca pentru myfeature, как и для . De asemenea, legătura dintre ele este publică, ceea ce înseamnă că tot ceea ce va fi conectat la țintă a fost creat un pseudonim cu prefixul Mylib::. Același lucru este specificat pentru ambele scopuri la exportarea acestora pentru instalarea în sistem. Aceasta oferă posibilitatea de a lucra uniform cu scopurile în orice schemă de legare.

După aceasta, a mai rămas să conectăm testele modulare cu noua bibliotecă (funcția myfunc a fost scoasă din antet, așa că acum trebuie să ne legăm):

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
 )

Antetele (Mylib::mylib) acum nu mai trebuie legate separat, deoarece, așa cum s-a spus deja, acestea sunt conectate automat împreună cu biblioteca (Mylib::myfeature).

Și să adăugăm câteva detalii pentru a asigura măsurarea acoperirii având în vedere biblioteca recent sosită:

@@ -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
     )

Putem adăuga mai multe biblioteci, fișiere executabile etc. În acest caz, nu contează cum sunt legate între ele în cadrul proiectului. Este important doar ce scopuri sunt interfața modulului nostru, adică expuse extern.

Dominați

Acum avem module-bloc standard și putem să le supunem controlului: să construim o structură de orice complexitate din ele, instalându-le în sistem sau legându-le între ele într-un sistem de construire unitar.

Instalare în sistem

Una dintre variantele de utilizare a modulului este instalarea modulului nostru în sistem.

cmake --build cale/către/directoria/de/construcție --target install

După aceasta, acesta se conectează la orice alt proiect cu comanda find_package.

find_package(Mylib 1.0 REQUIRED)

Conectare ca submodul

O altă variantă este conectarea folderului cu proiectul nostru la un alt proiect ca submodul folosind comanda add_subdirectory.

Utilizare

Modalitățile de legare sunt diferite, dar rezultatul este același. În ambele cazuri, în proiectul care utilizează modulul nostru, vor fi disponibile scopuri Mylib::myfeature și Mylib::mylib, care pot fi utilizate, de exemplu, astfel:

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

Concret în cazul nostru, biblioteca Mylib::myfeature trebuie conectată atunci când este necesar să se lipească cu biblioteca libmyfeature. Dacă sunt suficiente header-e, atunci merită să folosești biblioteca Mylib::mylib.

Obiectivele CMake pot fi sofisticate, de exemplu, destinate doar pentru a transmite anumite proprietăți, dependențe etc. Totuși, lucrul cu ele se face într-un mod unitar.

Ce și era necesar să obținem.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster