CMake FetchContent 多次下载外部依赖

joz*_*ols 0 android cmake

我开始使用 FetchContent 来自动下载外部依赖项。与旧方法相比,它工作得很好,但我有一个可能与 FetchContent 本身无关的问题 - 外部依赖项被多次下载。我实际上是为 Android 平台构建的,但这并不重要。我这样称呼 CMakecmake -B build/arm64-v8a ...cmake -B build/x86 .... 我需要为每个 ABI(arm64-v8a、x86、...)使用单独的构建文件夹以避免重建,因为我经常在 ABI 之间切换。但是当我使用简单的 FetchContent 结构时:

FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        release-1.8.0
)

FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
  FetchContent_Populate(googletest)
  add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
endif()
Run Code Online (Sandbox Code Playgroud)

它将为每个 ABI 下载一次外部项目(换句话说 - 每次使用不同构建文件夹的 CMake 调用一次),因为googletest_POPULATED在使用不同构建文件夹的下一次 CMake 调用中不可见。如果源文件下载一次就太棒了。

所以,我想通过SOURCE_DIRFetchContent_Declare先保存源升一级(在build/_deps/googletest-src没有build/<abi>/_deps/googletest-src文件夹)。它正确保存了源,但仍会触发重新下载,因为似乎googletest-subbuild文件夹(位于 下build/<abi>/_deps)管理googletest_POPULATED标志。

我怎样才能解决这个问题?

Fre*_*red 5

尝试使用FETCHCONTENT_BASE_DIR共享创建的处理下载管理的 CMake 项目。然后确保使用单独的构建目录来构建软件。

cmake_minimum_required(VERSION 3.13)
project(fc_twice)

include (FetchContent)
set(FETCHCONTENT_QUIET off)
get_filename_component(fc_base "../fc_base"
                       REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
set(FETCHCONTENT_BASE_DIR ${fc_base})

FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        release-1.8.0
)

FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
  FetchContent_Populate(googletest)
  #create gt build directory in binary tree
  add_subdirectory(${googletest_SOURCE_DIR} gt)
endif()
Run Code Online (Sandbox Code Playgroud)

在构建目录之间切换时,一些簿记项目会重复,但实际下载只会发生一次。您应该会看到以下消息:

  Performing download step (git clone) for 'googletest-populate'
  -- Avoiding repeated git clone, stamp file is up to date: 'C:/Users/XXX/Desktop/temp/so_fc/fc_base/googletest-subbuild/googletest-populate-prefix/src/googletest-populate-stamp/googletest-populate-gitclone-lastrun.txt'
Run Code Online (Sandbox Code Playgroud)

我使用命令进行了测试cmake -S src/ -B bld1cmake -S src/ -B bld2然后切换回并构建它们。

  • @jozols 我又看了一眼。它正在重新生成,因为“fc_base”是构建目录的相对路径(不断变化)。如果您使用某种绝对路径,则不会发生这种情况。我更新了示例以确定包含“bld1”和“bld2”的目录并将其用作绝对路径。然后“subbuild”中的“CMakeLists.txt”保持不变,并且不会重新生成任何内容。 (3认同)