From 8b67fe23447a564d0cff45e94547a23c114109b5 Mon Sep 17 00:00:00 2001 From: Avus-c <48911667+Avus-c@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:19:31 +0200 Subject: [PATCH] replace deprecated calls to FetchContent_Populate (#570) * replace deprecated calls to FetchContent_Populate The single argument signature for FetchContent_Populate is deprecated with CMake 3.30. It was used, in order to call add_subdirectory manually with the EXCLUDE_FROM_ALL and SYSTEM flags. These have been added to FetchContent_Declare with 3.25 and 3.28. Calling FetchContent_MakeAvailable will internally call add_subdirectory with EXCLUDE_FROM_ALL and SYSTEM. There is therefore no need to call this manually. * fix: OPTIONS passed to CPMAddPackage not set where previously parsed in cpm_add_subdirectory which is not called on the new code path. * refactor: remove an unnecessary else branch * ci: include cmake 3.30 in test matrix * fix: forward SOURCE_SUBDIR to FetchContent_Declare For CMake version <3.28 this is done by calling add_subdirectory manually. For newer version FetchContent_Declare/MakeAvailable handles this for us. * fix: only set options if download_only is false this replicates the old behaviour * fix: DOWNLOAD_ONLY test * refactor: always use *_Populate to reduce code paths * Revert "refactor: always use *_Populate to reduce code paths" This reverts commit 0e8ca2a0e92d1c2035a64d3d1e365325b1279ef9. --------- Co-authored-by: Avus <48911667+Avus@users.noreply.github.com> --- .github/workflows/test.yaml | 2 +- cmake/CPM.cmake | 53 ++++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7b4eef8f..fc7e4f18 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -19,7 +19,7 @@ jobs: os: [ubuntu-latest, windows-2022, macos-latest] # we want to ensure compatibility with a recent CMake version as well as the lowest officially supported # legacy version that we define as the default version of the second-latest Ubuntu LTS release currently available - cmake_version: ['3.16.3', '3.27.5'] + cmake_version: ['3.16.3', '3.27.5', '3.30.0'] exclude: # there seems to be an issue with CMake 3.16 not finding a C++ compiler on windows-2022 - os: windows-2022 diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake index b273c3bb..7832b310 100644 --- a/cmake/CPM.cmake +++ b/cmake/CPM.cmake @@ -862,14 +862,38 @@ function(CPMAddPackage) ) if(NOT CPM_SKIP_FETCH) + # CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare. + # Calling FetchContent_MakeAvailable will then internally forward these options to + # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and + # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30. + set(fetchContentDeclareExtraArgs "") + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0") + if(${CPM_ARGS_EXCLUDE_FROM_ALL}) + list(APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL) + endif() + if(${CPM_ARGS_SYSTEM}) + list(APPEND fetchContentDeclareExtraArgs SYSTEM) + endif() + if(DEFINED CPM_ARGS_SOURCE_SUBDIR) + list(APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR}) + endif() + # For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory + if(CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY) + foreach(OPTION ${CPM_ARGS_OPTIONS}) + cpm_parse_option("${OPTION}") + set(${OPTION_KEY} "${OPTION_VALUE}") + endforeach() + endif() + endif() cpm_declare_fetch( - "${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}" + "${CPM_ARGS_NAME}" ${fetchContentDeclareExtraArgs} "${CPM_ARGS_UNPARSED_ARGUMENTS}" ) - cpm_fetch_package("${CPM_ARGS_NAME}" populated) + + cpm_fetch_package("${CPM_ARGS_NAME}" ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS}) if(CPM_SOURCE_CACHE AND download_directory) file(LOCK ${download_directory}/../cmake.lock RELEASE) endif() - if(${populated}) + if(${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.28.0") cpm_add_subdirectory( "${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}" @@ -980,7 +1004,7 @@ function(CPMGetPackageVersion PACKAGE OUTPUT) endfunction() # declares a package in FetchContent_Declare -function(cpm_declare_fetch PACKAGE VERSION INFO) +function(cpm_declare_fetch PACKAGE) if(${CPM_DRY_RUN}) cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)") return() @@ -1056,7 +1080,7 @@ endfunction() # downloads a previously declared package via FetchContent and exports the variables # `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope -function(cpm_fetch_package PACKAGE populated) +function(cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated) set(${populated} FALSE PARENT_SCOPE @@ -1071,7 +1095,24 @@ function(cpm_fetch_package PACKAGE populated) string(TOLOWER "${PACKAGE}" lower_case_name) if(NOT ${lower_case_name}_POPULATED) - FetchContent_Populate(${PACKAGE}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0") + if(DOWNLOAD_ONLY) + # MakeAvailable will call add_subdirectory internally which is not what we want when + # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the + # build + FetchContent_Populate( + ${PACKAGE} + SOURCE_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-src" + BINARY_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build" + SUBBUILD_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild" + ${ARGN} + ) + else() + FetchContent_MakeAvailable(${PACKAGE}) + endif() + else() + FetchContent_Populate(${PACKAGE}) + endif() set(${populated} TRUE PARENT_SCOPE