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

永远的友谊


这个有趣的故事的前一部分中 ,我们讨论了将标头库组织为CMake装配系统生成器的一部分。


这次我们向其中添加了一个已编译的库,并且还彼此讨论了模块的布局。


和以前一样,那些迫不及待的人可以立即进入更新的存储库 ,用自己的双手触摸一切。


目录内容


  1. 分享到
  2. 征服


分享到


要实现我们的崇高目标,要做的第一件事就是将开发中的软件分为通用的,独立的模块,这些模块从用户的角度来看是统一的。


第一部分描述了这样的标准块-一个带有标头库的项目。 现在,将一个已编译的库添加到我们的项目中。


为此,我们在单独的.cpp文件中取出myfunc函数的实现:


 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) 

应该注意的是,出于myfeaturemylib的目的,别名以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将文件夹与我们的项目作为子模块连接到另一个项目。


使用方法


绑定方法不同,但结果相同。 在这两种情况下,在使用我们的模块的项目中,目标Mylib::myfeatureMylib::mylib都是可用的,例如可以这样使用:


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

具体来说,在我们的示例中,当需要libmyfeature库时,需要连接Mylib::myfeature libmyfeature库。 如果头足够,则应使用Mylib::mylib库。


CMake目标可能很棘手,例如,仅设计为转发某些属性,依赖项等。 同时,以单一方式进行处理。


需要接收什么。

Source: https://habr.com/ru/post/zh-CN463295/


All Articles