C ++ und CMake - Brothers Forever, Teil II

Freundschaft für immer


Im vorherigen Teil dieser unterhaltsamen Geschichte haben wir über das Organisieren einer Header-Bibliothek als Teil des CMake-Assembly-System-Generators gesprochen.


Dieses Mal fügen wir eine kompilierte Bibliothek hinzu und sprechen auch über das Layout der Module miteinander.


Nach wie vor können diejenigen, die nicht warten können, sofort zum aktualisierten Repository gehen und alles mit ihren eigenen Händen berühren.


Inhalt


  1. Teilen
  2. Erobern


Teilen


Das erste, was Sie tun müssen, um unser hohes Ziel zu erreichen, besteht darin, die in der Entwicklung befindliche Software in universelle isolierte Blöcke zu unterteilen, die aus Sicht des Benutzers einheitlich sind.


Der erste Teil beschrieb einen solchen Standardblock - ein Projekt mit einer Header-Bibliothek. Fügen wir nun unserem Projekt eine kompilierte Bibliothek hinzu.


Dazu nehmen wir die Implementierung der Funktion myfunc in einer separaten .cpp Datei heraus:


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

Dann definieren wir die kompilierte Bibliothek ( myfeature ), die aus der im vorherigen Schritt erhaltenen .cpp Datei besteht. Die neue Bibliothek erfordert offensichtlich vorhandene Header, und um dies sicherzustellen, ist es möglich und notwendig, sie mit dem vorhandenen Zweck von mylib zu stricken. Darüber hinaus ist die Verbindung zwischen ihnen öffentlich, was bedeutet, dass alles, mit dem das myfeature Ziel verbunden myfeature automatisch das mylib Ziel in der Last mylib ( mehr zum mylib einer Verbindung ).


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

Als nächstes werden wir die neue Bibliothek auch auf dem 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 sowohl für myfeature als auch für mylib ein Alias ​​mit dem Präfix Mylib:: vorangestellt wurde. Dasselbe wird für beide Zwecke angegeben, wenn sie zur Installation im System exportiert werden. Dies ermöglicht es, für jedes Verknüpfungsschema einheitlich mit Zielen zu arbeiten.


Danach müssen noch Unit-Tests mit der neuen Bibliothek gestrickt werden (die myfunc Funktion wurde aus dem Header entfernt, daher müssen Sie jetzt eine Verknüpfung herstellen):


 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 ) 

Header ( Mylib::mylib ) müssen jetzt nicht mehr separat verbunden werden, da sie, wie bereits erwähnt, automatisch mit der Bibliothek ( Mylib::myfeature ) verbunden werden.


Fügen Sie einige Nuancen hinzu, um die Abdeckungsmessungen unter Berücksichtigung der neu angekommenen Bibliothek sicherzustellen:


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

Sie können weitere Bibliotheken, ausführbare Dateien usw. hinzufügen. Es spielt keine Rolle, wie genau sie im Rahmen des Projekts zusammengestrickt werden. Das einzig Wichtige ist, welche Ziele die Schnittstelle unseres Moduls sind, dh herausragen.



Erobern


Jetzt haben wir Standardmodulblöcke, und wir können sie dominieren: eine Struktur beliebiger Komplexität daraus bilden, sie in einem System installieren oder sie in einem einzigen Montagesystem miteinander verbinden.


Systeminstallation


Eine der Optionen für die Verwendung des Moduls besteht darin, unser Modul im System zu installieren.


 cmake --build /// --target install 

Danach wird mit dem find_package Verbindung zu einem anderen Projekt find_package .


 find_package(Mylib 1.0 REQUIRED) 

Verbindung als Submodul


Eine andere Möglichkeit besteht darin, den Ordner mit unserem Projekt mit dem add_subdirectory als Submodul mit einem anderen Projekt zu verbinden.


Verwenden Sie


Die Bindungsmethoden sind unterschiedlich, aber das Ergebnis ist das gleiche. In beiden Fällen stehen in einem Projekt mit unserem Modul die Ziele Mylib::myfeature und Mylib::mylib zur Verfügung, die beispielsweise wie Mylib::mylib werden können:


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

In unserem Fall muss die Mylib::myfeature verbunden werden, wenn eine libmyfeature Bibliothek erforderlich ist. Wenn genügend Header vorhanden sind, sollten Sie die Mylib::mylib Bibliothek verwenden.


CMake-Ziele können schwierig sein, z. B. nur zum Weiterleiten einiger Eigenschaften, Abhängigkeiten usw. Gleichzeitig erfolgt die Arbeit mit ihnen auf eine einzige Weise.


Was war erforderlich, um zu erhalten.

Source: https://habr.com/ru/post/de463295/


All Articles