diff options
Diffstat (limited to 'Modules/ExternalData.cmake')
-rw-r--r-- | Modules/ExternalData.cmake | 119 |
1 files changed, 98 insertions, 21 deletions
diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index b00de14..873f88d 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -201,6 +201,11 @@ For example, the argument ``DATA{img.png}`` may be satisfied by either a real ``img.png`` file in the current source directory or a ``img.png.md5`` file containing its MD5 sum. +Multiple content links of the same name with different hash algorithms +are supported (e.g. ``img.png.sha256`` and ``img.png.sha1``) so long as +they all correspond to the same real file. This allows objects to be +fetched from sources indexed by different hash algorithms. + Referencing File Series """"""""""""""""""""""" @@ -274,6 +279,10 @@ The following hash algorithms are supported:: SHA256 .sha256 US Secure Hash Algorithms, RFC 4634 SHA384 .sha384 US Secure Hash Algorithms, RFC 4634 SHA512 .sha512 US Secure Hash Algorithms, RFC 4634 + SHA3_224 .sha3-224 Keccak SHA-3 + SHA3_256 .sha3-256 Keccak SHA-3 + SHA3_384 .sha3-384 Keccak SHA-3 + SHA3_512 .sha3-512 Keccak SHA-3 Note that the hashes are used only for unique data identification and download verification. @@ -429,8 +438,10 @@ function(ExternalData_add_target target) string(REPLACE "|" ";" tuple "${entry}") list(GET tuple 0 file) list(GET tuple 1 name) - list(GET tuple 2 ext) - set(stamp "${ext}-stamp") + list(GET tuple 2 exts) + string(REPLACE "+" ";" exts_list "${exts}") + list(GET exts_list 0 first_ext) + set(stamp "-hash-stamp") if(NOT DEFINED "_ExternalData_FILE_${file}") set("_ExternalData_FILE_${file}" 1) get_property(added DIRECTORY PROPERTY "_ExternalData_FILE_${file}") @@ -446,12 +457,12 @@ function(ExternalData_add_target target) OUTPUT "${file}${stamp}" "${file}" # Run the data fetch/update script. COMMAND ${CMAKE_COMMAND} -Drelative_top=${CMAKE_BINARY_DIR} - -Dfile=${file} -Dname=${name} -Dext=${ext} + -Dfile=${file} -Dname=${name} -Dexts=${exts} -DExternalData_ACTION=fetch -DExternalData_CONFIG=${config} -P ${_ExternalData_SELF} # Update whenever the object hash changes. - MAIN_DEPENDENCY "${name}${ext}" + MAIN_DEPENDENCY "${name}${first_ext}" ) endif() list(APPEND files "${file}${stamp}") @@ -501,8 +512,8 @@ endfunction() #----------------------------------------------------------------------------- # Private helper interface -set(_ExternalData_REGEX_ALGO "MD5|SHA1|SHA224|SHA256|SHA384|SHA512") -set(_ExternalData_REGEX_EXT "md5|sha1|sha224|sha256|sha384|sha512") +set(_ExternalData_REGEX_ALGO "MD5|SHA1|SHA224|SHA256|SHA384|SHA512|SHA3_224|SHA3_256|SHA3_384|SHA3_512") +set(_ExternalData_REGEX_EXT "md5|sha1|sha224|sha256|sha384|sha512|sha3-224|sha3-256|sha3-384|sha3-512") set(_ExternalData_SELF "${CMAKE_CURRENT_LIST_FILE}") get_filename_component(_ExternalData_SELF_DIR "${_ExternalData_SELF}" PATH) @@ -798,6 +809,7 @@ function(_ExternalData_arg_find_files glob pattern regex) cmake_policy(SET CMP0009 NEW) file(${glob} globbed RELATIVE "${top_src}" "${top_src}/${pattern}*") cmake_policy(POP) + set(externals_count -1) foreach(entry IN LISTS globbed) if("x${entry}" MATCHES "^x(.*)(\\.(${_ExternalData_REGEX_EXT}))$") set(relname "${CMAKE_MATCH_1}") @@ -817,7 +829,11 @@ function(_ExternalData_arg_find_files glob pattern regex) set(name "${top_src}/${relname}") set(file "${top_bin}/${relname}") if(alg) - list(APPEND external "${file}|${name}|${alg}") + if(NOT "${external_${externals_count}_file_name}" STREQUAL "${file}|${name}") + math(EXPR externals_count "${externals_count} + 1") + set(external_${externals_count}_file_name "${file}|${name}") + endif() + list(APPEND external_${externals_count}_algs "${alg}") elseif(ExternalData_LINK_CONTENT) _ExternalData_link_content("${name}" alg) list(APPEND external "${file}|${name}|${alg}") @@ -830,6 +846,14 @@ function(_ExternalData_arg_find_files glob pattern regex) endif() endif() endforeach() + if(${externals_count} GREATER -1) + foreach(ii RANGE ${externals_count}) + string(REPLACE ";" "+" algs_delim "${external_${ii}_algs}") + list(APPEND external "${external_${ii}_file_name}|${algs_delim}") + unset(external_${ii}_algs) + unset(external_${ii}_file_name) + endforeach() + endif() set(external "${external}" PARENT_SCOPE) set(internal "${internal}" PARENT_SCOPE) set(have_original "${have_original}" PARENT_SCOPE) @@ -947,13 +971,28 @@ function(_ExternalData_custom_fetch key loc file err_var msg_var) set("${msg_var}" "${msg}" PARENT_SCOPE) endfunction() -function(_ExternalData_download_object name hash algo var_obj) +function(_ExternalData_get_from_object_store hash algo var_obj var_success) + # Search all object stores for an existing object. + foreach(dir ${ExternalData_OBJECT_STORES}) + set(obj "${dir}/${algo}/${hash}") + if(EXISTS "${obj}") + message(STATUS "Found object: \"${obj}\"") + set("${var_obj}" "${obj}" PARENT_SCOPE) + set("${var_success}" 1 PARENT_SCOPE) + return() + endif() + endforeach() +endfunction() + +function(_ExternalData_download_object name hash algo var_obj var_success var_errorMsg) # Search all object stores for an existing object. + set(success 1) foreach(dir ${ExternalData_OBJECT_STORES}) set(obj "${dir}/${algo}/${hash}") if(EXISTS "${obj}") message(STATUS "Found object: \"${obj}\"") set("${var_obj}" "${obj}" PARENT_SCOPE) + set("${var_success}" "${success}" PARENT_SCOPE) return() endif() endforeach() @@ -1008,6 +1047,7 @@ function(_ExternalData_download_object name hash algo var_obj) get_filename_component(dir "${name}" PATH) set(staged "${dir}/.ExternalData_${algo}_${hash}") + set(success 1) if(found) file(RENAME "${tmp}" "${obj}") message(STATUS "Downloaded object: \"${obj}\"") @@ -1018,38 +1058,75 @@ function(_ExternalData_download_object name hash algo var_obj) if(NOT tried) set(tried "\n (No ExternalData_URL_TEMPLATES given)") endif() - message(FATAL_ERROR "Object ${algo}=${hash} not found at:${tried}") + set(success 0) + set("${var_errorMsg}" "Object ${algo}=${hash} not found at:${tried}" PARENT_SCOPE) endif() set("${var_obj}" "${obj}" PARENT_SCOPE) + set("${var_success}" "${success}" PARENT_SCOPE) endfunction() if("${ExternalData_ACTION}" STREQUAL "fetch") - foreach(v ExternalData_OBJECT_STORES file name ext) + foreach(v ExternalData_OBJECT_STORES file name exts) if(NOT DEFINED "${v}") message(FATAL_ERROR "No \"-D${v}=\" value provided!") endif() endforeach() - file(READ "${name}${ext}" hash) - string(STRIP "${hash}" hash) - - if("${ext}" MATCHES "^\\.(${_ExternalData_REGEX_EXT})$") - string(TOUPPER "${CMAKE_MATCH_1}" algo) - else() - message(FATAL_ERROR "Unknown hash algorithm extension \"${ext}\"") - endif() + string(REPLACE "+" ";" exts_list "${exts}") + set(succeeded 0) + set(errorMsg "") + set(hash_list ) + set(algo_list ) + set(hash ) + set(algo ) + foreach(ext ${exts_list}) + file(READ "${name}${ext}" hash) + string(STRIP "${hash}" hash) + + if("${ext}" MATCHES "^\\.(${_ExternalData_REGEX_EXT})$") + string(TOUPPER "${CMAKE_MATCH_1}" algo) + string(REPLACE "-" "_" algo "${algo}") + else() + message(FATAL_ERROR "Unknown hash algorithm extension \"${ext}\"") + endif() - _ExternalData_download_object("${name}" "${hash}" "${algo}" obj) + list(APPEND hash_list ${hash}) + list(APPEND algo_list ${algo}) + endforeach() + list(LENGTH exts_list num_extensions) + math(EXPR exts_range "${num_extensions} - 1") + foreach(ii RANGE 0 ${exts_range}) + list(GET hash_list ${ii} hash) + list(GET algo_list ${ii} algo) + _ExternalData_get_from_object_store("${hash}" "${algo}" obj succeeded) + if(succeeded) + break() + endif() + endforeach() + if(NOT succeeded) + foreach(ii RANGE 0 ${exts_range}) + list(GET hash_list ${ii} hash) + list(GET algo_list ${ii} algo) + _ExternalData_download_object("${name}" "${hash}" "${algo}" + obj succeeded algoErrorMsg) + set(errorMsg "${errorMsg}\n${algoErrorMsg}") + if(succeeded) + break() + endif() + endforeach() + endif() + if(NOT succeeded) + message(FATAL_ERROR "${errorMsg}") + endif() # Check if file already corresponds to the object. - set(stamp "${ext}-stamp") + set(stamp "-hash-stamp") set(file_up_to_date 0) if(EXISTS "${file}" AND EXISTS "${file}${stamp}") file(READ "${file}${stamp}" f_hash) string(STRIP "${f_hash}" f_hash) if("${f_hash}" STREQUAL "${hash}") - #message(STATUS "File already corresponds to object") set(file_up_to_date 1) endif() endif() |