aboutsummaryrefslogtreecommitdiff
path: root/cmake.deps/cmake/DownloadAndExtractFile.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake.deps/cmake/DownloadAndExtractFile.cmake')
-rw-r--r--cmake.deps/cmake/DownloadAndExtractFile.cmake195
1 files changed, 195 insertions, 0 deletions
diff --git a/cmake.deps/cmake/DownloadAndExtractFile.cmake b/cmake.deps/cmake/DownloadAndExtractFile.cmake
new file mode 100644
index 0000000000..abb1ddc81a
--- /dev/null
+++ b/cmake.deps/cmake/DownloadAndExtractFile.cmake
@@ -0,0 +1,195 @@
+if(NOT DEFINED PREFIX)
+ message(FATAL_ERROR "PREFIX must be defined.")
+endif()
+
+if(NOT DEFINED URL)
+ message(FATAL_ERROR "URL must be defined.")
+endif()
+
+if(NOT DEFINED DOWNLOAD_DIR)
+ message(FATAL_ERROR "DOWNLOAD_DIR must be defined.")
+endif()
+
+if(NOT DEFINED EXPECTED_SHA256)
+ message(FATAL_ERROR "EXPECTED_SHA256 must be defined.")
+endif()
+
+if(NOT DEFINED TARGET)
+ message(FATAL_ERROR "TARGET must be defined.")
+endif()
+
+if(NOT DEFINED SRC_DIR)
+ set(SRC_DIR ${PREFIX}/src/${TARGET})
+endif()
+set(BINARY_DIR ${PREFIX}/src/${TARGET}-build)
+
+# Check whether the source has been downloaded. If true, skip it.
+# Useful for external downloads like homebrew.
+if(USE_EXISTING_SRC_DIR)
+ if(EXISTS "${SRC_DIR}" AND IS_DIRECTORY "${SRC_DIR}")
+ file(GLOB EXISTED_FILES "${SRC_DIR}/*")
+ if(EXISTED_FILES)
+ message(STATUS "${SRC_DIR} is found and not empty, skipping download and extraction. ")
+ return()
+ endif()
+ endif()
+ message(FATAL_ERROR "USE_EXISTING_SRC_DIR set to ON, but '${SRC_DIR}' does not exist or is empty.")
+endif()
+
+# Taken from ExternalProject_Add. Let's hope we can drop this one day when
+# ExternalProject_Add allows you to disable SHOW_PROGRESS on the file download.
+if(TIMEOUT)
+ set(timeout_args TIMEOUT ${timeout})
+ set(timeout_msg "${timeout} seconds")
+else()
+ set(timeout_args "")
+ set(timeout_msg "none")
+endif()
+
+string(REGEX MATCH "[^/\\?]*$" fname "${URL}")
+if(NOT "${fname}" MATCHES "(\\.|=)(bz2|tar|tgz|tar\\.gz|zip)$")
+ string(REGEX MATCH "([^/\\?]+(\\.|=)(bz2|tar|tgz|tar\\.gz|zip))/.*$" match_result "${URL}")
+ set(fname "${CMAKE_MATCH_1}")
+endif()
+if(NOT "${fname}" MATCHES "(\\.|=)(bz2|tar|tgz|tar\\.gz|zip)$")
+ message(FATAL_ERROR "Could not extract tarball filename from url:\n ${url}")
+endif()
+string(REPLACE ";" "-" fname "${fname}")
+
+set(file ${DOWNLOAD_DIR}/${fname})
+message(STATUS "file: ${file}")
+
+set(EXISTING_SHA256 "")
+if(EXISTS ${file})
+ file(SHA256 ${file} EXISTING_SHA256)
+endif()
+
+if(NOT EXISTING_SHA256 STREQUAL ${EXPECTED_SHA256})
+ message(STATUS "downloading...
+ src='${URL}'
+ dst='${file}'
+ timeout='${timeout_msg}'")
+
+ file(DOWNLOAD ${URL} ${file}
+ ${timeout_args}
+ ${hash_args}
+ STATUS status
+ LOG log)
+
+ list(GET status 0 status_code)
+ list(GET status 1 status_string)
+
+ if(NOT status_code EQUAL 0)
+ # Retry on certain errors, e.g. CURLE_COULDNT_RESOLVE_HOST, which is often
+ # seen with libtermkey (www.leonerd.org.uk).
+ if((status_code EQUAL 6) # "Couldn't resolve host name"
+ OR (status_code EQUAL 7)) # "Couldn't connect to server"
+ message(STATUS "warning: retrying '${URL}' (${status_string}, status ${status_code})")
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 10)
+ file(DOWNLOAD ${URL} ${file}
+ ${timeout_args}
+ ${hash_args}
+ STATUS status
+ LOG log)
+ list(GET status 0 status_code)
+ list(GET status 1 status_string)
+ endif()
+ if(NOT status_code EQUAL 0)
+ message(FATAL_ERROR "error: downloading '${URL}' failed
+ status_code: ${status_code}
+ status_string: ${status_string}
+ log: ${log}
+ ")
+ endif()
+ endif()
+endif()
+
+set(NULL_SHA256 "0000000000000000000000000000000000000000000000000000000000000000")
+
+# Allow users to use "SKIP" or "skip" as the sha256 to skip checking the hash.
+# You can still use the all zeros hash too.
+if((EXPECTED_SHA256 STREQUAL "SKIP") OR (EXPECTED_SHA256 STREQUAL "skip"))
+ set(EXPECTED_SHA256 ${NULL_SHA256})
+endif()
+
+# We could avoid computing the SHA256 entirely if a NULL_SHA256 was given,
+# but we want to warn users of an empty file.
+file(SHA256 ${file} ACTUAL_SHA256)
+if(ACTUAL_SHA256 STREQUAL "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
+ # File was empty. It's likely due to lack of SSL support.
+ message(FATAL_ERROR
+ "Failed to download ${URL}. The file is empty and likely means CMake "
+ "was built without SSL support. Please use a version of CMake with "
+ "proper SSL support. See "
+ "https://github.com/neovim/neovim/wiki/Building-Neovim#build-prerequisites "
+ "for more information.")
+elseif((NOT EXPECTED_SHA256 STREQUAL NULL_SHA256) AND
+ (NOT EXPECTED_SHA256 STREQUAL ACTUAL_SHA256))
+ # Wasn't a NULL SHA256 and we didn't match, so we fail.
+ message(FATAL_ERROR
+ "Failed to download ${URL}. Expected a SHA256 of "
+ "${EXPECTED_SHA256} but got ${ACTUAL_SHA256} instead.")
+endif()
+
+message(STATUS "downloading... done")
+
+# Slurped from a generated extract-TARGET.cmake file.
+message(STATUS "extracting...
+ src='${file}'
+ dst='${SRC_DIR}'")
+
+if(NOT EXISTS "${file}")
+ message(FATAL_ERROR "error: file to extract does not exist: '${file}'")
+endif()
+
+# Prepare a space for extracting:
+#
+set(i 1234)
+while(EXISTS "${SRC_DIR}/../ex-${TARGET}${i}")
+ math(EXPR i "${i} + 1")
+endwhile()
+set(ut_dir "${SRC_DIR}/../ex-${TARGET}${i}")
+file(MAKE_DIRECTORY "${ut_dir}")
+
+# Extract it:
+#
+message(STATUS "extracting... [tar xfz]")
+execute_process(COMMAND ${CMAKE_COMMAND} -E tar xfz ${file}
+ WORKING_DIRECTORY ${ut_dir}
+ RESULT_VARIABLE rv)
+
+if(NOT rv EQUAL 0)
+ message(STATUS "extracting... [error clean up]")
+ file(REMOVE_RECURSE "${ut_dir}")
+ message(FATAL_ERROR "error: extract of '${file}' failed")
+endif()
+
+# Analyze what came out of the tar file:
+#
+message(STATUS "extracting... [analysis]")
+file(GLOB contents "${ut_dir}/*")
+list(LENGTH contents n)
+if(NOT n EQUAL 1 OR NOT IS_DIRECTORY "${contents}")
+ set(contents "${ut_dir}")
+endif()
+
+# Move "the one" directory to the final directory:
+#
+message(STATUS "extracting... [rename]")
+file(REMOVE_RECURSE ${SRC_DIR})
+get_filename_component(contents ${contents} ABSOLUTE)
+file(RENAME ${contents} ${SRC_DIR})
+
+# Remove any existing BINARY_DIR, to force a new build.
+# Without this a necessary output (e.g. libluv.a) might not be updated/installed.
+#
+message(STATUS "extracting... [clean binary dir]")
+file(REMOVE_RECURSE ${BINARY_DIR})
+file(MAKE_DIRECTORY ${BINARY_DIR})
+
+# Clean up:
+#
+message(STATUS "extracting... [clean up]")
+file(REMOVE_RECURSE "${ut_dir}")
+
+message(STATUS "extracting... done")