
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 und alles mit eigenen HÀnden ausprobieren.
Inhalt
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 ().
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 .
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.
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 installDanach kann es in jedem anderen Projekt mit dem Befehl .
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 .
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
