C++ dan CMake - bersaudara selamanya, bagian II

C++ dan CMake - bersaudara selamanya, bagian II

Di bagian sebelumnya Kisah menghibur ini berbicara tentang pengorganisasian perpustakaan header dalam generator sistem build CMake.

Kali ini kita akan menambahkan perpustakaan terkompilasi ke dalamnya, dan juga berbicara tentang menghubungkan modul satu sama lain.

Seperti tadi, yang tidak sabar bisa langsung buka repositori yang diperbarui dan sentuh semuanya dengan tanganmu sendiri.


kadar

  1. Membagi
  2. Menaklukkan

Membagi

Hal pertama yang perlu kita lakukan untuk mencapai tujuan luhur kita adalah membagi perangkat lunak yang kita kembangkan menjadi blok-blok universal dan terisolasi yang seragam dari sudut pandang pengguna.

Bagian pertama menjelaskan blok standar seperti itu - sebuah proyek dengan perpustakaan header. Sekarang mari tambahkan perpustakaan terkompilasi ke proyek kita.

Untuk melakukan ini, mari kita lakukan implementasi fungsinya myfunc secara terpisah .cpp-mengajukan:

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

Kemudian kita mendefinisikan perpustakaan yang akan dikompilasi (myfeature), yang terdiri dari apa yang diperoleh pada langkah sebelumnya .cpp-mengajukan. Perpustakaan baru jelas memerlukan header yang ada, dan untuk menyediakannya, perpustakaan dapat dan harus dikaitkan dengan tujuan yang ada mylib. Apalagi hubungan di antara mereka bersifat publik, artinya segala sesuatu yang menjadi target akan terhubung myfeature, secara otomatis akan menerima beban dan target mylib (lebih lanjut tentang metode merajut).

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

Selanjutnya, kami akan memastikan bahwa perpustakaan baru juga terinstal di sistem:

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

Perlu dicatat bahwa untuk tujuan tersebut myfeature, adapun mylib alias dengan awalan telah dibuat Mylib::. Hal yang sama ditulis untuk kedua tujuan saat mengekspornya untuk instalasi pada sistem. Hal ini memungkinkan untuk bekerja secara seragam dengan tujuan apa pun skema pengikatan.

Setelah ini, yang tersisa hanyalah menghubungkan pengujian unit dengan perpustakaan baru (function myfunc diambil dari judulnya, jadi sekarang Anda perlu menautkan):

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
 )

Judul (Mylib::mylib) sekarang Anda tidak perlu terhubung secara terpisah, karena seperti yang telah disebutkan, mereka secara otomatis terhubung dengan perpustakaan (Mylib::myfeature).

Dan mari tambahkan beberapa nuansa untuk memastikan pengukuran cakupan dengan mempertimbangkan perpustakaan yang baru hadir:

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

Anda dapat menambahkan lebih banyak perpustakaan, executable, dll. Tidak peduli bagaimana tepatnya mereka terhubung satu sama lain dalam proyek. Satu-satunya hal yang penting adalah target mana yang menjadi antarmuka modul kita, yaitu target yang menonjol.

Menaklukkan

Sekarang kami memiliki modul blok standar, dan kami dapat mendominasinya: menyusunnya menjadi struktur dengan kompleksitas apa pun, memasangnya ke dalam suatu sistem, atau menghubungkannya bersama-sama dalam satu sistem perakitan.

Instalasi ke dalam sistem

Salah satu opsi untuk menggunakan modul ini adalah dengan menginstal modul kami ke dalam sistem.

cmake --build ΠΏΡƒΡ‚ΡŒ/ΠΊ/сборочной/Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ --target install

Setelah itu, terhubung ke proyek lain menggunakan perintah find_package.

find_package(Mylib 1.0 REQUIRED)

Koneksi sebagai submodul

Pilihan lainnya adalah menghubungkan folder dengan proyek kita ke proyek lain sebagai submodul menggunakan perintah add_subdirectory.

Menggunakan

Cara mengikatnya berbeda-beda, tetapi hasilnya sama. Dalam kedua kasus tersebut, tujuan akan tersedia dalam proyek menggunakan modul kami Mylib::myfeature ΠΈ Mylib::mylib, yang dapat digunakan misalnya seperti ini:

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

Khususnya dalam kasus kami, perpustakaan Mylib::myfeature perlu dihubungkan ketika diperlukan untuk menghubungkan dengan perpustakaan libmyfeature. Jika headernya cukup, maka ada baiknya menggunakan perpustakaan Mylib::mylib.

Target CMake bisa jadi rumit, misalnya, dimaksudkan hanya untuk meneruskan beberapa properti, dependensi, dll. Pada saat yang sama, bekerja dengan mereka terjadi dengan cara yang sama.

Itulah yang perlu kami dapatkan.

Sumber: www.habr.com

Tambah komentar