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

اضافه کردن نظر