@@ -42,7 +42,11 @@ if(NOT COMMAND cpm_message)
4242 endfunction ()
4343endif ()
4444
45- set (CURRENT_CPM_VERSION 0.40.3)
45+ if (DEFINED EXTRACTED_CPM_VERSION)
46+ set (CURRENT_CPM_VERSION "${EXTRACTED_CPM_VERSION}${CPM_DEVELOPMENT} " )
47+ else ()
48+ set (CURRENT_CPM_VERSION 0.42.0)
49+ endif ()
4650
4751get_filename_component (CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR} " REALPATH)
4852if (CPM_DIRECTORY)
@@ -198,6 +202,60 @@ function(cpm_package_name_from_git_uri URI RESULT)
198202 endif ()
199203endfunction ()
200204
205+ # Find the shortest hash that can be used eg, if origin_hash is
206+ # cccb77ae9609d2768ed80dd42cec54f77b1f1455 the following files will be checked, until one is found
207+ # that is either empty (allowing us to assign origin_hash), or whose contents matches ${origin_hash}
208+ #
209+ # * .../cccb.hash
210+ # * .../cccb77ae.hash
211+ # * .../cccb77ae9609.hash
212+ # * .../cccb77ae9609d276.hash
213+ # * etc
214+ #
215+ # We will be able to use a shorter path with very high probability, but in the (rare) event that the
216+ # first couple characters collide, we will check longer and longer substrings.
217+ function (cpm_get_shortest_hash source_cache_dir origin_hash short_hash_output_var)
218+ # for compatibility with caches populated by a previous version of CPM, check if a directory using
219+ # the full hash already exists
220+ if (EXISTS "${source_cache_dir} /${origin_hash} " )
221+ set (${short_hash_output_var}
222+ "${origin_hash} "
223+ PARENT_SCOPE
224+ )
225+ return ()
226+ endif ()
227+
228+ foreach (len RANGE 4 40 4)
229+ string (SUBSTRING "${origin_hash} " 0 ${len} short_hash)
230+ set (hash_lock ${source_cache_dir} /${short_hash} .lock)
231+ set (hash_fp ${source_cache_dir} /${short_hash} .hash)
232+ # Take a lock, so we don't have a race condition with another instance of cmake. We will release
233+ # this lock when we can, however, if there is an error, we want to ensure it gets released on
234+ # it's own on exit from the function.
235+ file (LOCK ${hash_lock} GUARD FUNCTION)
236+
237+ # Load the contents of .../${short_hash}.hash
238+ file (TOUCH ${hash_fp} )
239+ file (READ ${hash_fp} hash_fp_contents)
240+
241+ if (hash_fp_contents STREQUAL "" )
242+ # Write the origin hash
243+ file (WRITE ${hash_fp} ${origin_hash} )
244+ file (LOCK ${hash_lock} RELEASE)
245+ break ()
246+ elseif (hash_fp_contents STREQUAL origin_hash)
247+ file (LOCK ${hash_lock} RELEASE)
248+ break ()
249+ else ()
250+ file (LOCK ${hash_lock} RELEASE)
251+ endif ()
252+ endforeach ()
253+ set (${short_hash_output_var}
254+ "${short_hash} "
255+ PARENT_SCOPE
256+ )
257+ endfunction ()
258+
201259# Try to infer package name and version from a url
202260function (cpm_package_name_and_ver_from_url url outName outVer)
203261 if (url MATCHES "[/\\ ?]([a-zA-Z0-9_\\ .-]+)\\ .(tar|tar\\ .gz|tar\\ .bz2|zip|ZIP)(\\ ?|/|$)" )
@@ -277,10 +335,10 @@ function(cpm_create_module_file Name)
277335 # https://cmake.org/cmake/help/latest/module/FetchContent.html#fetchcontent-find-package-integration-examples
278336 string (TOLOWER ${Name} NameLower)
279337 file (WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR} /${NameLower} -config.cmake
280- "include(\" ${CMAKE_CURRENT_LIST_DIR} /${NameLower} -extra.cmake\" OPTIONAL)\n "
281- "include(\" ${CMAKE_CURRENT_LIST_DIR} /${Name} Extra.cmake\" OPTIONAL)\n "
338+ "include(\"\ $ {CMAKE_CURRENT_LIST_DIR}/${NameLower} -extra.cmake\" OPTIONAL)\n "
339+ "include(\"\ $ {CMAKE_CURRENT_LIST_DIR}/${Name} Extra.cmake\" OPTIONAL)\n "
282340 )
283- file (WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR} /${NameLower} -version .cmake
341+ file (WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR} /${NameLower} -config- version .cmake
284342 "set(PACKAGE_VERSION_COMPATIBLE TRUE)\n " "set(PACKAGE_VERSION_EXACT TRUE)\n "
285343 )
286344 else ()
@@ -490,7 +548,7 @@ function(cpm_add_patches)
490548
491549 # Find the patch program.
492550 find_program (PATCH_EXECUTABLE patch)
493- if (WIN32 AND NOT PATCH_EXECUTABLE)
551+ if (CMAKE_HOST_WIN32 AND NOT PATCH_EXECUTABLE)
494552 # The Windows git executable is distributed with patch.exe. Find the path to the executable, if
495553 # it exists, then search `../usr/bin` and `../../usr/bin` for patch.exe.
496554 find_package (Git QUIET )
@@ -590,14 +648,6 @@ endfunction()
590648function (CPMAddPackage)
591649 cpm_set_policies()
592650
593- list (LENGTH ARGN argnLength)
594- if (argnLength EQUAL 1)
595- cpm_parse_add_package_single_arg("${ARGN} " ARGN)
596-
597- # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM
598- set (ARGN "${ARGN} ;EXCLUDE_FROM_ALL;YES;SYSTEM;YES;" )
599- endif ()
600-
601651 set (oneValueArgs
602652 NAME
603653 FORCE
@@ -620,10 +670,26 @@ function(CPMAddPackage)
620670
621671 set (multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES)
622672
673+ list (LENGTH ARGN argnLength)
674+
675+ # Parse single shorthand argument
676+ if (argnLength EQUAL 1)
677+ cpm_parse_add_package_single_arg("${ARGN} " ARGN)
678+
679+ # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM
680+ set (ARGN "${ARGN} ;EXCLUDE_FROM_ALL;YES;SYSTEM;YES;" )
681+
682+ # Parse URI shorthand argument
683+ elseif (argnLength GREATER 1 AND "${ARGV0} " STREQUAL "URI" )
684+ list (REMOVE_AT ARGN 0 1) # remove "URI gh:<...>@version#tag"
685+ cpm_parse_add_package_single_arg("${ARGV1} " ARGV0)
686+
687+ set (ARGN "${ARGV0} ;EXCLUDE_FROM_ALL;YES;SYSTEM;YES;${ARGN} " )
688+ endif ()
689+
623690 cmake_parse_arguments (CPM_ARGS "" "${oneValueArgs} " "${multiValueArgs} " "${ARGN} " )
624691
625692 # Set default values for arguments
626-
627693 if (NOT DEFINED CPM_ARGS_VERSION)
628694 if (DEFINED CPM_ARGS_GIT_TAG)
629695 cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG} " CPM_ARGS_VERSION)
@@ -794,9 +860,19 @@ function(CPMAddPackage)
794860 set (download_directory ${CPM_SOURCE_CACHE} /${lower_case_name} /${CPM_ARGS_CUSTOM_CACHE_KEY} )
795861 elseif (CPM_USE_NAMED_CACHE_DIRECTORIES)
796862 string (SHA1 origin_hash "${origin_parameters} ;NEW_CACHE_STRUCTURE_TAG" )
863+ cpm_get_shortest_hash(
864+ "${CPM_SOURCE_CACHE} /${lower_case_name} " # source cache directory
865+ "${origin_hash} " # Input hash
866+ origin_hash # Computed hash
867+ )
797868 set (download_directory ${CPM_SOURCE_CACHE} /${lower_case_name} /${origin_hash} /${CPM_ARGS_NAME} )
798869 else ()
799870 string (SHA1 origin_hash "${origin_parameters} " )
871+ cpm_get_shortest_hash(
872+ "${CPM_SOURCE_CACHE} /${lower_case_name} " # source cache directory
873+ "${origin_hash} " # Input hash
874+ origin_hash # Computed hash
875+ )
800876 set (download_directory ${CPM_SOURCE_CACHE} /${lower_case_name} /${origin_hash} )
801877 endif ()
802878 # Expand `download_directory` relative path. This is important because EXISTS doesn't work for
@@ -863,7 +939,9 @@ function(CPMAddPackage)
863939 endif ()
864940 endif ()
865941
866- cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(\" ${ARGN} \" )" )
942+ if (NOT "${DOWNLOAD_ONLY} " )
943+ cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(\" ${ARGN} \" )" )
944+ endif ()
867945
868946 if (CPM_PACKAGE_LOCK_ENABLED)
869947 if ((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK)
@@ -884,8 +962,9 @@ function(CPMAddPackage)
884962 # Calling FetchContent_MakeAvailable will then internally forward these options to
885963 # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and
886964 # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30.
965+ # A Bug in CMake prevents us to use the non-deprecated functions until 3.30.3.
887966 set (fetchContentDeclareExtraArgs "" )
888- if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0 " )
967+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30.3 " )
889968 if (${CPM_ARGS_EXCLUDE_FROM_ALL} )
890969 list (APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL )
891970 endif ()
@@ -911,7 +990,7 @@ function(CPMAddPackage)
911990 if (CPM_SOURCE_CACHE AND download_directory)
912991 file (LOCK ${download_directory} /../cmake.lock RELEASE)
913992 endif ()
914- if (${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.28.0 " )
993+ if (${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.30.3 " )
915994 cpm_add_subdirectory(
916995 "${CPM_ARGS_NAME} "
917996 "${DOWNLOAD_ONLY} "
@@ -1113,7 +1192,7 @@ function(cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated)
11131192 string (TOLOWER "${PACKAGE} " lower_case_name)
11141193
11151194 if (NOT ${lower_case_name} _POPULATED)
1116- if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0 " )
1195+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30.3 " )
11171196 if (DOWNLOAD_ONLY)
11181197 # MakeAvailable will call add_subdirectory internally which is not what we want when
11191198 # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the
0 commit comments