diff --git a/cmake/modules/ExternalProject.cmake b/cmake/modules/ExternalProject.cmake
index 966857b535e41289731d739a6fef01c6f0c9795d..a285b6c4df6b9cd65165c81dc7c0d9a22316d771 100644
--- a/cmake/modules/ExternalProject.cmake
+++ b/cmake/modules/ExternalProject.cmake
@@ -311,8 +311,15 @@ if(error_code)
   message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\")
 endif()
 
+if(NOT \"x${EP_CACHE_DIR}\" STREQUAL \"x\")
+  get_filename_component(ext_name \"${work_dir}\" NAME)
+  if(EXISTS \"${EP_CACHE_DIR}/\${ext_name}-reference\")
+    set(_git_reference --reference \"${EP_CACHE_DIR}/\${ext_name}-reference\" --dissociate)
+  endif()
+endif()
+
 execute_process(
-  COMMAND \"${git_EXECUTABLE}\" clone \"${git_repository}\" \"${src_name}\"
+  COMMAND \"${git_EXECUTABLE}\" clone \${_git_reference} \"${git_repository}\" \"${src_name}\"
   WORKING_DIRECTORY \"${work_dir}\"
   RESULT_VARIABLE error_code
   )
@@ -320,6 +327,12 @@ if(error_code)
   message(FATAL_ERROR \"Failed to clone repository: '${git_repository}'\")
 endif()
 
+if(_git_reference)
+  if(NOT EXISTS \"${EP_CACHE_DIR}/\${ext_name}-reference\")
+    file(COPY \"${work_dir}/${src_name}/\" DESTINATION \"${EP_CACHE_DIR}/\${ext_name}-reference\")
+  endif()
+endif()
+
 execute_process(
   COMMAND \"${git_EXECUTABLE}\" checkout ${git_tag}
   WORKING_DIRECTORY \"${work_dir}/${src_name}\"
@@ -472,14 +485,33 @@ function(_ep_write_downloadfile_script script_filename remote local timeout hash
 ${tls_verify}
 ${tls_cainfo}
 
-file(DOWNLOAD
-  \"${remote}\"
-  \"${local}\"
-  SHOW_PROGRESS
-  ${hash_args}
-  ${timeout_args}
-  STATUS status
-  LOG log)
+if(\"x${EP_CACHE_DIR}\" STREQUAL \"x\")
+  file(DOWNLOAD
+    \"${remote}\"
+    \"${local}\"
+    SHOW_PROGRESS
+    ${hash_args}
+    ${timeout_args}
+    STATUS status
+    LOG log)
+else()
+  get_filename_component(fname \"${local}\" NAME)
+  if(EXISTS \"${EP_CACHE_DIR}/\${fname}\")
+    get_filename_component(ddir \"${local}\" PATH)
+    file(COPY \"${EP_CACHE_DIR}/\${fname}\" DESTINATION \"\${ddir}\")
+    set(status 0 \"copy from cache\")
+  else()
+    file(DOWNLOAD
+      \"${remote}\"
+      \"${local}\"
+      SHOW_PROGRESS
+      ${hash_args}
+      ${timeout_args}
+      STATUS status
+      LOG log)
+    file(COPY \"${local}\" DESTINATION \"${EP_CACHE_DIR}\")
+  endif()
+endif()
 
 list(GET status 0 status_code)
 list(GET status 1 status_string)