C++ i CMake - bracia na zawsze, część II

C++ i CMake - bracia na zawsze, część II

W poprzedniej części Ta zabawna historia mówiła o organizowaniu biblioteki nagłówków w generatorze systemu kompilacji CMake.

Tym razem dodamy do niego skompilowaną bibliotekę, a także porozmawiamy o łączeniu modułów ze sobą.

Tak jak poprzednio, niecierpliwi mogą natychmiast przejdź do zaktualizowanego repozytorium i dotykaj wszystkiego własnymi rękami.


Zawartość

  1. Dzielić
  2. Podbić

Dzielić

Pierwszą rzeczą, którą musimy zrobić, aby osiągnąć nasz wzniosły cel, jest podzielenie tworzonego przez nas oprogramowania na uniwersalne, izolowane bloki, jednolite z punktu widzenia użytkownika.

W pierwszej części został opisany taki standardowy blok – projekt z biblioteką nagłówkową. Dodajmy teraz skompilowaną bibliotekę do naszego projektu.

Aby to zrobić, usuńmy implementację funkcji myfunc w osobnym .cpp-plik:

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

Następnie definiujemy bibliotekę do skompilowania (myfeature), który będzie składał się z tego, co uzyskano w poprzednim kroku .cpp-plik. Nowa biblioteka oczywiście wymaga istniejących nagłówków i aby to zapewnić, może i powinna być powiązana z istniejącym przeznaczeniem mylib. Co więcej, połączenie między nimi jest publiczne, co oznacza, że ​​wszystko, do czego będzie podłączony cel myfeature, automatycznie otrzyma ładunek i cel mylib (więcej o metodach dziewiarskich).

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

Następnie upewnimy się, że nowa biblioteka jest również zainstalowana w systemie:

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

Warto zauważyć, że w tym celu myfeature, Jeśli chodzi o mylib utworzono alias z przedrostkiem Mylib::. To samo jest napisane dla obu celów podczas eksportowania ich do instalacji w systemie. Dzięki temu możliwa jest jednolita praca z celami dla każdego wiążący schemat.

Następnie pozostaje już tylko połączyć testy jednostkowe z nową biblioteką (function myfunc usunięte z tytułu, więc teraz musisz podać link):

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
 )

Nagłówki (Mylib::mylib) teraz nie trzeba łączyć się osobno, ponieważ jak już wspomniano, są one automatycznie łączone wraz z biblioteką (Mylib::myfeature).

Dodajmy jeszcze kilka niuansów, aby zapewnić pomiary zasięgu, biorąc pod uwagę nowo przybyłą bibliotekę:

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

Możesz dodać więcej bibliotek, plików wykonywalnych itp. Nie ma znaczenia, jak dokładnie są ze sobą połączone w ramach projektu. Ważne jest tylko to, które cele są interfejsem naszego modułu, czyli wystają.

Podbić

Teraz mamy standardowe moduły blokowe i możemy je zdominować: zestawiać je w konstrukcje o dowolnej złożoności, instalując je w systemie lub łącząc w ramach jednego systemu montażowego.

Instalacja w systemie

Jedną z możliwości wykorzystania modułu jest zainstalowanie naszego modułu w systemie.

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

Następnie jest on podłączony do dowolnego innego projektu za pomocą polecenia find_package.

find_package(Mylib 1.0 REQUIRED)

Podłączenie jako podmoduł

Inną opcją jest połączenie folderu z naszym projektem z innym projektem jako submoduł za pomocą polecenia add_subdirectory.

Używać

Metody wiązania są różne, ale wynik jest taki sam. W obu przypadkach cele będą dostępne w projekcie za pomocą naszego modułu Mylib::myfeature и Mylib::mylib, którego można użyć na przykład w ten sposób:

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

Konkretnie w naszym przypadku biblioteka Mylib::myfeature muszą być połączone, gdy konieczne jest połączenie z biblioteką libmyfeature. Jeśli nagłówków jest wystarczająco dużo, warto skorzystać z biblioteki Mylib::mylib.

Cele CMake mogą być trudne, na przykład przeznaczone tylko do przekazywania niektórych właściwości, zależności itp. Jednocześnie praca z nimi przebiega w ten sam sposób.

To właśnie musieliśmy zdobyć.

Źródło: www.habr.com

Dodaj komentarz