@@ -42,7 +42,7 @@ if(NOT COMMAND cpm_message)
42
42
endfunction ()
43
43
endif ()
44
44
45
- set (CURRENT_CPM_VERSION 0.39.0 )
45
+ set (CURRENT_CPM_VERSION 0.40.1 )
46
46
47
47
get_filename_component (CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR} " REALPATH)
48
48
if (CPM_DIRECTORY)
@@ -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,69 @@ 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` 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 ${extra_search_path} DIRECTORY )
485
+ get_filename_component (extra_search_path ${extra_search_path} DIRECTORY )
486
+ find_program (PATCH_EXECUTABLE patch HINTS "${extra_search_path} /usr/bin" )
487
+ endif ()
488
+ endif ()
489
+ if (NOT PATCH_EXECUTABLE)
490
+ message (FATAL_ERROR "Couldn't find `patch` executable to use with PATCHES keyword." )
491
+ endif ()
492
+
493
+ # Create a temporary
494
+ set (temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS} )
495
+
496
+ # Ensure each file exists (or error out) and add it to the list.
497
+ set (first_item True )
498
+ foreach (PATCH_FILE ${ARGN} )
499
+ # Make sure the patch file exists, if we can't find it, try again in the current directory.
500
+ if (NOT EXISTS "${PATCH_FILE} " )
501
+ if (NOT EXISTS "${CMAKE_CURRENT_LIST_DIR} /${PATCH_FILE} " )
502
+ message (FATAL_ERROR "Couldn't find patch file: '${PATCH_FILE} '" )
503
+ endif ()
504
+ set (PATCH_FILE "${CMAKE_CURRENT_LIST_DIR} /${PATCH_FILE} " )
505
+ endif ()
506
+
507
+ # Convert to absolute path for use with patch file command.
508
+ get_filename_component (PATCH_FILE "${PATCH_FILE} " ABSOLUTE )
509
+
510
+ # The first patch entry must be preceded by "PATCH_COMMAND" while the following items are
511
+ # preceded by "&&".
512
+ if (first_item)
513
+ set (first_item False )
514
+ list (APPEND temp_list "PATCH_COMMAND" )
515
+ else ()
516
+ list (APPEND temp_list "&&" )
517
+ endif ()
518
+ # Add the patch command to the list
519
+ list (APPEND temp_list "${PATCH_EXECUTABLE} " "-p1" "<" "${PATCH_FILE} " )
520
+ endforeach ()
521
+
522
+ # Move temp out into parent scope.
523
+ set (CPM_ARGS_UNPARSED_ARGUMENTS
524
+ ${temp_list}
525
+ PARENT_SCOPE
526
+ )
527
+
528
+ endfunction ()
529
+
467
530
# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload
468
531
# FetchContent calls. As these are internal cmake properties, this method should be used carefully
469
532
# and may need modification in future CMake versions. Source:
@@ -537,7 +600,7 @@ function(CPMAddPackage)
537
600
CUSTOM_CACHE_KEY
538
601
)
539
602
540
- set (multiValueArgs URL OPTIONS DOWNLOAD_COMMAND)
603
+ set (multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES )
541
604
542
605
cmake_parse_arguments (CPM_ARGS "" "${oneValueArgs} " "${multiValueArgs} " "${ARGN} " )
543
606
@@ -628,6 +691,7 @@ function(CPMAddPackage)
628
691
SOURCE_DIR "${PACKAGE_SOURCE} "
629
692
EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL} "
630
693
SYSTEM "${CPM_ARGS_SYSTEM} "
694
+ PATCHES "${CPM_ARGS_PATCHES} "
631
695
OPTIONS "${CPM_ARGS_OPTIONS} "
632
696
SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR} "
633
697
DOWNLOAD_ONLY "${DOWNLOAD_ONLY} "
@@ -683,6 +747,8 @@ function(CPMAddPackage)
683
747
set (CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR} /_deps)
684
748
endif ()
685
749
750
+ cpm_add_patches(${CPM_ARGS_PATCHES} )
751
+
686
752
if (DEFINED CPM_ARGS_DOWNLOAD_COMMAND)
687
753
list (APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND} )
688
754
elseif (DEFINED CPM_ARGS_SOURCE_DIR)
@@ -796,14 +862,38 @@ function(CPMAddPackage)
796
862
)
797
863
798
864
if (NOT CPM_SKIP_FETCH)
865
+ # CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare.
866
+ # Calling FetchContent_MakeAvailable will then internally forward these options to
867
+ # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and
868
+ # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30.
869
+ set (fetchContentDeclareExtraArgs "" )
870
+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0" )
871
+ if (${CPM_ARGS_EXCLUDE_FROM_ALL} )
872
+ list (APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL )
873
+ endif ()
874
+ if (${CPM_ARGS_SYSTEM} )
875
+ list (APPEND fetchContentDeclareExtraArgs SYSTEM )
876
+ endif ()
877
+ if (DEFINED CPM_ARGS_SOURCE_SUBDIR)
878
+ list (APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR} )
879
+ endif ()
880
+ # For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory
881
+ if (CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY)
882
+ foreach (OPTION ${CPM_ARGS_OPTIONS} )
883
+ cpm_parse_option("${OPTION} " )
884
+ set (${OPTION_KEY} "${OPTION_VALUE} " )
885
+ endforeach ()
886
+ endif ()
887
+ endif ()
799
888
cpm_declare_fetch(
800
- "${CPM_ARGS_NAME} " " ${CPM_ARGS_VERSION} " " ${PACKAGE_INFO} " "${CPM_ARGS_UNPARSED_ARGUMENTS} "
889
+ "${CPM_ARGS_NAME} " ${fetchContentDeclareExtraArgs} "${CPM_ARGS_UNPARSED_ARGUMENTS} "
801
890
)
802
- cpm_fetch_package("${CPM_ARGS_NAME} " populated)
891
+
892
+ cpm_fetch_package("${CPM_ARGS_NAME} " ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS} )
803
893
if (CPM_SOURCE_CACHE AND download_directory)
804
894
file (LOCK ${download_directory} /../cmake.lock RELEASE)
805
895
endif ()
806
- if (${populated} )
896
+ if (${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.28.0" )
807
897
cpm_add_subdirectory(
808
898
"${CPM_ARGS_NAME} "
809
899
"${DOWNLOAD_ONLY} "
@@ -914,7 +1004,7 @@ function(CPMGetPackageVersion PACKAGE OUTPUT)
914
1004
endfunction ()
915
1005
916
1006
# declares a package in FetchContent_Declare
917
- function (cpm_declare_fetch PACKAGE VERSION INFO )
1007
+ function (cpm_declare_fetch PACKAGE)
918
1008
if (${CPM_DRY_RUN} )
919
1009
cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)" )
920
1010
return ()
@@ -990,7 +1080,7 @@ endfunction()
990
1080
991
1081
# downloads a previously declared package via FetchContent and exports the variables
992
1082
# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope
993
- function (cpm_fetch_package PACKAGE populated)
1083
+ function (cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated)
994
1084
set (${populated}
995
1085
FALSE
996
1086
PARENT_SCOPE
@@ -1005,7 +1095,24 @@ function(cpm_fetch_package PACKAGE populated)
1005
1095
string (TOLOWER "${PACKAGE} " lower_case_name)
1006
1096
1007
1097
if (NOT ${lower_case_name} _POPULATED)
1008
- FetchContent_Populate(${PACKAGE} )
1098
+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0" )
1099
+ if (DOWNLOAD_ONLY)
1100
+ # MakeAvailable will call add_subdirectory internally which is not what we want when
1101
+ # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the
1102
+ # build
1103
+ FetchContent_Populate(
1104
+ ${PACKAGE}
1105
+ SOURCE_DIR "${CPM_FETCHCONTENT_BASE_DIR} /${lower_case_name} -src"
1106
+ BINARY_DIR "${CPM_FETCHCONTENT_BASE_DIR} /${lower_case_name} -build"
1107
+ SUBBUILD_DIR "${CPM_FETCHCONTENT_BASE_DIR} /${lower_case_name} -subbuild"
1108
+ ${ARGN}
1109
+ )
1110
+ else ()
1111
+ FetchContent_MakeAvailable(${PACKAGE} )
1112
+ endif ()
1113
+ else ()
1114
+ FetchContent_Populate(${PACKAGE} )
1115
+ endif ()
1009
1116
set (${populated}
1010
1117
TRUE
1011
1118
PARENT_SCOPE
0 commit comments