From a575ab57b7e7449c896ae6fed72808ab91088954 Mon Sep 17 00:00:00 2001 From: Lars Melchior Date: Mon, 16 May 2022 21:28:44 +0200 Subject: [PATCH] Allow overriding FetchContent using CPM (#352) * Override FetchContent paramers, fixes #281 * add check to verify that dependency is cached * update test comment * rename test file and class * update test indentation --- cmake/CPM.cmake | 50 ++++++++++++++++++- .../test_fetchcontent_compatibility.rb | 43 ++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 test/integration/test_fetchcontent_compatibility.rb diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake index b7a6249..9b47e70 100644 --- a/cmake/CPM.cmake +++ b/cmake/CPM.cmake @@ -433,6 +433,47 @@ function(cpm_check_git_working_dir_is_clean repoPath gitTag isClean) endfunction() +# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload +# FetchContent calls. As these are internal cmake properties, this method should be used carefully +# and may need modification in future CMake versions. Source: +# https://github.com/Kitware/CMake/blob/dc3d0b5a0a7d26d43d6cfeb511e224533b5d188f/Modules/FetchContent.cmake#L1152 +function(cpm_override_fetchcontent contentName) + cmake_parse_arguments(PARSE_ARGV 1 arg "" "SOURCE_DIR;BINARY_DIR" "") + if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "") + message(FATAL_ERROR "Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() + + string(TOLOWER ${contentName} contentNameLower) + set(prefix "_FetchContent_${contentNameLower}") + + set(propertyName "${prefix}_sourceDir") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}") + + set(propertyName "${prefix}_binaryDir") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}") + + set(propertyName "${prefix}_populated") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} TRUE) +endfunction() + # Download and add a package from source function(CPMAddPackage) list(LENGTH ARGN argnLength) @@ -644,8 +685,15 @@ function(CPMAddPackage) "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" "${${CPM_ARGS_NAME}_BINARY_DIR}" "${CPM_ARGS_EXCLUDE_FROM_ALL}" "${CPM_ARGS_OPTIONS}" ) - set(CPM_SKIP_FETCH TRUE) set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}") + + # As the source dir is already cached/populated, we override the call to FetchContent. + set(CPM_SKIP_FETCH TRUE) + cpm_override_fetchcontent( + "${lower_case_name}" SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" + BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}" + ) + else() # Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but # it should guarantee no commit hash get mis-detected. diff --git a/test/integration/test_fetchcontent_compatibility.rb b/test/integration/test_fetchcontent_compatibility.rb new file mode 100644 index 0000000..9cc5d7d --- /dev/null +++ b/test/integration/test_fetchcontent_compatibility.rb @@ -0,0 +1,43 @@ +require_relative './lib' + +# Tests FetchContent overriding with CPM + +class FetchContentCompatibility < IntegrationTest + def setup + @cache_dir = File.join(cur_test_dir, 'cpmcache') + ENV['CPM_SOURCE_CACHE'] = @cache_dir + end + + def test_add_dependency_cpm_and_fetchcontent + prj = make_project 'using-adder' + + prj.create_lists_from_default_template package: <<~PACK + CPMAddPackage( + NAME testpack-adder + GITHUB_REPOSITORY cpm-cmake/testpack-adder + VERSION 1.0.0 + OPTIONS "ADDER_BUILD_TESTS OFF" + ) + + # should have no effect, as we added the dependency using CPM + FetchContent_Declare( + testpack-adder + GIT_REPOSITORY https://github.com/cpm-cmake/testpack-adder + GIT_TAG v1.0.0 + ) + FetchContent_MakeAvailable(testpack-adder) + PACK + + # configure with unpopulated cache + assert_success prj.configure + assert_success prj.build + + # cache is populated + assert_true File.exist?(File.join(@cache_dir, "testpack-adder")) + + # configure with populated cache + assert_success prj.configure + assert_success prj.build + end + +end