可以CMake find_package是“公共依赖性版本感知”? [英] Can CMake find_package be "common dependency version aware"?

查看:258
本文介绍了可以CMake find_package是“公共依赖性版本感知”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:



我正在重做旧版专案中的make系统,改用目前的版本到CMake。目前,我已经有CMake将整个事情作为一个大的CMake项目,但我们的代码基础是这么大,它打破了我们抛出的大多数IDE。



我们想要打破它,而CMake的find_package模块模式似乎是理想的打破成功能大小的块。主要候选人是一个大块的代码,只需要很少维护,甚至通常由另一个团队。这将允许我们维护代码,但在更新不同的代码时不会不断地重新编译。



也就是说,这段代码使用Boost的API中的共享指针,而不同版本的共享指针可能将一起工作,我宁愿不采取机会。因此,理想情况下,软件包会知道系统使用的是什么版本的boost,当模块被编译时使用了什么版本的boost,并且能够重新编译 - 或者至少会抛出一个错误或者CMake中的警告 - 如果两者不匹配。



那么...如何确保在CMake find_package模块中匹配常见依赖关系的版本?我唯一能想到的是测试适当的VERSION变量,但似乎...笨重。



我们在这里找到了一些我缺少的东西?



<重新使用CMake 3.5.1,但我们可以升级到3.5.2如果这将有所作为。这个项目实际上是一个软件产品线(q.v.),因此我们计划在未来的某个时候使用更现代的SPL软件工程技术(另一个选择CMake的原因)。代码库目前在Redhat Linux中,但理想情况下,这些技术将是跨平台的。

解决方案

find_package config 模式允许模块向其用户(根项目)公开一些内部属性。



如果您的每个模块都提供了目标,您可以使用包含Boost版本的属性公开该目标,并在特殊的 COMPATIBLE_INTERFACE_STRING 属性。



通过 find_package()调用并将读取这些属性。当它尝试链接由这些模块提供的库时,CMake将自动执行版本兼容性:



modA / CMakeLists.txt

  ... 
find_package(Boost)
add_library(modA_lib ...)
...#Link modA_lib with Boost
#安装modA_lib目标并将其导出以用于其他项目。
install(TARGETS modA_lib EXPORT modA_lib)
#配置的-config文件如下所示
configure(modA-config.cmake.in modA-config.cmake)
install(EXPORT modA_lib
DESTINATION share / cmake / modA)
install(FILES $ {CMAKE_CURRENT_BINARY_DIR} /modA-config.cmake
DESTINATION share / cmake / modA)



modA / modA-config.cmake.in

  include(@ CMAKE_INSTALL_PREFIX @ / share / cmake / modA / modA_lib.cmake)#包括文件描述库目标
#通过目标属性暴露Boost的链接版本。
set_property(TARGET modA_lib PROPERTY INTERFACE_BOOST_VERSION @ Boost_VERSION @)
#将此属性标记为兼容性要求
set_property(TARGET modA_lib PROPERTY APPEND COMPATIBLE_INTERFACE_STRING BOOST_VERSION)

(modB以类似的方式实现)



root / CMakeLists.txt

  find_package(modA)#此导入目标modA_lib 
find_package(modB)#此导入目标modB_lib

add_executable(root_exe< ...>)

此处将执行Boost版本检查
target_link_libraries(root_exe modA_lib modB_lib)
<此外,在根项目中创建的可执行文件可以通过设置适当的属性来请求特定的Boost版本:

code>

  add_executable(root_exe< ...>)
set_property(TARGET root_exe PROPERTY BOOST_VERSION< ...>)

在这种情况下,它将被禁止(由CMake)的依赖关系使用Boost库与其他版本。

更多信息和使用示例参见CMake build system description


The Problem:

I'm in the process of redoing the make system in our legacy project, changing from its present arcane version to CMake. At the moment, I've got CMake treating the whole thing as one large CMake project, but our code base is so large that it's breaking most of the IDEs we throw at it.

We'd like to break it apart, and CMake's find_package "module mode" seems to be ideal for breaking it into "feature-sized" chunks. The prime candidate is a large chunk of the code that only needs to be maintained rarely, and even then its usually by another team. That would allow us to maintain the code, but not continuously recompile it when updating different code.

That said, this chunk of code uses Boost's shared pointer in the API, and while different versions of shared pointer probably will work together, I'd rather not take the chance. So, ideally, the package will be aware of what version of "boost" the system is using, what version of boost was used when the module was compiled, and be able to recompile -- or, at the very least, throw an error or warning in CMake -- if the two don't match.

So ... how does one go about ensuring that versions of common dependencies match in CMake find_package modules? The only thing I can think of is testing the appropriate VERSION variable, but that seems ... bulky. Is there something I'm missing?

Additional Information:

We're using CMake 3.5.1, but we can upgrade to 3.5.2 if that would make a difference. This project is actually a Software Product Line (q.v.), so we are planning to use more modern SPL Software Engineering techniques at some point in the future (yet another reason to choose CMake). The codebase is currently in Redhat Linux, but ideally the technique(s) would be cross-platform.

解决方案

You may use config mode of the find_package for allow you modules to expose some internal properties to their user (root project).

If each your module provides library target, you may expose that target with property containing Boost version attached and list this property in a special COMPATIBLE_INTERFACE_STRING property.

Your root project will include modules via find_package() calls and will read these properties. When it will try to link libraries, provided by such modules, version compatibility will be automatically performed by CMake:

modA/CMakeLists.txt:

...
find_package(Boost)
add_library(modA_lib ...)
... # Link modA_lib with Boost
# Install modA_lib target and exports it for use in other project.
install(TARGETS modA_lib EXPORT modA_lib)
# Configured -config file is shown below
configure(modA-config.cmake.in modA-config.cmake)
install(EXPORT modA_lib
    DESTINATION share/cmake/modA)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/modA-config.cmake
    DESTINATION share/cmake/modA)

modA/modA-config.cmake.in:

include(@CMAKE_INSTALL_PREFIX@/share/cmake/modA/modA_lib.cmake) # Include file described library target
# Expose linked version of Boost via target's property.
set_property(TARGET modA_lib PROPERTY INTERFACE_BOOST_VERSION @Boost_VERSION@)
# Mark this property as compatibility requirement
set_property(TARGET modA_lib PROPERTY APPEND COMPATIBLE_INTERFACE_STRING BOOST_VERSION)

(modB is implemented in similar manner)

root/CMakeLists.txt:

find_package(modA) # This imports target modA_lib
find_package(modB) # This imports target modB_lib

add_executable(root_exe <...>)

# Boost version check will be performed here
target_link_libraries(root_exe modA_lib modB_lib)

Additionally, an executable created in the root project may request specific Boost version via setting appropriate property:

add_executable(root_exe <...>)
set_property(TARGET root_exe PROPERTY BOOST_VERSION <...>)

In this case it will be prohibited (by CMake) for its dependencies to use Boost library with other versions.

More info and usage examples see in CMake build system description.

这篇关于可以CMake find_package是“公共依赖性版本感知”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆