C++ ve CMake - sonsuza kadar kardeşler, bölüm II

C++ ve CMake - sonsuza kadar kardeşler, bölüm II

Önceki bölümde Bu eğlenceli hikaye, CMake yapı sistemi oluşturucusu içinde bir başlık kütüphanesinin düzenlenmesinden bahsediyordu.

Bu sefer içine derlenmiş bir kütüphane ekleyeceğiz ve ayrıca modüllerin birbirine bağlanmasından da bahsedeceğiz.

Daha önce olduğu gibi sabırsız olanlar hemen yapabilirler. güncellenen depoya git ve her şeye kendi ellerinizle dokunun.


Içerik

  1. Bölmek
  2. Fethetmek

Bölmek

Yüce hedefimize ulaşmak için yapmamız gereken ilk şey, geliştirdiğimiz yazılımı kullanıcı açısından tekdüze, evrensel, yalıtılmış bloklara bölmektir.

İlk bölümde böyle standart bir blok tanımlandı - başlık kütüphanesine sahip bir proje. Şimdi projemize derlenmiş bir kütüphane ekleyelim.

Bunu yapmak için fonksiyonun uygulamasını çıkaralım. myfunc ayrı olarak .cpp-dosya:

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

Daha sonra derlenecek kütüphaneyi tanımlıyoruz (myfeature), önceki adımda elde edilenlerden oluşacaktır .cpp-dosya. Yeni kütüphanenin mevcut başlıklara ihtiyacı olduğu açıktır ve bunu sağlamak için mevcut amaca bağlanabilir ve bağlanmalıdır. mylib. Üstelik aralarındaki bağlantı halka açıktır, bu da hedefin bağlanacağı her şeyin olduğu anlamına gelir. myfeature, yükü ve hedefi otomatik olarak alacak mylib (örgü yöntemleri hakkında daha fazla bilgi).

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

Daha sonra yeni kütüphanenin de sisteme kurulu olduğundan emin olacağız:

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

Şunu belirtmek gerekir ki, bu amaç için myfeature, gelince mylib öneki olan bir takma ad oluşturuldu Mylib::. Sisteme kurulum için dışa aktarırken her iki amaç için de aynı şey yazılır. Bu, herhangi bir hedef için aynı şekilde çalışmayı mümkün kılar. bağlama şeması.

Bundan sonra geriye kalan tek şey birim testlerini yeni kütüphaneye bağlamaktır (fonksiyon myfunc başlıktan çıkarıldı, bu yüzden şimdi bağlantı vermeniz gerekiyor):

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
 )

Başlıklar (Mylib::mylib) artık ayrı olarak bağlanmanıza gerek yok, çünkü daha önce de belirtildiği gibi, kitaplıkla birlikte otomatik olarak bağlanırlar (Mylib::myfeature).

Yeni gelen kütüphaneyi dikkate alarak kapsam ölçümlerini sağlamak için birkaç nüans ekleyelim:

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

Daha fazla kitaplık, yürütülebilir dosya vb. ekleyebilirsiniz. Proje içerisinde birbirlerine tam olarak nasıl bağlandıkları önemli değildir. Önemli olan tek şey hangi hedeflerin modülümüzün arayüzü olduğu, yani öne çıktığıdır.

Fethetmek

Artık standart blok modüllerimiz var ve onlara hakim olabiliriz: bunları herhangi bir karmaşıklıktaki yapıda birleştirebilir, bir sisteme kurabilir veya tek bir montaj sistemi içinde birbirine bağlayabiliriz.

Sisteme kurulum

Modülü kullanma seçeneklerinden biri modülümüzü sisteme kurmaktır.

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

Bundan sonra komutu kullanarak başka bir projeye bağlanır. find_package.

find_package(Mylib 1.0 REQUIRED)

Alt modül olarak bağlantı

Diğer bir seçenek ise projemizin bulunduğu klasörü aşağıdaki komutu kullanarak başka bir projeye alt modül olarak bağlamaktır. add_subdirectory.

kullanımı

Bağlama yöntemleri farklıdır ancak sonuç aynıdır. Her iki durumda da hedefler modülümüzü kullanarak projede mevcut olacaktır. Mylib::myfeature и Mylib::mylibörneğin şu şekilde kullanılabilir:

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

Özellikle bizim durumumuzda kütüphane Mylib::myfeature Kütüphaneye bağlanmak gerektiğinde bağlanmak gerekir libmyfeature. Yeterli başlık varsa, kütüphaneyi kullanmaya değer Mylib::mylib.

CMake hedefleri yanıltıcı olabilir; örneğin yalnızca bazı özellikleri, bağımlılıkları vb. iletmeyi amaçlayabilir. Aynı zamanda onlarla çalışmak da aynı şekilde gerçekleşir.

Almamız gereken şey buydu.

Kaynak: habr.com

Yorum ekle