C++ kaj CMake - fratoj eterne, parto II

C++ kaj CMake - fratoj eterne, parto II

En la antaŭa parto Ĉi tiu amuza rakonto parolis pri organizado de kapbiblioteko ene de la CMake-konstrua sistemgeneratoro.

Ĉi-foje ni aldonos kompilitan bibliotekon al ĝi, kaj ankaŭ parolos pri ligado de moduloj unu kun la alia.

Kiel antaŭe, tiuj, kiuj estas senpaciencaj, povas tuj iru al la ĝisdatigita deponejo kaj tuŝu ĉion per viaj propraj manoj.


Enhavo

  1. Dividi
  2. Konkeri

Dividi

La unua afero, kiun ni devas fari por atingi nian altan celon, estas dividi la programaron, kiun ni evoluigas en universalajn, izolitajn blokojn, kiuj estas unuformaj el la vidpunkto de la uzanto.

En la unua parto estis priskribita tia norma bloko - projekto kun kapa biblioteko. Nun ni aldonu kompilitan bibliotekon al nia projekto.

Por fari tion, ni elprenu la efektivigon de la funkcio myfunc en aparta .cpp-dosiero:

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

Tiam ni difinas la kompilotan bibliotekon (myfeature), kiu konsistos el tio, kio estis akirita en la antaŭa paŝo .cpp-dosiero. La nova biblioteko evidente postulas ekzistantajn kapliniojn, kaj por provizi tion, ĝi povas kaj devas esti ligita al la ekzistanta celo mylib. Krome, la ligo inter ili estas publika, kio signifas, ke ĉio al kio la celo estos konektita myfeature, aŭtomate ricevos la ŝarĝon kaj celon mylib (pli pri trikaj metodoj).

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

Poste, ni certigos, ke la nova biblioteko ankaŭ estas instalita en la sistemo:

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

Oni notu, ke tiucele myfeature, kiel por mylib kaŝnomo kun prefikso estis kreita Mylib::. La sama estas skribita por ambaŭ celoj kiam ili eksportas por instalado en la sistemo. Ĉi tio ebligas labori unuforme kun celoj por iu ajn liga skemo.

Post tio, restas nur ligi unutestojn kun la nova biblioteko (funkcio myfunc forprenita el la titolo, do nun vi devas ligi):

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
 )

Titoloj (Mylib::mylib) nun vi ne bezonas aparte konektiĝi, ĉar, kiel jam menciite, ili estas aŭtomate konektitaj kune kun la biblioteko (Mylib::myfeature).

Kaj ni aldonu kelkajn nuancojn por certigi kovrajn mezuradojn konsiderante la ĵusalvenitan bibliotekon:

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

Vi povas aldoni pli da bibliotekoj, ruleblaj, ktp. Ne gravas kiom precize ili estas konektitaj unu al la alia ene de la projekto. La sola grava afero estas, kiuj celoj estas la interfaco de nia modulo, tio estas, ili elstaras.

Konkeri

Nun ni havas normajn blokmodulojn, kaj ni povas regi ilin: kunmeti ilin en strukturon de ajna komplekseco, instalante ilin en sistemon aŭ kunligante ilin ene de ununura ensambla sistemo.

Instalado en la sistemon

Unu el la ebloj por uzi la modulon estas instali nian modulon en la sistemon.

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

Post tio, ĝi estas konektita al iu ajn alia projekto uzante la komandon find_package.

find_package(Mylib 1.0 REQUIRED)

Konekto kiel submodulo

Alia eblo estas konekti la dosierujon kun nia projekto al alia projekto kiel submodulo uzante la komandon add_subdirectory.

Uzo

La ligaj metodoj estas malsamaj, sed la rezulto estas la sama. En ambaŭ kazoj, celoj estos disponeblaj en la projekto uzante nian modulon Mylib::myfeature и Mylib::mylib, kiu povas esti uzata, ekzemple, jene:

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

Specife en nia kazo, la biblioteko Mylib::myfeature devas esti konektita kiam necesas ligi kun la biblioteko libmyfeature. Se estas sufiĉe da kaplinioj, tiam indas uzi la bibliotekon Mylib::mylib.

CMake-celoj povas esti malfacilaj, ekzemple, intencitaj nur por plusendi iujn ecojn, dependecojn, ktp. Samtempe, labori kun ili okazas en la sama maniero.

Tion ni bezonis akiri.

fonto: www.habr.com

Aldoni komenton