C++ und CMake – BrĂŒder fĂŒr immer, Teil II

C++ und CMake – BrĂŒder fĂŒr immer, Teil II

Im vorherigen Teil In dieser spannenden ErzÀhlung ging es um die Organisation einer Header-Bibliothek im Rahmen des CMake-Build-Systems.

Diesmal fĂŒgen wir eine kompilierbare Bibliothek hinzu und sprechen auch ĂŒber die Anordnung der Module untereinander.

Wie immer können die Ungeduldigen sofort zum aktualisierten Repository wechseln und alles mit eigenen HÀnden ausprobieren.


Inhalt

  1. Teile
  2. Herrsche

Teile

Das erste, was wir tun mĂŒssen, um unser hohes Ziel zu erreichen, ist, die zu entwickelnde Software in universelle isolierte Blöcke zu unterteilen, die aus Sicht des Benutzers einheitlich sind.

Im ersten Teil wurde ein solcher Standardblock beschrieben - ein Projekt mit einer Header-Bibliothek. Jetzt fĂŒgen wir unserem Projekt eine kompilierbare Bibliothek hinzu.

Dazu ziehen wir die Implementierung der Funktion myfunc in eine separate .cpp-Datei:

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

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

Dann definieren wir die kompilierbare Bibliothek (myfeature), die aus der zuvor erhaltenen .cpp-Datei bestehen wird. Offensichtlich benötigt die neue Bibliothek bereits vorhandene Header, und um dies zu gewÀhrleisten, sollte sie mit dem bestehenden Ziel mylibverkoppelt werden. Die Verkoppelung zwischen ihnen ist öffentlich, was bedeutet, dass alles, was mit dem Ziel verbunden wird, automatisch auch das Ziel erhÀlt. myfeatureWeitere Informationen zu den Verkoppelungsmöglichkeiten mylib (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)+################################################################################################### +## +## Kompilierbare Bibliothek +## +################################################################################################### + +add_library(myfeature src/mylib/myfeature.cpp) +target_link_libraries(myfeature PUBLIC mylib) + +add_library(Mylib::myfeature ALIAS myfeature) +).

Dann lassen wir die neue Bibliothek ebenfalls im System installieren:

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

Es ist zu beachten, dass fĂŒr das Ziel

, wie auch fĂŒr myfeature, wie auch fĂŒr mylib Es wurde ein Pseudonym mit einem PrĂ€fix eingerichtet Mylib::. Dasselbe ist fĂŒr beide Ziele beim Exportieren in das System festgelegt. Dies ermöglicht eine einheitliche Arbeit mit den Zielen bei jeder Bindungsstruktur.

Danach blieb es, die Modultests mit der neuen Bibliothek zu verknĂŒpfen (die Funktion myfunc wurde aus dem Header herausgenommen, sodass jetzt eine Verlinkung erforderlich ist):

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
 )

Die Header (Mylib::mylib) mĂŒssen jetzt nicht mehr separat eingebunden werden, da sie, wie bereits erwĂ€hnt, automatisch mit der Bibliothek eingebunden werden (Mylib::myfeature).

Und wir fĂŒgen ein paar Nuancen hinzu, um die Messungen der Codeabdeckung unter BerĂŒcksichtigung der neu hinzugekommenen Bibliothek zu gewĂ€hrleisten:

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

Es können weitere Bibliotheken, ausfĂŒhrbare Dateien usw. hinzugefĂŒgt werden. Dabei ist es unwichtig, wie sie im Rahmen des Projekts miteinander verknĂŒpft sind. Wichtig ist nur, welche Ziele als Schnittstelle unseres Moduls fungieren, also nach außen sichtbar sind.

Herrsche

Jetzt haben wir Standardmodul-Blöcke, und wir können sie beherrschen: Sie zu einer beliebigen komplexen Struktur zusammenzustellen, sie im System zu installieren oder sie innerhalb eines gemeinsamen Build-Systems zu verlinken.

Installation im System

Eine Möglichkeit, das Modul zu nutzen — unser Modul im System zu installieren.

cmake --build pfad/zum/build/verzeichnis --target install

Danach kann es in jedem anderen Projekt mit dem Befehl find_package.

find_package(Mylib 1.0 REQUIRED)

Einbindung als Submodul

Eine andere Möglichkeit — den Ordner mit unserem Projekt im Rahmen eines anderen Projekts als Submodul mit dem Befehl einzubinden add_subdirectory.

Verwendung

Die Bindungsmethoden sind unterschiedlich, aber das Ergebnis ist dasselbe. In beiden FĂ€llen sind in dem Projekt, das unser Modul verwendet, die Ziele verfĂŒgbar Mylib::myfeature und Mylib::mylib, die beispielsweise so verwendet werden können:

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

Speziell in unserem Fall muss die Bibliothek Mylib::myfeature eingebunden werden, wenn es notwendig ist, sich mit der Bibliothek zu verlinken libmyfeature. Wenn nur die Header-Dateien ausreichend sind, sollte man die Bibliothek verwenden Mylib::mylib.

CMake-Ziele können trickreich sein, zum Beispiel nur dafĂŒr vorgesehen, um bestimmte Eigenschaften, AbhĂ€ngigkeiten usw. weiterzugeben. Der Umgang mit ihnen erfolgt dabei einheitlich.

Was gefordert war.

Quelle: habr.com

ZuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz kaufen, VPS VDS Server đŸ”„ ZuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz kaufen, VPS VDS Server - ProHoster