C++ 和 CMake - 永遠的兄弟,第二部分

C++ 和 CMake - 永遠的兄弟,第二部分

在上一部分中 這個有趣的故事講述了在 CMake 建置系統生成器中組織頭檔庫。

這次我們將向其中添加一個已編譯的庫,並討論模組之間的連結。

和以前一樣,那些不耐煩的人可以立即 轉到更新的儲存庫 並用自己的雙手觸摸一切。


Содержание

  1. 劃分
  2. 征服

劃分

為了實現我們的崇高目標,我們要做的第一件事就是將我們開發的軟體劃分為通用的、孤立的區塊,這些區塊從使用者的角度來看是統一的。

在第一部分中,描述了這樣一個標準區塊 - 一個帶有頭庫的項目。現在讓我們將編譯的函式庫加入我們的專案中。

為此,我們取出該函數的實現 myfunc 在一個單獨的 .cpp-文件:

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

然後我們定義要編譯的函式庫(myfeature),其中將包含上一步中獲得的內容 .cpp-文件。新庫顯然需要現有的標頭,為了提供這一點,它可以而且應該與現有的目的聯繫起來 mylib。而且,它們之間的連接是公共的,這意味著目標將連接到的所有內容 myfeature,將自動接收負載和目標 mylib (有關編織方法的更多信息).

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

接下來,我們將確保新庫也安裝在系統上:

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

需要注意的是,為了達到目的 myfeature,至於 mylib 創建了帶有前綴的別名 Mylib::。匯出它們以在系統上安裝時,為這兩個目的編寫了相同的內容。這使得能夠針對任何目標統一工作 綁定方案.

之後,剩下的就是將單元測試與新庫連結起來(函數 myfunc 從標題中取出,所以現在您需要連結):

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
 )

標題(Mylib::mylib)現在您不需要單獨連接,因為,正如已經提到的,它們會自動與庫一起連接(Mylib::myfeature).

讓我們添加一些細微差別,以確保覆蓋率測量考慮到新到達的庫:

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

您可以新增更多函式庫、執行檔等。它們在專案中如何精確地相互連接並不重要。唯一重要的是哪些目標是我們模組的接口,也就是說,它們是突出的。

征服

現在我們有了標準的區塊模組,我們可以控制它們:將它們組合成任何複雜的結構,將它們安裝到系統中或在單一組裝系統中將它們連結在一起。

安裝到系統中

使用該模組的選項之一是將我們的模組安裝到系統中。

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

之後,使用命令將其連接到任何其他項目 find_package.

find_package(Mylib 1.0 REQUIRED)

作為子模組連接

另一種選擇是使用以下命令將包含我們項目的資料夾作為子模組連接到另一個項目 add_subdirectory.

使用

綁定方法不同,但結果是一樣的。在這兩種情況下,使用我們的模組的專案中都可以使用目標 Mylib::myfeature и Mylib::mylib,可以這樣使用:

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

特別是在我們的例子中,圖書館 Mylib::myfeature 需要與庫連結時需要連接 libmyfeature。如果有足夠的標頭,那麼值得使用該庫 Mylib::mylib.

CMake 目標可能很棘手,例如,僅用於轉送某些屬性、依賴項等。同時,與他們的合作也以同樣的方式進行。

這就是我們需要得到的。

來源: www.habr.com

添加評論