C++ en CMake — broers voor altijd, deel II

C++ en CMake — broers voor altijd, deel II

In het vorige deel van dit boeiende verhaal werd gesproken over het organiseren van een headerbibliotheek binnen de CMake build system generator.

Deze keer voegen we een compileerbare bibliotheek toe en bespreken we de samenvoeging van modules met elkaar.

Zoals altijd kunnen degenen die niet kunnen wachten meteen overstappen naar de bijgewerkte repository en alles zelf uitproberen.


Inhoud

  1. Scheiding
  2. Heers

Scheiding

Het eerste wat gedaan moet worden om ons hoge doel te bereiken, is de te ontwikkelen software op te splitsen in universele, geĆÆsoleerde blokken die uniform zijn vanuit het gebruikersperspectief.

In het eerste deel werd zo'n standaard blok beschreven: een project met een headerbibliotheek. Nu voegen we een compileerbare bibliotheek toe aan ons project.

Daarvoor brengen we de implementatie van de functie myfunc over naar een aparte .cpp-bestand:

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

         ~  zie 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;
+    }
+}

Daarna definiƫren we de compileerbare bibliotheek (myfeature), die zal bestaan uit het op de vorige stap verkregen .cpp-bestand. De nieuwe bibliotheek heeft duidelijk bestaande headers nodig, en om dit te waarborgen kunnen en moeten we deze verbinden met de bestaande doel mylib. Bovendien is de verbinding tussen hen openbaar, wat betekent dat alles waaraan de doelstelling myfeature, automatisch zal beschikken over de doel mylib (verder over verbindingsmethoden).

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)

+###################################################################################################
+##
+##      Compileerbare bibliotheek
+##
+###################################################################################################
+
+add_library(myfeature src/mylib/myfeature.cpp)
+target_link_libraries(myfeature PUBLIC mylib)
+
+add_library(Mylib::myfeature ALIAS myfeature)
+

Vervolgens zorgen we ervoor dat de nieuwe bibliotheek ook in het systeem wordt geĆÆnstalleerd:

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

Let op dat voor de doelstelling myfeature, net als voor mylib werd een pseudoniem met de prefix Mylib::. Hetzelfde is ingesteld voor beide doelen bij het exporteren naar de installatiesystemen. Dit biedt de mogelijkheid voor uniforme werking met doelen, ongeacht de bindschema.

Daarna moeten de moduletests worden verbonden met de nieuwe bibliotheek (de functie myfunc is uit de header gehaald, dus nu moet er gelinkt worden):

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
 )

Headers (Mylib::mylib) hoeven nu niet meer apart te worden geĆÆmporteerd, omdat, zoals eerder vermeld, ze automatisch samen met de bibliotheek worden geĆÆmporteerd (Mylib::myfeature).

En laten we een paar nuances toevoegen om de dekkingseisen rekening te houden met de nieuw binnengekomen bibliotheek:

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

Je kunt meer bibliotheken, uitvoerbare bestanden, enz. toevoegen. En het maakt niet uit hoe ze in het project zijn verbonden. Het enige dat telt zijn de doelen die de interface van onze module vormen, dat wil zeggen wat er naar buiten steekt.

Heers

Nu hebben we standaard moduleblokken en kunnen we daarover heersen: een structuur van elke complexiteit opbouwen, ze in het systeem installeren of binnen het kader van een enkele build-systeem met elkaar verbinden.

Installatie in het systeem

Een van de gebruiksmogelijkheden voor de module is om onze module in het systeem te installeren.

cmake --build pad/naar/build/map --target install

Daarna kan deze in elk ander project worden aangesloten met het commando find_package.

find_package(Mylib 1.0 REQUIRED)

Aansluiting als submodule

Een andere optie is om de map met ons project als submodule aan een ander project toe te voegen met het commando add_subdirectory.

Gebruik van

Er zijn verschillende manieren van linken, maar het resultaat is hetzelfde. In beide gevallen zijn de doelen beschikbaar in het project dat onze module gebruikt. Mylib::myfeature en Mylib::mylib, die bijvoorbeeld zo kunnen worden gebruikt:

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

Specifiek in ons geval de bibliotheek Mylib::myfeature moet worden gekoppeld wanneer het nodig is om met de bibliotheek te linken libmyfeature. Als de headerbestanden voldoende zijn, is het dan de moeite waard om de bibliotheek te gebruiken Mylib::mylib.

CMake-doelen kunnen slim zijn, bijvoorbeeld bedoeld om bepaalde eigenschappen, afhankelijkheden, enz. door te geven. Het werken met hen gebeurt op een uniforme manier.

Wat we wilden bereiken.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster