C++ och CMake - bröder för alltid, del II

C++ och CMake - bröder för alltid, del II

I föregående del Den här underhållande historien talade om att organisera ett rubrikbibliotek inom CMake build-systemgeneratorn.

Den här gången kommer vi att lägga till ett sammanställt bibliotek till det, och även prata om att länka moduler med varandra.

Som tidigare kan den som är otålig direkt gå till det uppdaterade arkivet och rör allt med dina egna händer.


Innehåll

  1. Dela upp
  2. Erövra

Dela upp

Det första vi behöver göra för att uppnå vårt höga mål är att dela upp mjukvaran vi utvecklar i universella, isolerade block som är enhetliga ur användarens synvinkel.

I den första delen beskrevs ett sådant standardblock - ett projekt med ett header-bibliotek. Låt oss nu lägga till ett kompilerat bibliotek till vårt projekt.

För att göra detta, låt oss ta bort implementeringen av funktionen myfunc i en separat .cpp-fil:

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

Sedan definierar vi biblioteket som ska kompileras (myfeature), som kommer att bestå av det som erhölls i föregående steg .cpp-fil. Det nya biblioteket kräver uppenbarligen befintliga rubriker, och för att tillhandahålla detta kan och bör det kopplas till det befintliga syftet mylib. Dessutom är kopplingen mellan dem offentlig, vilket innebär att allt som målet kommer att kopplas till myfeature, kommer automatiskt att ta emot belastningen och målet mylib (mer om stickmetoder).

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

Därefter ser vi till att det nya biblioteket också är installerat på systemet:

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

Det bör noteras att för ändamålet myfeature, som för mylib ett alias med ett prefix skapades Mylib::. Detsamma skrivs för båda ändamålen när man exporterar dem för installation på systemet. Detta gör det möjligt att arbeta enhetligt med mål för eventuella bindande schema.

Efter detta återstår bara att koppla enhetstester med det nya biblioteket (funktion myfunc tagits ur titeln, så nu måste du länka):

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
 )

Rubriker (Mylib::mylib) nu behöver du inte ansluta separat, eftersom de, som redan nämnts, ansluts automatiskt tillsammans med biblioteket (Mylib::myfeature).

Och låt oss lägga till ett par nyanser för att säkerställa täckningsmätningar med hänsyn till det nyinkomna biblioteket:

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

Du kan lägga till fler bibliotek, körbara filer etc. Det spelar ingen roll hur exakt de är kopplade till varandra inom projektet. Det enda viktiga är vilka mål som är gränssnittet i vår modul, det vill säga de sticker ut.

Erövra

Nu har vi standardblockmoduler, och vi kan dominera dem: komponera dem till en struktur av vilken komplexitet som helst, installera dem i ett system eller länka ihop dem i ett enda monteringssystem.

Installation i systemet

Ett av alternativen för att använda modulen är att installera vår modul i systemet.

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

Efter det kopplas den till vilket annat projekt som helst med kommandot find_package.

find_package(Mylib 1.0 REQUIRED)

Anslutning som undermodul

Ett annat alternativ är att koppla mappen med vårt projekt till ett annat projekt som en undermodul med kommandot add_subdirectory.

Använd

Bindningsmetoderna är olika, men resultatet är detsamma. I båda fallen kommer mål att vara tillgängliga i projektet med hjälp av vår modul Mylib::myfeature и Mylib::mylib, som till exempel kan användas så här:

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

Närmare bestämt i vårt fall, biblioteket Mylib::myfeature måste anslutas när det är nödvändigt att länka till biblioteket libmyfeature. Om det finns tillräckligt med rubriker är det värt att använda biblioteket Mylib::mylib.

CMake-mål kan vara knepiga, till exempel avsedda att endast vidarebefordra vissa egenskaper, beroenden, etc. Samtidigt sker arbetet med dem på samma sätt.

Det var vad vi behövde få.

Källa: will.com

Lägg en kommentar