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

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

In het vorige deel Dit vermakelijke verhaal ging over het organiseren van een headerbibliotheek binnen de CMake-buildsysteemgenerator.

Deze keer zullen we er een gecompileerde bibliotheek aan toevoegen, en ook praten over het aan elkaar koppelen van modules.

Net als voorheen kunnen degenen die ongeduldig zijn onmiddellijk ga naar de bijgewerkte repository en raak alles met je eigen handen aan.


Inhoud

  1. Verdeling
  2. Veroveren

Verdeling

Het eerste wat we moeten doen om ons verheven doel te bereiken is de software die we ontwikkelen op te delen in universele, geΓ―soleerde blokken die uniform zijn vanuit het gezichtspunt van de gebruiker.

In het eerste deel werd zo'n standaardblok beschreven: een project met een headerbibliotheek. Laten we nu een gecompileerde bibliotheek aan ons project toevoegen.

Om dit te doen, nemen we de implementatie van de functie eruit myfunc in 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

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

Vervolgens definiΓ«ren we de te compileren bibliotheek (myfeature), die zal bestaan ​​uit wat in de vorige stap is verkregen .cpp-bestand. De nieuwe bibliotheek heeft uiteraard bestaande headers nodig, en om hierin te voorzien kan en moet deze aan het bestaande doel worden gekoppeld mylib. Bovendien is de verbinding daartussen openbaar, wat betekent dat alles waarmee het doelwit verbonden zal zijn myfeature, ontvangt automatisch de lading en het doel mylib (meer over breimethoden).

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

Vervolgens zorgen we ervoor dat de nieuwe bibliotheek ook op 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)

Opgemerkt moet worden dat voor het doel myfeature, wat betreft mylib er is een alias met een voorvoegsel gemaakt Mylib::. Hetzelfde is voor beide doeleinden geschreven bij het exporteren voor installatie op het systeem. Hierdoor is het mogelijk om uniform te werken met doelstellingen voor iedereen bindend schema.

Hierna rest alleen nog het koppelen van unittests aan de nieuwe bibliotheek (function myfunc uit de titel gehaald, dus nu moet je linken):

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
 )

Koppen (Mylib::mylib) nu hoef je niet apart verbinding te maken, omdat ze, zoals eerder vermeld, automatisch samen met de bibliotheek zijn verbonden (Mylib::myfeature).

En laten we een paar nuances toevoegen om dekkingsmetingen te garanderen, rekening houdend met de nieuw aangekomen 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
     )

U kunt meer bibliotheken, uitvoerbare bestanden, enz. toevoegen. Hoe ze binnen het project precies met elkaar verbonden zijn, maakt niet uit. Het enige belangrijke is welke doelen de interface van onze module zijn, dat wil zeggen dat ze uitsteken.

Veroveren

Nu hebben we standaard blokmodules, en we kunnen ze domineren: ze samenstellen tot een structuur van elke complexiteit, ze in een systeem installeren of ze aan elkaar koppelen binnen een enkel assemblagesysteem.

Installatie in het systeem

EΓ©n van de mogelijkheden om de module te gebruiken is om onze module in het systeem te installeren.

cmake --build ΠΏΡƒΡ‚ΡŒ/ΠΊ/сборочной/Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ --target install

Daarna wordt het met behulp van de opdracht verbonden met elk ander project 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 te koppelen met behulp van de opdracht add_subdirectory.

Gebruiken

De bindmethoden zijn verschillend, maar het resultaat is hetzelfde. In beide gevallen zullen doelen beschikbaar zijn in het project met behulp van onze module Mylib::myfeature ΠΈ Mylib::mylib, die bijvoorbeeld als volgt kan worden gebruikt:

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

In ons geval specifiek de bibliotheek Mylib::myfeature moeten verbonden zijn wanneer het nodig is om te koppelen met de bibliotheek libmyfeature. Als er voldoende headers zijn, is het de moeite waard om de bibliotheek te gebruiken Mylib::mylib.

CMake-doelen kunnen lastig zijn, bijvoorbeeld alleen bedoeld om bepaalde eigenschappen, afhankelijkheden, enz. door te geven. Tegelijkertijd gebeurt het werken met hen op dezelfde manier.

Dat is wat we moesten krijgen.

Bron: www.habr.com

Voeg een reactie