#
# Download and optionally unpack a file
#
# ocv_download(FILENAME p HASH h URL u1 [u2 ...] DESTINATION_DIR d [ID id] [STATUS s] [UNPACK] [RELATIVE_URL])
# FILENAME - filename
# HASH - MD5 hash
# URL - full download url (first nonempty value will be chosen)
# DESTINATION_DIR - file will be copied to this directory
# ID - identifier for project/group of downloaded files
# STATUS - passed variable will be updated in parent scope,
# function will not fail the build in case of download problem if this option is provided,
# but will fail in case when other operations (copy, remove, etc.) failed
# UNPACK - downloaded file will be unpacked to DESTINATION_DIR
# RELATIVE_URL - if set, then URL is treated as a base, and FILENAME will be appended to it
# Note: uses OPENCV_DOWNLOAD_PATH folder as cache, default is <opencv>/.cache
set ( HELP_OPENCV_DOWNLOAD_PATH "Cache directory for downloaded files" )
if ( DEFINED ENV{OPENCV_DOWNLOAD_PATH} )
set ( OPENCV_DOWNLOAD_PATH "$ENV{OPENCV_DOWNLOAD_PATH}" CACHE PATH "${HELP_OPENCV_DOWNLOAD_PATH}" )
endif ( )
set ( OPENCV_DOWNLOAD_PATH "${OpenCV_SOURCE_DIR}/.cache" CACHE PATH "${HELP_OPENCV_DOWNLOAD_PATH}" )
set ( OPENCV_DOWNLOAD_LOG "${OpenCV_BINARY_DIR}/CMakeDownloadLog.txt" )
set ( OPENCV_DOWNLOAD_WITH_CURL "${OpenCV_BINARY_DIR}/download_with_curl.sh" )
set ( OPENCV_DOWNLOAD_WITH_WGET "${OpenCV_BINARY_DIR}/download_with_wget.sh" )
set ( OPENCV_DOWNLOAD_TRIES_LIST 1 CACHE STRING "List of download tries" ) # a list
set ( OPENCV_DOWNLOAD_PARAMS INACTIVITY_TIMEOUT 60 TIMEOUT 600 CACHE STRING "Download parameters to be passed to file(DOWNLOAD ...)" )
mark_as_advanced ( OPENCV_DOWNLOAD_TRIES_LIST OPENCV_DOWNLOAD_PARAMS )
# Init download cache directory and log file and helper scripts
if ( NOT EXISTS "${OPENCV_DOWNLOAD_PATH}" )
file ( MAKE_DIRECTORY ${ OPENCV_DOWNLOAD_PATH } )
endif ( )
if ( NOT EXISTS "${OPENCV_DOWNLOAD_PATH}/.gitignore" )
file ( WRITE "${OPENCV_DOWNLOAD_PATH}/.gitignore" "*\n" )
endif ( )
file ( WRITE "${OPENCV_DOWNLOAD_LOG}" "#use_cache \" ${ OPENCV_DOWNLOAD_PATH } \"\n")
file ( REMOVE "${OPENCV_DOWNLOAD_WITH_CURL}" )
file ( REMOVE "${OPENCV_DOWNLOAD_WITH_WGET}" )
ocv_check_environment_variables ( OPENCV_DOWNLOAD_MIRROR_ID )
function ( ocv_init_download_mirror )
if ( NOT DEFINED OPENCV_DOWNLOAD_MIRROR_ID )
# Run `git remote get-url origin` to get remote source
execute_process (
C O M M A N D
g i t r e m o t e g e t - u r l o r i g i n
W O R K I N G _ D I R E C T O R Y
$ { C M A K E _ S O U R C E _ D I R }
R E S U L T _ V A R I A B L E
R E S U L T _ S T A T U S
O U T P U T _ V A R I A B L E
O C V _ G I T _ O R I G I N _ U R L _ O U T P U T
E R R O R _ Q U I E T
)
# if non-git, OCV_GIT_ORIGIN_URL_OUTPUT is empty
if ( NOT OCV_GIT_ORIGIN_URL_OUTPUT )
message ( STATUS "ocv_init_download: OpenCV source tree is not fetched as git repository. 3rdparty resources will be downloaded from github.com by default." )
return ( )
else ( )
# Check if git origin is github.com
string ( FIND "${OCV_GIT_ORIGIN_URL_OUTPUT}" "github.com" _found_github )
if ( NOT ${ _found_github } EQUAL -1 )
set ( OPENCV_DOWNLOAD_MIRROR_ID "github" CACHE STRING "" )
endif ( )
# Check if git origin is gitcode.net
string ( FIND "${OCV_GIT_ORIGIN_URL_OUTPUT}" "gitcode.net" _found_gitcode )
if ( NOT ${ _found_gitcode } EQUAL -1 )
set ( OPENCV_DOWNLOAD_MIRROR_ID "gitcode" CACHE STRING "" )
endif ( )
endif ( )
endif ( )
if ( OPENCV_DOWNLOAD_MIRROR_ID STREQUAL "gitcode" OR OPENCV_DOWNLOAD_MIRROR_ID STREQUAL "custom" )
message ( STATUS "ocv_init_download: Using ${OPENCV_DOWNLOAD_MIRROR_ID}-hosted mirror to download 3rdparty components." )
ocv_cmake_hook_append ( OPENCV_DOWNLOAD_PRE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/mirrors/${OPENCV_DOWNLOAD_MIRROR_ID}.cmake" )
elseif ( OPENCV_DOWNLOAD_MIRROR_ID STREQUAL "github" )
return ( )
else ( )
message ( STATUS "ocv_init_download: Unable to recognize git server of OpenCV source code. Using github.com to download 3rdparty components." )
endif ( )
endfunction ( )
function ( ocv_download )
cmake_parse_arguments ( DL "UNPACK;RELATIVE_URL" "FILENAME;HASH;DESTINATION_DIR;ID;STATUS" "URL" ${ ARGN } )
function ( ocv_download_log )
file ( APPEND "${OPENCV_DOWNLOAD_LOG}" "${ARGN}\n" )
endfunction ( )
ocv_assert ( DL_FILENAME )
ocv_assert ( DL_HASH )
ocv_assert ( DL_URL )
ocv_assert ( DL_DESTINATION_DIR )
if ( ( NOT " ${DL_UNPARSED_ARGUMENTS}" STREQUAL " " )
O R D L _ F I L E N A M E S T R E Q U A L " "
O R D L _ H A S H S T R E Q U A L " "
O R D L _ U R L S T R E Q U A L " "
O R D L _ D E S T I N A T I O N _ D I R S T R E Q U A L " "
)
set ( msg_level FATAL_ERROR )
if ( DEFINED DL_STATUS )
set ( ${ DL_STATUS } FALSE PARENT_SCOPE )
set ( msg_level WARNING )
endif ( )
message ( ${ msg_level } "ERROR: ocv_download() unsupported arguments: ${ARGV}" )
return ( )
endif ( )
if ( DEFINED DL_STATUS )
set ( ${ DL_STATUS } TRUE PARENT_SCOPE )
endif ( )
ocv_cmake_hook ( OPENCV_DOWNLOAD_PRE )
# Check CMake cache for already processed tasks
string ( FIND "${DL_DESTINATION_DIR}" "${CMAKE_BINARY_DIR}" DL_BINARY_PATH_POS )
if ( DL_BINARY_PATH_POS EQUAL 0 )
set ( __file_id "${DL_DESTINATION_DIR}/${DL_FILENAME}" )
file ( RELATIVE_PATH __file_id "${CMAKE_BINARY_DIR}" "${__file_id}" )
string ( REGEX REPLACE "[^a-zA-Z0-9_]" "_" __file_id "${__file_id}" )
if ( DL_ID )
string ( TOUPPER ${ DL_ID } __id )
string ( REGEX REPLACE "[^a-zA-Z0-9_]" "_" __id "${__id}" )
set ( OCV_DOWNLOAD_HASH_NAME "OCV_DOWNLOAD_${__id}_HASH_${__file_id}" )
else ( )
set ( OCV_DOWNLOAD_HASH_NAME "OCV_DOWNLOAD_HASH_${__file_id}" )
endif ( )
if ( " ${${OCV_DOWNLOAD_HASH_NAME}}" STREQUAL " ${DL_HASH}" )
ocv_download_log ( "#match_hash_in_cmake_cache \" ${ OCV_DOWNLOAD_HASH_NAME } \"")
return ( )
endif ( )
unset ( "${OCV_DOWNLOAD_HASH_NAME}" CACHE )
else ( )
set ( OCV_DOWNLOAD_HASH_NAME "" )
#message(WARNING "Download destination is not in CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}: ${DL_DESTINATION_DIR}")
endif ( )
# Select first non-empty url
foreach ( url ${ DL_URL } )
if ( url )
set ( DL_URL "${url}" )
break ( )
endif ( )
endforeach ( )
# Append filename to url if needed
if ( DL_RELATIVE_URL )
set ( DL_URL "${DL_URL}${DL_FILENAME}" )
endif ( )
set ( mode "copy" )
if ( DL_UNPACK )
set ( mode "unpack" )
endif ( )
# Log all calls to file
ocv_download_log ( "#do_${mode} \" ${ DL_FILENAME } \" \"${DL_HASH}\" \"${DL_URL}\" \"${DL_DESTINATION_DIR}\"")
# ... and to console
set ( __msg_prefix "" )
if ( DL_ID )
set ( __msg_prefix "${DL_ID}: " )
endif ( )
message ( STATUS "${__msg_prefix}Downloading ${DL_FILENAME} from ${DL_URL}" )
# Copy mode: check if copy destination exists and is correct
if ( NOT DL_UNPACK )
set ( COPY_DESTINATION "${DL_DESTINATION_DIR}/${DL_FILENAME}" )
if ( EXISTS "${COPY_DESTINATION}" )
ocv_download_log ( "#check_md5 \" ${ COPY_DESTINATION } \"")
file ( MD5 "${COPY_DESTINATION}" target_md5 )
if ( target_md5 STREQUAL DL_HASH )
ocv_download_log ( "#match_md5 \" ${ COPY_DESTINATION } \" \"${target_md5}\"")
if ( OCV_DOWNLOAD_HASH_NAME )
set ( ${ OCV_DOWNLOAD_HASH_NAME } "${DL_HASH}" CACHE INTERNAL "" )
endif ( )
return ( )
endif ( )
ocv_download_log ( "#mismatch_md5 \" ${ COPY_DESTINATION } \" \"${target_md5}\"")
else ( )
ocv_download_log ( "#missing \" ${ COPY_DESTINATION } \"")
endif ( )
endif ( )
# Check cache first
if ( DL_ID )
string ( TOLOWER "${DL_ID}" __id )
string ( REGEX REPLACE "[^a-zA-Z0-9_/ ]" "_" __id "${__id}" )
set ( CACHE_CANDIDATE "${OPENCV_DOWNLOAD_PATH}/${__id}/${DL_HASH}-${DL_FILENAME}" )
else ( )
set ( CACHE_CANDIDATE "${OPENCV_DOWNLOAD_PATH}/${DL_HASH}-${DL_FILENAME}" )
endif ( )
if ( EXISTS "${CACHE_CANDIDATE}" )
ocv_download_log ( "#check_md5 \" ${ CACHE_CANDIDATE } \"")
file ( MD5 "${CACHE_CANDIDATE}" target_md5 )
if ( NOT target_md5 STREQUAL DL_HASH )
ocv_download_log ( "#mismatch_md5 \" ${ CACHE_CANDIDATE } \" \"${target_md5}\"")
ocv_download_log ( "#delete \" ${ CACHE_CANDIDATE } \"")
file ( REMOVE ${ CACHE_CANDIDATE } )
endif ( )
endif ( )
# Download
if ( NOT EXISTS "${CACHE_CANDIDATE}" )
ocv_download_log ( "#cmake_download \" ${ CACHE_CANDIDATE } \" \"${DL_URL}\"")
foreach ( try ${ OPENCV_DOWNLOAD_TRIES_LIST } )
ocv_download_log ( "#try ${try}" )
file ( DOWNLOAD "${DL_URL}" "${CACHE_CANDIDATE}"
S T A T U S s t a t u s
L O G _ _ l o g
$ { O P E N C V _ D O W N L O A D _ P A R A M S } )
if ( status EQUAL 0 )
break ( )
endif ( )
message ( STATUS "Try ${try} failed" )
endforeach ( )
if ( NOT OPENCV_SKIP_FILE_DOWNLOAD_DUMP ) # workaround problem with old CMake versions: "Invalid escape sequence"
string ( LENGTH "${__log}" __log_length )
if ( __log_length LESS 65536 )
string ( REPLACE "\n" "\n# " __log "${__log}" )
ocv_download_log ( "# ${__log}\n" )
endif ( )
endif ( )
if ( NOT status EQUAL 0 )
set ( msg_level FATAL_ERROR )
if ( DEFINED DL_STATUS )
set ( ${ DL_STATUS } FALSE PARENT_SCOPE )
set ( msg_level WARNING )
endif ( )
if ( status MATCHES "Couldn't resolve host name" )
message ( STATUS "
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
C o u l d n ' t d o w n l o a d f i l e s f r o m t h e I n t e r n e t .
P l e a s e c h e c k t h e I n t e r n e t a c c e s s o n t h i s h o s t .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
" )
elseif ( status MATCHES "Couldn't connect to server" )
message ( STATUS "
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
C o u l d n ' t c o n n e c t t o s e r v e r f r o m t h e I n t e r n e t .
P e r h a p s d i r e c t c o n n e c t i o n s a r e n o t a l l o w e d i n t h e c u r r e n t n e t w o r k .
T o u s e p r o x y p l e a s e c h e c k / s p e c i f y t h e s e e n v i r o n m e n t v a r i a b l e s :
- h t t p _ p r o x y / h t t p s _ p r o x y
- a n d / o r H T T P _ P R O X Y / H T T P S _ P R O X Y
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
" )
endif ( )
message ( ${ msg_level } " ${ __msg_prefix } Download failed: ${ status }
F o r d e t a i l s p l e a s e r e f e r t o t h e d o w n l o a d l o g f i l e :
$ { O P E N C V _ D O W N L O A D _ L O G }
" )
# write helper scripts for failed downloads
file ( APPEND "${OPENCV_DOWNLOAD_WITH_CURL}" "curl --create-dirs --output \" ${ CACHE_CANDIDATE } \" \"${DL_URL}\"\n")
file ( APPEND "${OPENCV_DOWNLOAD_WITH_WGET}" "mkdir -p $(dirname ${CACHE_CANDIDATE}) && wget -O \" ${ CACHE_CANDIDATE } \" \"${DL_URL}\"\n")
return ( )
endif ( )
# Don't remove this code, because EXPECTED_MD5 parameter doesn't fail "file(DOWNLOAD)" step on wrong hash
ocv_download_log ( "#check_md5 \" ${ CACHE_CANDIDATE } \"")
file ( MD5 "${CACHE_CANDIDATE}" target_md5 )
if ( NOT target_md5 STREQUAL DL_HASH )
ocv_download_log ( "#mismatch_md5 \" ${ CACHE_CANDIDATE } \" \"${target_md5}\"")
set ( msg_level FATAL_ERROR )
if ( DEFINED DL_STATUS )
set ( ${ DL_STATUS } FALSE PARENT_SCOPE )
set ( msg_level WARNING )
endif ( )
message ( ${ msg_level } "${__msg_prefix}Hash mismatch: ${target_md5}" )
return ( )
endif ( )
endif ( )
# Unpack or copy
if ( DL_UNPACK )
if ( EXISTS "${DL_DESTINATION_DIR}" )
ocv_download_log ( "#remove_unpack \" ${ DL_DESTINATION_DIR } \"")
file ( REMOVE_RECURSE "${DL_DESTINATION_DIR}" )
endif ( )
ocv_download_log ( "#mkdir \" ${ DL_DESTINATION_DIR } \"")
file ( MAKE_DIRECTORY "${DL_DESTINATION_DIR}" )
ocv_download_log ( "#unpack \" ${ DL_DESTINATION_DIR } \" \"${CACHE_CANDIDATE}\"")
execute_process ( COMMAND "${CMAKE_COMMAND}" -E tar xzf "${CACHE_CANDIDATE}"
W O R K I N G _ D I R E C T O R Y " $ { D L _ D E S T I N A T I O N _ D I R } "
R E S U L T _ V A R I A B L E r e s )
if ( NOT res EQUAL 0 )
message ( FATAL_ERROR "${__msg_prefix}Unpack failed: ${res}" )
endif ( )
else ( )
ocv_download_log ( "#copy \" ${ COPY_DESTINATION } \" \"${CACHE_CANDIDATE}\"")
execute_process ( COMMAND ${ CMAKE_COMMAND } -E copy_if_different "${CACHE_CANDIDATE}" "${COPY_DESTINATION}"
R E S U L T _ V A R I A B L E r e s )
if ( NOT res EQUAL 0 )
message ( FATAL_ERROR "${__msg_prefix}Copy failed: ${res}" )
endif ( )
endif ( )
if ( OCV_DOWNLOAD_HASH_NAME )
set ( ${ OCV_DOWNLOAD_HASH_NAME } "${DL_HASH}" CACHE INTERNAL "" )
endif ( )
endfunction ( )
# ----------------------------------------------------------------------------
# Initialize download in case mirror is used
# ----------------------------------------------------------------------------
ocv_init_download_mirror ( )