c++ - FetchContent 与 ExternalProject

标签 c++ cmake external-project

我正在使用 Cmake 构建一个项目并使用 FetchContent 来管理依赖项。由于多种原因,我不能依赖系统范围内安装的包,所以这个包有很大帮助。它允许我做这样的事情:

cmake_minimum_required(VERSION 3.14)
project(dummy LANGUAGES C CXX)
include(FetchContent)
FetchContent_Declare(nlohmann
    GIT_REPOSITORY https://github.com/onavratil-monetplus/json
    GIT_TAG v3.7.3
)
FetchContent_MakeAvailable(nlohmann)

add_executable(dummy main.cpp)
target_link_libraries(dummy PUBLIC nlohmann_json::nlohmann_json)

现在只要 repo 是一个带有 CMakeLists.txt 的 cmake 项目,它就可以很好地工作。我很乐意对非 cmake 项目使用类似的方法,例如 Botan 库。显然

FetchContent_Declare(botan
    GIT_REPOSITORY https://github.com/onavratil-monetplus/botan
    GIT_TAG 2.17.2
)
FetchContent_MakeAvailable(botan)

并没有真正完成工作,构建没有运行,因为它不是 cmake 项目。人们会考虑添加

  CONFIGURE_COMMAND "<SOURCE_DIR>/configure.py --prefix=<BINARY_DIR>"
  BUILD_COMMAND "cd <SOURCE_DIR> && make"

或类似于 declare 命令的内容,但 FetchContent 文档明确指出这些特定参数在传递给 FetchContent 时会被忽略。

现在问题很明显了——如何在这种情况下正确使用 FetchContent?我正在考虑在 fetchcontent 之后使用 ExternalProject_Add,但是 fetchcontent 似乎没用(ExternalProject 也可以下载 git repo)。此外,我想在配置时使用 botan 的一些目标(如果有意义的话)。

最佳答案

我遇到了同样的问题。由于 Botan 库在内部不使用 CMake 构建系统,因此我们无法使用 Botan“目标”。但是可以在 CMake 配置时构建 Botan 库并使用库和头文件。这是我的解决方案(最小配置,仅适用于 MS Visual Studio):

cmake_minimum_required (VERSION 3.20)

if(WIN32)
  if(NOT (${CMAKE_BUILD_TYPE} STREQUAL "Release"))
    message(FATAL_ERROR "This configuration only works for a Release build")
  endif()

  # set paths
  set(BOTAN_LIB_ROOT_DIR    "${CMAKE_SOURCE_DIR}/external/botan")
  set(BOTAN_LIB_REPOS_DIR   "${BOTAN_LIB_ROOT_DIR}/repos")
  set(BOTAN_LIB_FCSTUFF_DIR "${BOTAN_LIB_ROOT_DIR}/cmake-fetchcontent-stuff")
  set(BOTAN_LIB_INSTALL_DIR "${BOTAN_LIB_ROOT_DIR}-install")

  # download and unpack Botan library
  include(FetchContent)
  FetchContent_Declare(
    botan
    GIT_REPOSITORY  https://github.com/randombit/botan.git
    GIT_TAG         2.19.1
    PREFIX          ${BOTAN_LIB_FCSTUFF_DIR}
    SOURCE_DIR      ${BOTAN_LIB_REPOS_DIR}
  )
  set(FETCHCONTENT_QUIET OFF CACHE BOOL "" FORCE)
  FetchContent_MakeAvailable(botan)

  # find Python3 Interpreter and run build, testing and installation
  if(${botan_POPULATED} AND MSVC AND NOT EXISTS "${BOTAN_LIB_INSTALL_DIR}/lib/botan.lib")
    find_package(Python3 COMPONENTS Interpreter)
    if(NOT ${Python3_Interpreter_FOUND})
      message(FATAL_ERROR "Python3 Interpreter NOT FOUND")
    endif()

    execute_process(
      COMMAND           ${Python3_EXECUTABLE} configure.py --cc=msvc --os=windows --prefix=${BOTAN_LIB_INSTALL_DIR}
      WORKING_DIRECTORY ${BOTAN_LIB_REPOS_DIR}
      COMMAND_ECHO      STDOUT
    )
    execute_process(
      COMMAND           nmake
      WORKING_DIRECTORY ${BOTAN_LIB_REPOS_DIR}
      COMMAND_ECHO      STDOUT
    )
    execute_process(
      COMMAND           nmake check
      WORKING_DIRECTORY ${BOTAN_LIB_REPOS_DIR}
      COMMAND_ECHO      STDOUT
    )
    execute_process(
      COMMAND           nmake install
      WORKING_DIRECTORY ${BOTAN_LIB_REPOS_DIR}
      COMMAND_ECHO      STDOUT
    )
  endif()
endif()


add_executable (main "main.cpp")

if(WIN32)
  target_include_directories(main PUBLIC "${BOTAN_LIB_INSTALL_DIR}/include/botan-2")
  target_link_libraries(main PUBLIC "${BOTAN_LIB_INSTALL_DIR}/lib/botan.lib")

  configure_file("${BOTAN_LIB_INSTALL_DIR}/bin/botan.dll"
                 "${CMAKE_CURRENT_BINARY_DIR}/botan.dll"
                 COPYONLY
  )

  install(TARGETS main DESTINATION bin)
  install(FILES "${BOTAN_LIB_INSTALL_DIR}/bin/botan.dll" DESTINATION bin)
endif()

这是完整版:https://github.com/weenchvd/cmake-build-botan-lib

关于c++ - FetchContent 与 ExternalProject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65232395/

相关文章:

c++ - 如何使用 enable_if 根据类的模板参数启用成员函数

c++ - 尝试将我的 C++ 可执行文件与 Fortran 库(Cygwin 环境)链接起来

cmake - 为 Raspbian 交叉编译 cpp-netlib 时出错

cmake - 在 ExternalProject_Add 命令中 INSTALL_DIR 有什么用?

c++ - CMake 声明函数对ExternalProject_Add 的依赖

c++ - 将 CMake 变量传递给 ExternalProject_Add

c++ - 如何在C++中创建一个n行5列的数组,但是n的值是变化的

c++ - 将 Eigen 类型与 STL 容器和 std::vector 一起使用

cmake - 如何让 CMake 构建具有 MPI 支持的 Fortran 程序?

带有 Emscripten 和 vcpkg 的 CMake 无法绑定(bind)两个 TOOLCHAIN_FILES