获取软件包(FetchContent) (CMake 3.11+)

有时你想要在配置的时候下载数据或者是包,而不是在编译的时候下载。这种方法已经被第三方包重复“发明”了好几次。最终,这种方法在 CMake 3.11 中以 FetchContent 模块的形式出现。

FetchContent 模块有出色的文档,我在此不会赘述。我会阐述这样几个步骤:

  • 使用 FetchContent_Declare(MyName) 来从 URL、Git 仓库等地方获取数据或者是软件包。
  • 使用 FetchContent_GetProperties(MyName) 来获取 MyName_* 等变量的值,这里的 MyName 是上一步获取的软件包的名字。
  • 检查 MyName_POPULATED 是否已经导出,否则使用 FetchContent_Populate(MyName) 来导出变量(如果这是一个软件包,则使用 add_subdirectory("${MyName_SOURCE_DIR}" "${MyName_BINARY_DIR}")

比如,下载 Catch2 :

  1. FetchContent_Declare(
  2. catch
  3. GIT_REPOSITORY https://github.com/catchorg/Catch2.git
  4. GIT_TAG v2.13.6
  5. )
  6. # CMake 3.14+
  7. FetchContent_MakeAvailable(catch)

如果你不能使用 CMake 3.14+ ,可以使用适用于低版本的方式来加载:

  1. # CMake 3.11+
  2. FetchContent_GetProperties(catch)
  3. if(NOT catch_POPULATED)
  4. FetchContent_Populate(catch)
  5. add_subdirectory(${catch_SOURCE_DIR} ${catch_BINARY_DIR})
  6. endif()

当然,你可以将这些语句封装到一个宏内:

  1. if(${CMAKE_VERSION} VERSION_LESS 3.14)
  2. macro(FetchContent_MakeAvailable NAME)
  3. FetchContent_GetProperties(${NAME})
  4. if(NOT ${NAME}_POPULATED)
  5. FetchContent_Populate(${NAME})
  6. add_subdirectory(${${NAME}_SOURCE_DIR} ${${NAME}_BINARY_DIR})
  7. endif()
  8. endmacro()
  9. endif()

这样,你就可以在 CMake 3.11+ 里使用 CMake 3.14+ 的语法了。

可以在这里查看例子。