
на тази занимателна история се говореше за организацията на заглавната библиотека в рамките на генератора на системи за компилиране CMake.
Този път ще добавим към него компилируема библиотека, а също така ще говорим за свързването на модулите помежду им.
Както и преди, за тези, които нямат търпение, могат веднага и да опитат всичко с ръцете си.
Съдържание
Първото, което трябва да направим, за да постигнем нашата амбициозна цел, е да разделим разработвания софтуер на универсални изолирани блокове, които са единно изградени от гледна точка на потребителя.
В първата част беше описан такъв стандартен блок — проект с заглавна библиотека. Сега ще добавим в нашия проект компилируема библиотека.
За целта ще изнесем реализацията на функцията 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
~ виж 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
+
+namespace mylib
+{
+ bool myfunc (mystruct)
+ {
+ return true;
+ }
+}След това ще определим компилируемата библиотека (myfeature), която ще се състои от полученото на предишната стъпка .cpp-файл. Новата библиотека, очевидно, изисква вече съществуващите заглавия, и за да се осигури това, може и трябва да бъде свързана с вече съществуващата цел mylib. Освен това свързването между тях е публично, а това означава, че всичко, към което ще бъде свързана целта, автоматично ще получи в натоварването и целта myfeature, повече за начините на свързване mylib ().
След това ще направим така, че новата библиотека също да бъде инсталирана в системата:@@ -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)
@@ -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(Mylib 1.0 REQUIRED)Свързване като подмодул
Друг вариант е да свържем папката с нашия проект към друг проект като подмодул с помощта на командата .
Използването
Методите за свързване са различни, но резултатът е един и същ. И в двата случая, в проект, който използва нашия модул, целите ще бъдат достъпни. 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 целите могат да бъдат хитри, например, проектирани само за предаване на определени свойства, зависимости и т.н. Работата с тях се осъществява по един и същ начин.
Каквото и да е необходимо.
Източник: habr.com
