C++ และ CMake - พี่น้องกันตลอดไป ตอนที่ II

C++ และ CMake - พี่น้องกันตลอดไป ตอนที่ II

ในส่วนก่อนหน้า เรื่องราวสนุกสนานนี้พูดถึงการจัดระเบียบไลบรารีส่วนหัวภายในตัวสร้างระบบ 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::. สิ่งเดียวกันนี้เขียนขึ้นเพื่อวัตถุประสงค์ทั้งสองประการเมื่อส่งออกเพื่อติดตั้งบนระบบ ทำให้สามารถทำงานอย่างเท่าเทียมกันโดยมีเป้าหมายสำหรับสิ่งใดสิ่งหนึ่ง โครงการมีผลผูกพัน.

หลังจากนี้ สิ่งที่เหลืออยู่คือการเชื่อมโยงการทดสอบหน่วยกับไลบรารีใหม่ (function 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 อาจยุ่งยาก เช่น มีจุดประสงค์เพื่อส่งต่อคุณสมบัติบางอย่าง การขึ้นต่อกัน ฯลฯ เท่านั้น ในขณะเดียวกัน การทำงานร่วมกับพวกเขาก็เกิดขึ้นในลักษณะเดียวกัน

นั่นคือสิ่งที่เราต้องได้รับ

ที่มา: will.com

เพิ่มความคิดเห็น