2 # Download and optionally unpack a file
4 # ocv_download(FILENAME p HASH h URL u1 [u2 ...] DESTINATION_DIR d [ID id] [STATUS s] [UNPACK] [RELATIVE_URL])
7 # URL - full download url (first nonempty value will be chosen)
8 # DESTINATION_DIR - file will be copied to this directory
9 # ID - identifier for project/group of downloaded files
10 # STATUS - passed variable will be updated in parent scope,
11 # function will not fail the build in case of download problem if this option is provided,
12 # but will fail in case when other operations (copy, remove, etc.) failed
13 # UNPACK - downloaded file will be unpacked to DESTINATION_DIR
14 # RELATIVE_URL - if set, then URL is treated as a base, and FILENAME will be appended to it
15 # Note: uses OPENCV_DOWNLOAD_PATH folder as cache, default is <opencv>/.cache
17 set(HELP_OPENCV_DOWNLOAD_PATH "Cache directory for downloaded files")
18 if(DEFINED ENV{OPENCV_DOWNLOAD_PATH})
19 set(OPENCV_DOWNLOAD_PATH "$ENV{OPENCV_DOWNLOAD_PATH}" CACHE PATH "${HELP_OPENCV_DOWNLOAD_PATH}")
21 set(OPENCV_DOWNLOAD_PATH "${OpenCV_SOURCE_DIR}/.cache" CACHE PATH "${HELP_OPENCV_DOWNLOAD_PATH}")
22 set(OPENCV_DOWNLOAD_LOG "${OpenCV_BINARY_DIR}/CMakeDownloadLog.txt")
24 # Init download cache directory and log file
25 if(NOT EXISTS "${OPENCV_DOWNLOAD_PATH}")
26 file(MAKE_DIRECTORY ${OPENCV_DOWNLOAD_PATH})
28 if(NOT EXISTS "${OPENCV_DOWNLOAD_PATH}/.gitignore")
29 file(WRITE "${OPENCV_DOWNLOAD_PATH}/.gitignore" "*\n")
31 file(WRITE "${OPENCV_DOWNLOAD_LOG}" "use_cache \"${OPENCV_DOWNLOAD_PATH}\"\n")
34 function(ocv_download)
35 cmake_parse_arguments(DL "UNPACK;RELATIVE_URL" "FILENAME;HASH;DESTINATION_DIR;ID;STATUS" "URL" ${ARGN})
37 macro(ocv_download_log)
38 file(APPEND "${OPENCV_DOWNLOAD_LOG}" "${ARGN}\n")
41 ocv_assert(DL_FILENAME)
44 ocv_assert(DL_DESTINATION_DIR)
45 if((NOT " ${DL_UNPARSED_ARGUMENTS}" STREQUAL " ")
46 OR DL_FILENAME STREQUAL ""
47 OR DL_HASH STREQUAL ""
49 OR DL_DESTINATION_DIR STREQUAL ""
51 set(msg_level FATAL_ERROR)
53 set(${DL_STATUS} FALSE PARENT_SCOPE)
54 set(msg_level WARNING)
56 message(${msg_level} "ERROR: ocv_download() unsupported arguments: ${ARGV}")
61 set(${DL_STATUS} TRUE PARENT_SCOPE)
64 # Check CMake cache for already processed tasks
65 string(FIND "${DL_DESTINATION_DIR}" "${CMAKE_BINARY_DIR}" DL_BINARY_PATH_POS)
66 if(DL_BINARY_PATH_POS EQUAL 0)
67 set(__file_id "${DL_DESTINATION_DIR}/${DL_FILENAME}")
68 file(RELATIVE_PATH __file_id "${CMAKE_BINARY_DIR}" "${__file_id}")
69 string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" __file_id "${__file_id}")
71 string(TOUPPER ${DL_ID} __id)
72 string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" __id "${__id}")
73 set(OCV_DOWNLOAD_HASH_NAME "OCV_DOWNLOAD_${__id}_HASH_${__file_id}")
75 set(OCV_DOWNLOAD_HASH_NAME "OCV_DOWNLOAD_HASH_${__file_id}")
77 if(" ${${OCV_DOWNLOAD_HASH_NAME}}" STREQUAL " ${DL_HASH}")
78 ocv_download_log("#match_hash_in_cmake_cache \"${OCV_DOWNLOAD_HASH_NAME}\"")
81 unset("${OCV_DOWNLOAD_HASH_NAME}" CACHE)
83 set(OCV_DOWNLOAD_HASH_NAME "")
84 #message(WARNING "Download destination is not in CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}: ${DL_DESTINATION_DIR}")
87 # Select first non-empty url
88 foreach(url ${DL_URL})
95 # Append filename to url if needed
97 set(DL_URL "${DL_URL}${DL_FILENAME}")
105 # Log all calls to file
106 ocv_download_log("do_${mode} \"${DL_FILENAME}\" \"${DL_HASH}\" \"${DL_URL}\" \"${DL_DESTINATION_DIR}\"")
110 set(__msg_prefix "${DL_ID}: ")
112 message(STATUS "${__msg_prefix}Download: ${DL_FILENAME}")
114 # Copy mode: check if copy destination exists and is correct
116 set(COPY_DESTINATION "${DL_DESTINATION_DIR}/${DL_FILENAME}")
117 if(EXISTS "${COPY_DESTINATION}")
118 ocv_download_log("#check_md5 \"${COPY_DESTINATION}\"")
119 file(MD5 "${COPY_DESTINATION}" target_md5)
120 if(target_md5 STREQUAL DL_HASH)
121 ocv_download_log("#match_md5 \"${COPY_DESTINATION}\" \"${target_md5}\"")
122 if(OCV_DOWNLOAD_HASH_NAME)
123 set(${OCV_DOWNLOAD_HASH_NAME} "${DL_HASH}" CACHE INTERNAL "")
127 ocv_download_log("#mismatch_md5 \"${COPY_DESTINATION}\" \"${target_md5}\"")
129 ocv_download_log("#missing \"${COPY_DESTINATION}\"")
135 string(TOLOWER "${DL_ID}" __id)
136 string(REGEX REPLACE "[^a-zA-Z0-9_/ ]" "_" __id "${__id}")
137 set(CACHE_CANDIDATE "${OPENCV_DOWNLOAD_PATH}/${__id}/${DL_HASH}-${DL_FILENAME}")
139 set(CACHE_CANDIDATE "${OPENCV_DOWNLOAD_PATH}/${DL_HASH}-${DL_FILENAME}")
141 if(EXISTS "${CACHE_CANDIDATE}")
142 ocv_download_log("#check_md5 \"${CACHE_CANDIDATE}\"")
143 file(MD5 "${CACHE_CANDIDATE}" target_md5)
144 if(NOT target_md5 STREQUAL DL_HASH)
145 ocv_download_log("#mismatch_md5 \"${CACHE_CANDIDATE}\" \"${target_md5}\"")
146 ocv_download_log("#delete \"${CACHE_CANDIDATE}\"")
147 file(REMOVE ${CACHE_CANDIDATE})
152 if(NOT EXISTS "${CACHE_CANDIDATE}")
153 ocv_download_log("#cmake_download \"${CACHE_CANDIDATE}\" \"${DL_URL}\"")
154 file(DOWNLOAD "${DL_URL}" "${CACHE_CANDIDATE}"
155 INACTIVITY_TIMEOUT 60
159 string(LENGTH "${__log}" __log_length)
160 if(__log_length LESS 65536)
161 string(REPLACE "\n" "\n# " __log "${__log}")
162 ocv_download_log("# ${__log}\n")
164 if(NOT status EQUAL 0)
165 set(msg_level FATAL_ERROR)
166 if(DEFINED DL_STATUS)
167 set(${DL_STATUS} FALSE PARENT_SCOPE)
168 set(msg_level WARNING)
170 if(status MATCHES "Couldn't resolve host name")
172 =======================================================================
173 Couldn't download files from the Internet.
174 Please check the Internet access on this host.
175 =======================================================================
177 elseif(status MATCHES "Couldn't connect to server")
179 =======================================================================
180 Couldn't connect to server from the Internet.
181 Perhaps direct connections are not allowed in the current network.
182 To use proxy please check/specify these environment variables:
183 - http_proxy/https_proxy
184 - and/or HTTP_PROXY/HTTPS_PROXY
185 =======================================================================
188 message(${msg_level} "${__msg_prefix}Download failed: ${status}
189 For details please refer to the download log file:
190 ${OPENCV_DOWNLOAD_LOG}
195 # Don't remove this code, because EXPECTED_MD5 parameter doesn't fail "file(DOWNLOAD)" step on wrong hash
196 ocv_download_log("#check_md5 \"${CACHE_CANDIDATE}\"")
197 file(MD5 "${CACHE_CANDIDATE}" target_md5)
198 if(NOT target_md5 STREQUAL DL_HASH)
199 ocv_download_log("#mismatch_md5 \"${CACHE_CANDIDATE}\" \"${target_md5}\"")
200 set(msg_level FATAL_ERROR)
201 if(DEFINED DL_STATUS)
202 set(${DL_STATUS} FALSE PARENT_SCOPE)
203 set(msg_level WARNING)
205 message(${msg_level} "${__msg_prefix}Hash mismatch: ${target_md5}")
212 if(EXISTS "${DL_DESTINATION_DIR}")
213 ocv_download_log("#remove_unpack \"${DL_DESTINATION_DIR}\"")
214 file(REMOVE_RECURSE "${DL_DESTINATION_DIR}")
216 ocv_download_log("#mkdir \"${DL_DESTINATION_DIR}\"")
217 file(MAKE_DIRECTORY "${DL_DESTINATION_DIR}")
218 ocv_download_log("#unpack \"${DL_DESTINATION_DIR}\" \"${CACHE_CANDIDATE}\"")
219 execute_process(COMMAND "${CMAKE_COMMAND}" -E tar xz "${CACHE_CANDIDATE}"
220 WORKING_DIRECTORY "${DL_DESTINATION_DIR}"
223 message(FATAL_ERROR "${__msg_prefix}Unpack failed: ${res}")
226 ocv_download_log("#copy \"${COPY_DESTINATION}\" \"${CACHE_CANDIDATE}\"")
227 execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CACHE_CANDIDATE}" "${COPY_DESTINATION}"
230 message(FATAL_ERROR "${__msg_prefix}Copy failed: ${res}")
234 if(OCV_DOWNLOAD_HASH_NAME)
235 set(${OCV_DOWNLOAD_HASH_NAME} "${DL_HASH}" CACHE INTERNAL "")