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 بالغرض الحالي من mylib . علاوة على ذلك ، يكون الرابط بينهما عامًا ، مما يعني أن كل شيء سيتم ربط هدف myfeature به 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 ، تم myfeature الاسم المستعار بالبادئة Mylib:: . يتم ذكر الشيء نفسه لكلا الغرضين عند تصديرهما للتثبيت في النظام. هذا يجعل من الممكن العمل بشكل موحد مع أهداف لأي نظام ربط .


بعد ذلك ، يظل myfunc اختبارات الوحدة والمكتبة الجديدة (تمت myfunc وظيفة 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 بمشروع آخر كوحدة فرعية باستخدام 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 بمكتبة libmyfeature . إذا كانت هناك رؤوس كافية ، فيجب عليك استخدام مكتبة Mylib::mylib .


يمكن أن تكون أهداف CMake صعبة ، على سبيل المثال ، مصممة فقط لإعادة توجيه بعض الخصائص والتبعيات وما إلى ذلك. في الوقت نفسه ، يحدث العمل معهم بطريقة واحدة.


ما هو المطلوب لتلقي.

Source: https://habr.com/ru/post/ar463295/


All Articles