简体   繁体   English

使用 cmake 获取外部依赖

[英]Getting external dependency with cmake

I am writing a small library in c++ with no external dependencies, except for testing where I want to use catch2 .我正在用 C++ 编写一个没有外部依赖项的小型库,除了测试我想使用catch2 的地方 So I'd rather not include the project and thought I could just download it when needed with cmake , but so far it looks like cmake only downloads when I execute the makefile所以我宁愿不包含该项目,并认为我可以在需要时使用 cmake 下载它,但到目前为止看起来 cmake 只在我执行 makefile 时下载

This is problematic since the rest of the CMakeList file depends on it already being downloaded so it can make use of catch2's provided cmake functions;这是有问题的,因为 CMakeList 文件的其余部分依赖于已经下载的文件,因此它可以使用 catch2 提供的 cmake 函数; without it the build fails.没有它,构建就会失败。

My following approach looks like this我的以下方法看起来像这样

./CMakeList.txt: ./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: ./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: ./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)

With the following project structure具有以下项目结构

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

Now this won't work at all, because I'm still misunderstanding who variables are scoped between multiple cmakefiles, but putting this all in one CmakeList still won't let add_subdirectory discover Catch2.现在这根本行不通,因为我仍然误解了多个 cmakefile 之间的变量范围,但是将所有这些放在一个 CmakeList 中仍然不会让 add_subdirectory 发现 Catch2。

My other idea was to just include it as a git submodule, if that would allow cmake to download catch2 before executing the makefiles.我的另一个想法是将它作为 git 子模块包含在内,如果这允许 cmake 在执行 makefile 之前下载 catch2。

So in general I want to keep my gitrepo as small as possible and only acquire dependencies when they're needed.所以总的来说,我想让我的 gitrepo 尽可能小,并且只在需要时才获取依赖项。

I did end up choosing submodules, since fetchContent works well, but is only supported in cmake v3.11我最终选择了子模块,因为 fetchContent 运行良好,但仅在 cmake v3.11 中受支持

I followed this guide for googletest https://cliutils.gitlab.io/modern-cmake/chapters/testing/googletest.html我按照本指南进行了 googletest https://cliutils.gitlab.io/modern-cmake/chapters/testing/googletest.html

./test/CMakeList with catch2 submodule at extern/catch2 : ./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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM