【问题标题】:Can CMake find_package be "common dependency version aware"?CMake find_package 可以“感知通用依赖版本”吗?
【发布时间】:2016-05-27 14:48:50
【问题描述】:

问题:

我正在重做旧项目中的 make 系统,从目前的神秘版本更改为 CMake。目前,我已经让 CMake 将整个事情视为一个大型 CMake 项目,但我们的代码库太大,以至于它破坏了我们投入它的大多数 IDE。

我们想将其拆分,CMake 的 find_package “模块模式”似乎非常适合将其拆分为“特征大小”的块。主要候选者是一大块只需要很少维护的代码,即便如此,它通常也由另一个团队维护。这将允许我们维护代码,但在更新不同的代码时不会不断地重新编译它。

也就是说,这段代码在 API 中使用了 Boost 的共享指针,虽然不同版本的共享指针可能可以一起工作,但我宁愿不要冒险。所以,理想情况下,包会知道系统正在使用什么版本的“boost”,编译模块时使用的boost版本,并且能够重新编译——或者,至少,抛出一个错误或 CMake 中的警告——如果两者不匹配。

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

其他信息:

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

【问题讨论】:

    标签: c++ cmake software-product-lines


    【解决方案1】:

    您可以使用find_packageconfig 模式来允许您的模块向其用户(根项目)公开一些内部属性。

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

    您的根项目将通过find_package() 调用包含模块并将读取这些属性。当它尝试链接此类模块提供的库时,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的实现方式类似)

    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)
    

    此外,在根项目中创建的可执行文件可以通过设置适当的属性来请求特定的 Boost 版本:

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

    在这种情况下,将禁止(通过 CMake)其依赖项将 Boost 库与其他版本一起使用。

    更多信息和使用示例请参见 CMake 构建系统 description

    【讨论】:

      猜你喜欢
      • 2015-11-08
      • 1970-01-01
      • 1970-01-01
      • 2014-12-23
      • 2018-11-16
      • 2011-12-04
      • 2012-10-27
      • 2019-12-25
      • 2019-04-18
      相关资源
      最近更新 更多