@@ -42,7 +42,7 @@ if(NOT COMMAND cpm_message)
42
42
endfunction ()
43
43
endif ()
44
44
45
- set (CURRENT_CPM_VERSION 0.38.5 )
45
+ set (CURRENT_CPM_VERSION 0.40.2 )
46
46
47
47
get_filename_component (CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR} " REALPATH)
48
48
if (CPM_DIRECTORY)
@@ -99,6 +99,12 @@ macro(cpm_set_policies)
99
99
cmake_policy (SET CMP0135 NEW)
100
100
set (CMAKE_POLICY_DEFAULT_CMP0135 NEW)
101
101
endif ()
102
+
103
+ # treat relative git repository paths as being relative to the parent project's remote
104
+ if (POLICY CMP0150)
105
+ cmake_policy (SET CMP0150 NEW)
106
+ set (CMAKE_POLICY_DEFAULT_CMP0150 NEW)
107
+ endif ()
102
108
endmacro ()
103
109
cpm_set_policies()
104
110
@@ -294,12 +300,6 @@ function(CPMFindPackage)
294
300
return ()
295
301
endif ()
296
302
297
- cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION} " )
298
- if (CPM_PACKAGE_ALREADY_ADDED)
299
- cpm_export_variables(${CPM_ARGS_NAME} )
300
- return ()
301
- endif ()
302
-
303
303
cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION} " ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS} )
304
304
305
305
if (NOT CPM_PACKAGE_FOUND)
@@ -391,8 +391,8 @@ function(cpm_parse_add_package_single_arg arg outArgs)
391
391
# We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url
392
392
# should do this at a later point
393
393
else ()
394
- # We should never get here. This is an assertion and hitting it means there's a bug in the code
395
- # above. A packageType was set, but not handled by this if-else.
394
+ # We should never get here. This is an assertion and hitting it means there's a problem with the
395
+ # code above. A packageType was set, but not handled by this if-else.
396
396
message (FATAL_ERROR "${CPM_INDENT} Unsupported package type '${packageType} ' of '${arg} '" )
397
397
endif ()
398
398
@@ -464,6 +464,72 @@ function(cpm_check_git_working_dir_is_clean repoPath gitTag isClean)
464
464
465
465
endfunction ()
466
466
467
+ # Add PATCH_COMMAND to CPM_ARGS_UNPARSED_ARGUMENTS. This method consumes a list of files in ARGN
468
+ # then generates a `PATCH_COMMAND` appropriate for `ExternalProject_Add()`. This command is appended
469
+ # to the parent scope's `CPM_ARGS_UNPARSED_ARGUMENTS`.
470
+ function (cpm_add_patches)
471
+ # Return if no patch files are supplied.
472
+ if (NOT ARGN)
473
+ return ()
474
+ endif ()
475
+
476
+ # Find the patch program.
477
+ find_program (PATCH_EXECUTABLE patch)
478
+ if (WIN32 AND NOT PATCH_EXECUTABLE)
479
+ # The Windows git executable is distributed with patch.exe. Find the path to the executable, if
480
+ # it exists, then search `../usr/bin` and `../../usr/bin` for patch.exe.
481
+ find_package (Git QUIET )
482
+ if (GIT_EXECUTABLE)
483
+ get_filename_component (extra_search_path ${GIT_EXECUTABLE} DIRECTORY )
484
+ get_filename_component (extra_search_path_1up ${extra_search_path} DIRECTORY )
485
+ get_filename_component (extra_search_path_2up ${extra_search_path_1up} DIRECTORY )
486
+ find_program (
487
+ PATCH_EXECUTABLE patch HINTS "${extra_search_path_1up} /usr/bin"
488
+ "${extra_search_path_2up} /usr/bin"
489
+ )
490
+ endif ()
491
+ endif ()
492
+ if (NOT PATCH_EXECUTABLE)
493
+ message (FATAL_ERROR "Couldn't find `patch` executable to use with PATCHES keyword." )
494
+ endif ()
495
+
496
+ # Create a temporary
497
+ set (temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS} )
498
+
499
+ # Ensure each file exists (or error out) and add it to the list.
500
+ set (first_item True )
501
+ foreach (PATCH_FILE ${ARGN} )
502
+ # Make sure the patch file exists, if we can't find it, try again in the current directory.
503
+ if (NOT EXISTS "${PATCH_FILE} " )
504
+ if (NOT EXISTS "${CMAKE_CURRENT_LIST_DIR} /${PATCH_FILE} " )
505
+ message (FATAL_ERROR "Couldn't find patch file: '${PATCH_FILE} '" )
506
+ endif ()
507
+ set (PATCH_FILE "${CMAKE_CURRENT_LIST_DIR} /${PATCH_FILE} " )
508
+ endif ()
509
+
510
+ # Convert to absolute path for use with patch file command.
511
+ get_filename_component (PATCH_FILE "${PATCH_FILE} " ABSOLUTE )
512
+
513
+ # The first patch entry must be preceded by "PATCH_COMMAND" while the following items are
514
+ # preceded by "&&".
515
+ if (first_item)
516
+ set (first_item False )
517
+ list (APPEND temp_list "PATCH_COMMAND" )
518
+ else ()
519
+ list (APPEND temp_list "&&" )
520
+ endif ()
521
+ # Add the patch command to the list
522
+ list (APPEND temp_list "${PATCH_EXECUTABLE} " "-p1" "<" "${PATCH_FILE} " )
523
+ endforeach ()
524
+
525
+ # Move temp out into parent scope.
526
+ set (CPM_ARGS_UNPARSED_ARGUMENTS
527
+ ${temp_list}
528
+ PARENT_SCOPE
529
+ )
530
+
531
+ endfunction ()
532
+
467
533
# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload
468
534
# FetchContent calls. As these are internal cmake properties, this method should be used carefully
469
535
# and may need modification in future CMake versions. Source:
@@ -534,9 +600,10 @@ function(CPMAddPackage)
534
600
GIT_SHALLOW
535
601
EXCLUDE_FROM_ALL
536
602
SOURCE_SUBDIR
603
+ CUSTOM_CACHE_KEY
537
604
)
538
605
539
- set (multiValueArgs URL OPTIONS DOWNLOAD_COMMAND)
606
+ set (multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES )
540
607
541
608
cmake_parse_arguments (CPM_ARGS "" "${oneValueArgs} " "${multiValueArgs} " "${ARGN} " )
542
609
@@ -627,6 +694,7 @@ function(CPMAddPackage)
627
694
SOURCE_DIR "${PACKAGE_SOURCE} "
628
695
EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL} "
629
696
SYSTEM "${CPM_ARGS_SYSTEM} "
697
+ PATCHES "${CPM_ARGS_PATCHES} "
630
698
OPTIONS "${CPM_ARGS_OPTIONS} "
631
699
SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR} "
632
700
DOWNLOAD_ONLY "${DOWNLOAD_ONLY} "
@@ -682,6 +750,8 @@ function(CPMAddPackage)
682
750
set (CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR} /_deps)
683
751
endif ()
684
752
753
+ cpm_add_patches(${CPM_ARGS_PATCHES} )
754
+
685
755
if (DEFINED CPM_ARGS_DOWNLOAD_COMMAND)
686
756
list (APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND} )
687
757
elseif (DEFINED CPM_ARGS_SOURCE_DIR)
@@ -704,7 +774,10 @@ function(CPMAddPackage)
704
774
string (TOLOWER ${CPM_ARGS_NAME} lower_case_name)
705
775
set (origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS} )
706
776
list (SORT origin_parameters)
707
- if (CPM_USE_NAMED_CACHE_DIRECTORIES)
777
+ if (CPM_ARGS_CUSTOM_CACHE_KEY)
778
+ # Application set a custom unique directory name
779
+ set (download_directory ${CPM_SOURCE_CACHE} /${lower_case_name} /${CPM_ARGS_CUSTOM_CACHE_KEY} )
780
+ elseif (CPM_USE_NAMED_CACHE_DIRECTORIES)
708
781
string (SHA1 origin_hash "${origin_parameters} ;NEW_CACHE_STRUCTURE_TAG" )
709
782
set (download_directory ${CPM_SOURCE_CACHE} /${lower_case_name} /${origin_hash} /${CPM_ARGS_NAME} )
710
783
else ()
@@ -792,14 +865,38 @@ function(CPMAddPackage)
792
865
)
793
866
794
867
if (NOT CPM_SKIP_FETCH)
868
+ # CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare.
869
+ # Calling FetchContent_MakeAvailable will then internally forward these options to
870
+ # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and
871
+ # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30.
872
+ set (fetchContentDeclareExtraArgs "" )
873
+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0" )
874
+ if (${CPM_ARGS_EXCLUDE_FROM_ALL} )
875
+ list (APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL )
876
+ endif ()
877
+ if (${CPM_ARGS_SYSTEM} )
878
+ list (APPEND fetchContentDeclareExtraArgs SYSTEM )
879
+ endif ()
880
+ if (DEFINED CPM_ARGS_SOURCE_SUBDIR)
881
+ list (APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR} )
882
+ endif ()
883
+ # For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory
884
+ if (CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY)
885
+ foreach (OPTION ${CPM_ARGS_OPTIONS} )
886
+ cpm_parse_option("${OPTION} " )
887
+ set (${OPTION_KEY} "${OPTION_VALUE} " )
888
+ endforeach ()
889
+ endif ()
890
+ endif ()
795
891
cpm_declare_fetch(
796
- "${CPM_ARGS_NAME} " " ${CPM_ARGS_VERSION} " " ${PACKAGE_INFO} " "${CPM_ARGS_UNPARSED_ARGUMENTS} "
892
+ "${CPM_ARGS_NAME} " ${fetchContentDeclareExtraArgs} "${CPM_ARGS_UNPARSED_ARGUMENTS} "
797
893
)
798
- cpm_fetch_package("${CPM_ARGS_NAME} " populated)
894
+
895
+ cpm_fetch_package("${CPM_ARGS_NAME} " ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS} )
799
896
if (CPM_SOURCE_CACHE AND download_directory)
800
897
file (LOCK ${download_directory} /../cmake.lock RELEASE)
801
898
endif ()
802
- if (${populated} )
899
+ if (${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.28.0" )
803
900
cpm_add_subdirectory(
804
901
"${CPM_ARGS_NAME} "
805
902
"${DOWNLOAD_ONLY} "
@@ -910,7 +1007,7 @@ function(CPMGetPackageVersion PACKAGE OUTPUT)
910
1007
endfunction ()
911
1008
912
1009
# declares a package in FetchContent_Declare
913
- function (cpm_declare_fetch PACKAGE VERSION INFO )
1010
+ function (cpm_declare_fetch PACKAGE)
914
1011
if (${CPM_DRY_RUN} )
915
1012
cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)" )
916
1013
return ()
@@ -986,7 +1083,7 @@ endfunction()
986
1083
987
1084
# downloads a previously declared package via FetchContent and exports the variables
988
1085
# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope
989
- function (cpm_fetch_package PACKAGE populated)
1086
+ function (cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated)
990
1087
set (${populated}
991
1088
FALSE
992
1089
PARENT_SCOPE
@@ -1001,7 +1098,24 @@ function(cpm_fetch_package PACKAGE populated)
1001
1098
string (TOLOWER "${PACKAGE} " lower_case_name)
1002
1099
1003
1100
if (NOT ${lower_case_name} _POPULATED)
1004
- FetchContent_Populate(${PACKAGE} )
1101
+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0" )
1102
+ if (DOWNLOAD_ONLY)
1103
+ # MakeAvailable will call add_subdirectory internally which is not what we want when
1104
+ # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the
1105
+ # build
1106
+ FetchContent_Populate(
1107
+ ${PACKAGE}
1108
+ SOURCE_DIR "${CPM_FETCHCONTENT_BASE_DIR} /${lower_case_name} -src"
1109
+ BINARY_DIR "${CPM_FETCHCONTENT_BASE_DIR} /${lower_case_name} -build"
1110
+ SUBBUILD_DIR "${CPM_FETCHCONTENT_BASE_DIR} /${lower_case_name} -subbuild"
1111
+ ${ARGN}
1112
+ )
1113
+ else ()
1114
+ FetchContent_MakeAvailable(${PACKAGE} )
1115
+ endif ()
1116
+ else ()
1117
+ FetchContent_Populate(${PACKAGE} )
1118
+ endif ()
1005
1119
set (${populated}
1006
1120
TRUE
1007
1121
PARENT_SCOPE
@@ -1095,12 +1209,15 @@ function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT)
1095
1209
DOWNLOAD_ONLY
1096
1210
GITHUB_REPOSITORY
1097
1211
GITLAB_REPOSITORY
1212
+ BITBUCKET_REPOSITORY
1098
1213
GIT_REPOSITORY
1099
1214
SOURCE_DIR
1100
1215
FIND_PACKAGE_ARGUMENTS
1101
1216
NO_CACHE
1102
1217
SYSTEM
1103
1218
GIT_SHALLOW
1219
+ EXCLUDE_FROM_ALL
1220
+ SOURCE_SUBDIR
1104
1221
)
1105
1222
set (multiValueArgs URL OPTIONS DOWNLOAD_COMMAND)
1106
1223
cmake_parse_arguments (CPM_ARGS "" "${oneValueArgs} " "${multiValueArgs} " ${ARGN} )
0 commit comments