diff --git a/README.md b/README.md index 33fbbc89..d3a6bcbb 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,13 @@ In the case that `find_package` requires additional arguments, the parameter `FI Note that this does not apply to dependencies that have been defined with a truthy `FORCE` parameter. These will be added as defined. +### CPM_DONT_UPDATE_MODULE_PATH + +By default, CPM will override any `find_package` commands to use the CPM downloaded version. +This is equivalent to the `OVERRIDE_FIND_PACKAGE` FetchContent option, which has no effect in CPM. +To disable this behaviour set the `CPM_DONT_UPDATE_MODULE_PATH` option. +This will not work for `find_package(CONFIG)` in CMake versions before 3.24. + ### CPM_USE_NAMED_CACHE_DIRECTORIES If set, CPM use additional directory level in cache to improve readability of packages names in IDEs like CLion. It changes cache structure, so all dependencies are downloaded again. There is no problem to mix both structures in one cache directory but then there may be 2 copies of some dependencies. diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake index 6e260791..0875dabe 100644 --- a/cmake/CPM.cmake +++ b/cmake/CPM.cmake @@ -162,7 +162,7 @@ set(CPM_SOURCE_CACHE CACHE PATH "Directory to download CPM dependencies" ) -if(NOT CPM_DONT_UPDATE_MODULE_PATH) +if(NOT CPM_DONT_UPDATE_MODULE_PATH AND NOT DEFINED CMAKE_FIND_PACKAGE_REDIRECTS_DIR) set(CPM_MODULE_PATH "${CMAKE_BINARY_DIR}/CPM_modules" CACHE INTERNAL "" @@ -269,10 +269,25 @@ endfunction() # finding the system library function(cpm_create_module_file Name) if(NOT CPM_DONT_UPDATE_MODULE_PATH) - # erase any previous modules - file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake - "include(\"${CPM_FILE}\")\n${ARGN}\nset(${Name}_FOUND TRUE)" - ) + if(DEFINED CMAKE_FIND_PACKAGE_REDIRECTS_DIR) + # Redirect find_package calls to the CPM package. This is what FetchContent does when you set + # OVERRIDE_FIND_PACKAGE. The CMAKE_FIND_PACKAGE_REDIRECTS_DIR works for find_package in CONFIG + # mode, unlike the Find${Name}.cmake fallback. CMAKE_FIND_PACKAGE_REDIRECTS_DIR is not defined + # in script mode, or in CMake < 3.24. + # https://cmake.org/cmake/help/latest/module/FetchContent.html#fetchcontent-find-package-integration-examples + string(TOLOWER ${Name} NameLower) + file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${NameLower}-config.cmake + "include(\"${CMAKE_CURRENT_LIST_DIR}/${NameLower}-extra.cmake\" OPTIONAL)\n" + "include(\"${CMAKE_CURRENT_LIST_DIR}/${Name}Extra.cmake\" OPTIONAL)\n" + ) + file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${NameLower}-version.cmake + "set(PACKAGE_VERSION_COMPATIBLE TRUE)\n" "set(PACKAGE_VERSION_EXACT TRUE)\n" + ) + else() + file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake + "include(\"${CPM_FILE}\")\n${ARGN}\nset(${Name}_FOUND TRUE)" + ) + endif() endif() endfunction() diff --git a/test/integration/test_basics.rb b/test/integration/test_basics.rb index 5cb6ccfd..ebd55728 100644 --- a/test/integration/test_basics.rb +++ b/test/integration/test_basics.rb @@ -31,7 +31,9 @@ def test_cpm_default assert_same_path File.join(prj.bin_dir, 'cpm-package-lock.cmake'), check_and_get('CPM_PACKAGE_LOCK_FILE') assert_equal 'OFF', check_and_get('CPM_DONT_UPDATE_MODULE_PATH', 'BOOL') - assert_same_path File.join(prj.bin_dir, 'CPM_modules'), check_and_get('CPM_MODULE_PATH') + if @cache.entries['CMAKE_FIND_PACKAGE_REDIRECTS_DIR'].nil? + assert_same_path File.join(prj.bin_dir, 'CPM_modules'), check_and_get('CPM_MODULE_PATH') + end end # Test when env CPM_SOURCE_CACHE is set diff --git a/test/unit/local_dependency/ModuleCMakeLists.txt.in b/test/unit/local_dependency/ModuleCMakeLists.txt.in index 8c87ec1f..5ab7b3e9 100644 --- a/test/unit/local_dependency/ModuleCMakeLists.txt.in +++ b/test/unit/local_dependency/ModuleCMakeLists.txt.in @@ -8,6 +8,10 @@ option(ENABLE_TEST_COVERAGE "Enable test coverage" OFF) # ---- Dependencies ---- +if (@TEST_FORCE_MODULE_MODE@) + unset(CMAKE_FIND_PACKAGE_REDIRECTS_DIR CACHE) +endif() + include(@CPM_PATH@/CPM.cmake) CPMAddPackage( @@ -15,21 +19,23 @@ CPMAddPackage( SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/dependency ) -# ---- check if generated modules override find_package ---- - -if (@test_check_find_package@) - find_package(@TEST_DEPENDENCY_NAME@ REQUIRED) -endif() - # ---- Call dependency method to validate correct addition of directory ---- dependency_function() -# ---- Check parameters ---- - +# ---- Check newly added ---- include(@CPM_PATH@/testing.cmake) - ASSERT_TRUTHY(@TEST_DEPENDENCY_NAME@_ADDED) + +# ---- Check if generated modules override find_package ---- + +if (@TEST_FIND_PACKAGE@) + find_package(@TEST_DEPENDENCY_NAME@ @TEST_FIND_PACKAGE_CONFIG@ REQUIRED) + find_package(@TEST_CANT_FIND_PACKAGE_NAME@ @TEST_FIND_PACKAGE_CONFIG@ QUIET) + ASSERT_FALSY(@TEST_CANT_FIND_PACKAGE_NAME@_FOUND) +endif() + +# ---- Check parameters ---- ASSERT_DEFINED(@TEST_DEPENDENCY_NAME@_SOURCE_DIR) ASSERT_DEFINED(@TEST_DEPENDENCY_NAME@_BINARY_DIR) ASSERT_EQUAL("${CPM_LAST_PACKAGE_NAME}" "@TEST_DEPENDENCY_NAME@") diff --git a/test/unit/modules.cmake b/test/unit/modules.cmake index a0dec8e2..c5e5653b 100644 --- a/test/unit/modules.cmake +++ b/test/unit/modules.cmake @@ -3,7 +3,8 @@ include(${CPM_PATH}/testing.cmake) set(TEST_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/modules) -function(init_project_with_dependency TEST_DEPENDENCY_NAME) +function(init_project_with_dependency TEST_DEPENDENCY_NAME TEST_CANT_FIND_PACKAGE_NAME) + set(TEST_FIND_PACKAGE ON) configure_package_config_file( "${CMAKE_CURRENT_LIST_DIR}/local_dependency/ModuleCMakeLists.txt.in" "${CMAKE_CURRENT_LIST_DIR}/local_dependency/CMakeLists.txt" @@ -18,11 +19,17 @@ function(init_project_with_dependency TEST_DEPENDENCY_NAME) assert_equal(${ret} "0") endfunction() -init_project_with_dependency(A) -assert_exists(${TEST_BUILD_DIR}/CPM_modules) -assert_exists(${TEST_BUILD_DIR}/CPM_modules/FindA.cmake) -assert_not_exists(${TEST_BUILD_DIR}/CPM_modules/FindB.cmake) +init_project_with_dependency(A B) +init_project_with_dependency(B A) -init_project_with_dependency(B) -assert_not_exists(${TEST_BUILD_DIR}/CPM_modules/FindA.cmake) -assert_exists(${TEST_BUILD_DIR}/CPM_modules/FindB.cmake) +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24.0") + set(TEST_FIND_PACKAGE_CONFIG CONFIG) + init_project_with_dependency(A B) + init_project_with_dependency(B A) + + # Test the fallback path for CMake <3.24 works + set(TEST_FIND_PACKAGE_CONFIG) + set(TEST_FORCE_MODULE_MODE ON) + init_project_with_dependency(A B) + init_project_with_dependency(B A) +endif()