Cmake 如何在主项目配置期间配置ExternalProject?

Cmake 如何在主项目配置期间配置ExternalProject?,cmake,external-project,Cmake,External Project,CMake允许定义如何下载、配置、构建和安装外部项目。其所有步骤都将在构建时执行 我想在配置主项目期间执行外部项目的配置步骤。完成外部项目配置后,导入目标的描述可用,因此可以使用find\u package()函数加载外部项目 是否可以在配置时构建一些目标?外部项目只是要执行的一系列步骤。因此,您可以使用它的两个实例: 要在主项目的配置阶段生成的ExternalProject_Add()调用。例如,如中所述: 其他_项目/CMakeLists.txt: project(other_project

CMake允许定义如何下载、配置、构建和安装外部项目。其所有步骤都将在构建时执行

我想在配置主项目期间执行外部项目的配置步骤。完成外部项目配置后,导入目标的描述可用,因此可以使用
find\u package()
函数加载外部项目

是否可以在配置时构建一些目标?

外部项目只是要执行的一系列步骤。因此,您可以使用它的两个实例:

  • 要在主项目的配置阶段生成的ExternalProject_Add()调用。例如,如中所述:
  • 其他_项目/CMakeLists.txt

    project(other_project)
    include(ExternalProject)
    
    ExternalProject_Add(<project_name> <options...>
        BUILD_COMMAND "" # Disable build step.
        INSTALL_COMMAND "" # Disable install step too.
    )
    
    # The first external project will be built at *configure stage*
    execute_process(
        COMMAND ${CMAKE_COMMAND} --build . ${CMAKE_SOURCE_DIR}/other_project
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/other_project
    )
    
    # The second external project will be built at *build stage*
    ExternalProject_Add(<project_name> <options...>
        CONFIGURE_COMMAND "" # Disable configure step. But other steps will be generated.
    )
    
  • 要在主项目的构建阶段构建的ExternalProject_Add()调用
  • CMakeLists.txt

    project(other_project)
    include(ExternalProject)
    
    ExternalProject_Add(<project_name> <options...>
        BUILD_COMMAND "" # Disable build step.
        INSTALL_COMMAND "" # Disable install step too.
    )
    
    # The first external project will be built at *configure stage*
    execute_process(
        COMMAND ${CMAKE_COMMAND} --build . ${CMAKE_SOURCE_DIR}/other_project
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/other_project
    )
    
    # The second external project will be built at *build stage*
    ExternalProject_Add(<project_name> <options...>
        CONFIGURE_COMMAND "" # Disable configure step. But other steps will be generated.
    )
    
    #第二个外部项目将在*构建阶段构建*
    外部项目添加(
    CONFIGURE_命令“”#禁用配置步骤。但将生成其他步骤。
    )
    
    通过对两个
    ExternalProject\u Add()
    调用使用相同的方法,我们实现了对创建的两个外部项目的“抢占”:第二个项目的构建和后续步骤将使用第一个项目的配置步骤的结果。

    实现了我的要求。Hunter基于CMake ExternalProject,但附带了一组预定义的项目。此外,它在配置过程中构建依赖项
    find_package(…CONFIG)
    可以访问这些依赖项。好东西

    如果您不想在配置时构建项目†,而只想下载,请使用
    FetchContent\u Declare
    使用了许多与
    ExternalProject\u Add
    相同的参数,只是它不允许构建项目

    有一个很好的例子说明了如何使用:

    这需要CMake 3.11或更高版本。对于以前的版本,您可以从CMake存储库中下载,同时下载,以确保遵守BSD 3条款许可证


    †在配置时构建存在一些严重缺陷。例如,除非您非常小心地进行设置,否则库的用户无法控制构建过程。包管理器是一个更好的解决方案

    因为CMake 3.14和更高版本,这就是您使用FetchContent的方式

    FetchContent_Declare(
      googletest
      GIT_REPOSITORY https://github.com/google/googletest.git
      GIT_TAG        release-1.8.0
    )
    
    FetchContent_MakeAvailable(googletest)
    
    然后构建您的测试
    test/CMakeLists.txt

    cmake_minimum_required(VERSION 3.15)
    project(${PROJECT_NAME}_test)
    
    # Tests for mu_project
    file(GLOB_RECURSE TEST_SOURCES 
        ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp
        ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
    )
    
    add_executable(${PROJECT_NAME}_test ${TEST_SOURCES})
    target_link_libraries(${PROJECT_NAME}_test gtest gmock_main)
    
    # Register the tests
    add_test(NAME ${PROJECT_NAME}_test
             COMMAND ${PROJECT_NAME}_test)
    enable_testing()
    

    您现在可以开始了

    ExternalProject
    只是一系列步骤。因此,您可以使用一个
    ExternalProject\u Add()
    调用在主项目的配置阶段进行构建(例如,如中所述),使用第二个
    ExternalProject\u Add()
    调用在主项目的构建阶段进行构建。但我不明白如何通过
    find_package()
    使用配置的project:通常这需要安装project。在外部项目上运行cmake配置时,它会输出可由
    find_package(…CONFIG)
    使用的ExternalProjectConfig.cmake文件。嗯,是的,在某些情况下,使用构建树中的
    *Config.cmake
    。但是,只有该文件的已安装变体可以工作:该文件可能包括其他
    .cmake
    文件,它们在构建树和安装树中的布局可能不同。请注意,
    execute\u process
    将不会创建其
    WORKING\u目录
    ,如果它不存在,则在执行您可能要调用的
    文件之前,不会创建它的
    WORKING\u目录(确保目录${CMAKE\u BINARY\u DIR}/other\u project)
    。不确定旧版本的CMAKE是否如此……感谢您的宝贵评论。我记得我检查过这种方法(为了验证ExternalProject的工作是否“抢占”),但不记得我是如何为它调整构建目录的。我会检查一下。有没有办法告诉cmake不要从外部模块导入所有目标?我正试图使用此方法将gRPC包括在我的项目中,但它会用一堆垃圾目标库填充我的目标列表,但我不知道。如果我找到什么,我会回来的谢谢你。