【问题标题】:cmake: how to reference and build separate cmake project dependency?cmake:如何引用和构建单独的 cmake 项目依赖项?
【发布时间】:2018-02-01 05:00:21
【问题描述】:

我有一个交叉编译器 cmake 项目,该项目依赖于一个单独项目中的库,该项目恰好也使用 cmake:

/myProject/CMakeLists.txt (uses cross-compiler)
/anotherProject/CMakeLists.txt (platform-agnostic)

anotherProject 可以完全独立地单独构建。它根本不知道 myProject。

现在,anotherProject 有许多我需要的模块,例如:

anotherProject/A/CMakeLists.txt (produces static lib A.a)
anotherProject/B/CMakeLists.txt (produces static lib B.a)
etc

当我构建 myProject 时,我想构建和链接 anotherProject/A 和 anotherProject/B,以生成共享库 myproject.so。如果可能的话,我想利用 anotherProject 的现有 cmake 特性,而不是从 myProject 手动 globbing 其各种源集。

使用 cmake 实现此目的的正确方法是什么?我觉得我错过了一些明显的东西。

如果 myProject 只是 anotherProject 下的一个子目录,或者如果有一个可以引用 myProject 和 anotherProject 的顶级 CMakeLists.txt,那就很简单了;但也不是我所追求的。我知道我可以构建 anotherProject 并将其库导出到一个众所周知的位置,然后从 myProject 引用导出目录 - 但我也想避免这种设置。

【问题讨论】:

标签: c++ cmake


【解决方案1】:

解决方案是使用CMake packages

基本上,在 anotherProject 中,您制作一个 CMake 配置文件,在其中设置 myProject 使用的变量(例如,包含目录、库列表、编译标志...),甚至是目标。

然后,在 myProject 中,您使用 find_package() 机制,以便 CMake 找到此配置文件并导入当前项目中的变量/目标。

在 CMake wiki 上有一个 tutorial

【讨论】:

    【解决方案2】:

    根据您的要求,我能想到的唯一替代设置是允许您的主(依赖)项目使用 find_package 发现另一个(依赖)项目。

    在您的主项目CMakeLists.txt 中,您应该添加如下内容:

    find_package(anotherProject CONFIG)
    
    if(anotherProject_FOUND)
      message(STATUS "Found project dependency: anotherProject")
    else
      # change WARNING to FATAL_ERROR if the dependency is NOT optional
      message(WARNING "package anotherProject was not found")
    endif()
    

    关于CONFIGMODULE 模式之间的区别,请查看文档和此link

    然后假设您的主项目创建了一个可执行文件,您可以像这样连接发现的依赖项:

    add_executable(myProject ${SOURCES})
    [...]
    
    if(anotherProject_FOUND)
       target_link_libraries(myProject PUBLIC anotherProject)
    endif()
    

    这也应该处理所需的包含文件和定义。


    现在在依赖项目CMakeLists.txt 中你应该这样做:

    set(PRJ_NAME "anotherProject")
    string(TOLOWER ${PRJ_NAME} PRJ_NAME_LOWER)
    set(ANOTHERPROJECT_EXPORT_NAME "${PRJ_NAME}")
    
    install(TARGETS ${PRJ_NAME} EXPORT ${ANOTHERPROJECT_EXPORT_NAME}
      RUNTIME DESTINATION .)
    install(EXPORT ${ANOTHERPROJECT_EXPORT_NAME} DESTINATION "share/cmake")
    

    这会将导出与目标相关联,然后安装导出。

    现在,如果您检查该导出文件,它预计会找到某些内容和included,这可能是您的项目特有的。为了使其尽可能灵活,您可以使用configure 功能从模板生成它们,然后从构建目录生成install
    因此,在名为 share/cmake 的子目录下的项目中,您可以有一个名为 config.cmake.in 的文件,其内容为:

    include(${CMAKE_CURRENT_LIST_DIR}/@PRJ_NAME@.cmake)
    

    在主项目的CMakeLists.txt 中,您需要添加以下内容以从该模板生成文件:

    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/share/cmake/config.cmake
      ${CMAKE_CURRENT_BINARY_DIR}/share/cmake/${PRJ_NAME_LOWER}-config.cmake)
    
    install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/
      DESTINATION share)
    

    请注意,我使用了PRJ_NAME,因为您可能会在add_executable 命令中重用它来命名实际的可执行文件。如果导出的目标与生成的目标同名,这在精神上会有所帮助。

    这是一个更通用的版本,可以容纳this教程的多个子项目。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多