【问题标题】:Getting external dependency with cmake使用 cmake 获取外部依赖
【发布时间】:2019-11-26 06:25:07
【问题描述】:

我正在用 c++ 编写一个没有外部依赖项的小型库,除了测试我想在哪里使用 catch2。所以我宁愿不包含该项目,并认为我可以在需要时使用 cmake 下载它,但到目前为止,看起来 cmake 仅在我执行 makefile 时下载

这是有问题的,因为 CMakeList 文件的其余部分依赖于它已经被下载,因此它可以利用 catch2 提供的 cmake 函数;没有它,构建会失败。

我下面的方法是这样的

./CMakeList.txt:

cmake_minimum_required(VERSION 3.9)
project(projectname VERSION 0.0.1)

enable_language(CXX CUDA)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)

add_definitions(-DNVRTC_GET_TYPE_NAME=1)

include_directories(include)
link_libraries(cuda nvrtc)

file(GLOB SOURCES "*.cpp")

add_subdirectory(examples)
add_subdirectory(test)

./examples/CMakeList.txt:

if (CMAKE_BUILD_TYPE STREQUAL "Debug")
    add_definitions(-Wall -Dcurrent_log_level=loglevel::DEBUG1)
endif ()

add_executable(example_saxpy ${SOURCES} example_saxpy.cpp)
add_executable(example_program ${SOURCES} example_program.cpp)
add_executable(example_template ${SOURCES} example_template.cpp)

./test/CMakeList.txt:

file(GLOB TESTS "*.cpp")

add_executable(tests ${SOURCES} ${TESTS})
find_package(Catch2 CONFIG)
if (${Catch2_FOUND})       
else ()
    message(STATUS "downloading Catch2")
    include(ExternalProject)
    ExternalProject_Add(
            catch2
            PREFIX ${PROJECT_SOURCE_DIR}/lib/catch2
            GIT_REPOSITORY https://github.com/catchorg/Catch2.git
            TIMEOUT 10
            UPDATE_COMMAND ${GIT_EXECUTABLE} pull
            CONFIGURE_COMMAND ""
            BUILD_COMMAND ""
            INSTALL_COMMAND ""
            LOG_DOWNLOAD ON
    )
    add_dependencies(tests catch2)

    # Expose required variable (CATCH_INCLUDE_DIR) to parent scope
    ExternalProject_Get_Property(catch2 source_dir)
    set(CATCH_INCLUDE_DIR ${source_dir}/include CACHE INTERNAL "Path to include folder for Catch2")
    add_subdirectory(${PROJECT_SOURCE_DIR}/lib/catch2)
    include_directories(${CATCH_INCLUDE_DIR})
endif ()
enable_testing(true)
target_link_libraries(tests Catch2::Catch2)

include(CTest)
include(Catch)
catch_discover_tests(tests)

具有以下项目结构

projectname
├── bin
├── build
├── CMakeLists.txt
├── examples
│   └── CMakeLists.txt
├── include
    └── $projectname
├── src
└── test
    └──  CMakeLists.txt

现在这根本行不通,因为我仍然误解了多个 cmakefile 之间的变量范围,但是将所有这些都放在一个 CmakeList 中仍然不会让 add_subdirectory 发现 Catch2。

我的另一个想法是将它作为一个 git 子模块包含在内,如果这将允许 cmake 在执行 makefile 之前下载 catch2。

所以总的来说,我希望我的 gitrepo 尽可能小,并且只在需要时获取依赖项。

【问题讨论】:

  • 为什么不一劳永逸地下载 catch2,将其添加到 CMake 和您的版本控制中,然后忘记它?对我来说,这样做似乎是在浪费时间。继续前进,炸更大的鱼..
  • 试试FetchContent + add_subdirectory
  • @JesperJuhl 如果我使用 git submodule 或 git clone 我可以轻松更新或选择不同的版本。总是向我的项目提交另一个项目对我来说似乎很奇怪
  • 奇怪,为什么?它不占用太多空间,让生活变得简单,并让您可以完美地控制何时更新它。对我来说似乎完全合理、简单和直接。但是,我更喜欢完成实际工作,而不是陷入微优化/拖延这样的小细节。
  • @JesperJuhl 没必要这么被动攻击,因为代码都在那里,所以现在微优化似乎很好。对于我的工作流程,我喜欢将依赖项与我的代码严格分开,只是链接到一个 git 标签对我来说似乎很方便,而且这似乎是一种我可以重用的技术,否则我确实花了更多的时间来尝试设置它而不是我刚刚复制这个,但对我来说这是值得的。

标签: c++ cmake dependencies external-project catch2


【解决方案1】:

我最终还是选择了子模块,因为 fetchContent 运行良好,但仅在 cmake v3.11 中受支持

我按照这个 googletest 指南 https://cliutils.gitlab.io/modern-cmake/chapters/testing/googletest.html

./test/CMakeListextern/catch2 带有 catch2 子模块:

file(GLOB TESTS "*.cpp")
file(GLOB SOURCES "${PROJECT_SOURCE_DIR}/src/*.cpp")    

add_executable(tests ${SOURCES} ${TESTS})
SET(catch2_dir ${PROJECT_SOURCE_DIR}/extern/catch2)

find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
    # Update submodules as needed
    option(GIT_SUBMODULE "Check submodules during build" ON)
    if(GIT_SUBMODULE)
        message(STATUS "Submodule update")
        execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
                WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
                RESULT_VARIABLE GIT_SUBMOD_RESULT)
        if(NOT GIT_SUBMOD_RESULT EQUAL "0")
            message(FATAL_ERROR "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
        endif()
    endif()
endif()

if(NOT EXISTS "${catch2_dir}/CMakeLists.txt")
    message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.")
endif()

add_subdirectory(${catch2_dir} ${CMAKE_CURRENT_SOURCE_DIR}/catch_build)
list(APPEND CMAKE_MODULE_PATH "${catch2_dir}/contrib/")

target_link_libraries(tests Catch2::Catch2)

include(CTest)
include(Catch)
catch_discover_tests(tests)

【讨论】:

    猜你喜欢
    • 2017-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多