diff options
author | David Cole <david.cole@kitware.com> | 2010-05-27 16:21:56 (GMT) |
---|---|---|
committer | David Cole <david.cole@kitware.com> | 2010-05-27 16:21:56 (GMT) |
commit | f67139ae6fdf964218a93e5506722a367e781c6f (patch) | |
tree | 2245faa382647a682ed2cfe41bc70331c706247e /Modules/ExternalProject.cmake | |
parent | 282a119e355f86e20cc04fabd98083de2799c0ea (diff) | |
download | CMake-f67139ae6fdf964218a93e5506722a367e781c6f.zip CMake-f67139ae6fdf964218a93e5506722a367e781c6f.tar.gz CMake-f67139ae6fdf964218a93e5506722a367e781c6f.tar.bz2 |
Improve FILE(DOWNLOAD) and ExternalProject.
Improve FILE(DOWNLOAD ...):
- Add percent complete progress output to the FILE DOWNLOAD
command. This progress output is off by default to
preserve existing behavior. To turn it on, pass
SHOW_PROGRESS as an argument.
- Add EXPECTED_MD5 argument. Verify that the downloaded
file has the expected md5 sum after download is complete.
- Add documentation for SHOW_PROGRESS and EXPECTED_MD5.
When the destination file exists already and has the
expected md5 sum, then do not bother re-downloading
the file. ("Short circuit" return.)
Also, add a test that checks for the status output
indicating that the short circuit behavior is actually
occurring. Use a binary file for the test so that the
md5 sum is guaranteed to be the same on all platforms
regardless of "shifting text file line ending" issues.
Improve ExternalProject:
- Add argument URL_MD5.
- Add verify step that compares md5 sum of .tar.gz file
before extracting it.
- Add md5 check to download step, too, to prevent
unnecessary downloads.
- Emit a warning message when a file is not verified.
Indicate that the file may be corrupt or that no
checksum was specified.
Diffstat (limited to 'Modules/ExternalProject.cmake')
-rw-r--r-- | Modules/ExternalProject.cmake | 79 |
1 files changed, 68 insertions, 11 deletions
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 0302d5c..ff04fa7 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -17,6 +17,7 @@ # [SVN_REPOSITORY url] # URL of Subversion repo # [SVN_REVISION rev] # Revision to checkout from Subversion repo # [URL /.../src.tgz] # Full path or URL of source +# [URL_MD5 md5] # MD5 checksum of file at URL # [TIMEOUT seconds] # Time allowed for file download operations # #--Update/Patch step---------- # [UPDATE_COMMAND cmd...] # Source work-tree update command @@ -111,19 +112,19 @@ # License text for the above reference.) # Pre-compute a regex to match documented keywords for each command. -file(STRINGS "${CMAKE_CURRENT_LIST_FILE}" lines LIMIT_COUNT 100 - REGEX "^# ( \\[[A-Z_]+ [^]]*\\] +#.*$|[A-Za-z_]+\\()") +file(STRINGS "${CMAKE_CURRENT_LIST_FILE}" lines LIMIT_COUNT 103 + REGEX "^# ( \\[[A-Z0-9_]+ [^]]*\\] +#.*$|[A-Za-z0-9_]+\\()") foreach(line IN LISTS lines) - if("${line}" MATCHES "^# [A-Za-z_]+\\(") + if("${line}" MATCHES "^# [A-Za-z0-9_]+\\(") if(_ep_func) set(_ep_keywords_${_ep_func} "${_ep_keywords_${_ep_func}})$") endif() - string(REGEX REPLACE "^# ([A-Za-z_]+)\\(.*" "\\1" _ep_func "${line}") + string(REGEX REPLACE "^# ([A-Za-z0-9_]+)\\(.*" "\\1" _ep_func "${line}") #message("function [${_ep_func}]") set(_ep_keywords_${_ep_func} "^(") set(_ep_keyword_sep) else() - string(REGEX REPLACE "^# \\[([A-Z_]+) .*" "\\1" _ep_key "${line}") + string(REGEX REPLACE "^# \\[([A-Z0-9_]+) .*" "\\1" _ep_key "${line}") #message(" keyword [${_ep_key}]") set(_ep_keywords_${_ep_func} "${_ep_keywords_${_ep_func}}${_ep_keyword_sep}${_ep_key}") @@ -148,7 +149,7 @@ function(_ep_parse_arguments f name ns args) foreach(arg IN LISTS args) set(is_value 1) - if(arg MATCHES "^[A-Z][A-Z_][A-Z_]+$" AND + if(arg MATCHES "^[A-Z][A-Z0-9_][A-Z0-9_]+$" AND NOT ((arg STREQUAL "${key}") AND (key STREQUAL "COMMAND")) AND NOT arg MATCHES "^(TRUE|FALSE)$") if(_ep_keywords_${f} AND arg MATCHES "${_ep_keywords_${f}}") @@ -203,7 +204,7 @@ define_property(DIRECTORY PROPERTY "EP_PREFIX" INHERITED ) -function(_ep_write_downloadfile_script script_filename remote local timeout) +function(_ep_write_downloadfile_script script_filename remote local timeout md5) if(timeout) set(timeout_args TIMEOUT ${timeout}) set(timeout_msg "${timeout} seconds") @@ -212,6 +213,12 @@ function(_ep_write_downloadfile_script script_filename remote local timeout) set(timeout_msg "none") endif() + if(md5) + set(md5_args EXPECTED_MD5 ${md5}) + else() + set(md5_args "# no EXPECTED_MD5") + endif() + file(WRITE ${script_filename} "message(STATUS \"downloading... src='${remote}' @@ -221,6 +228,8 @@ function(_ep_write_downloadfile_script script_filename remote local timeout) file(DOWNLOAD \"${remote}\" \"${local}\" + SHOW_PROGRESS + ${md5_args} ${timeout_args} STATUS status LOG log) @@ -243,6 +252,51 @@ message(STATUS \"downloading... done\") endfunction(_ep_write_downloadfile_script) +function(_ep_write_verifyfile_script script_filename local md5) + file(WRITE ${script_filename} +"message(STATUS \"verifying file... + file='${local}'\") + +set(verified 0) + +# If an expected md5 checksum exists, compare against it: +# +if(NOT \"${md5}\" STREQUAL \"\") + execute_process(COMMAND \${CMAKE_COMMAND} -E md5sum \"${local}\" + OUTPUT_VARIABLE ov + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE rv) + + if(NOT rv EQUAL 0) + message(FATAL_ERROR \"error: computing md5sum of '${local}' failed\") + endif() + + string(REGEX MATCH \"^([0-9A-Fa-f]+)\" md5_actual \"\${ov}\") + + string(TOLOWER \"\${md5_actual}\" md5_actual) + string(TOLOWER \"${md5}\" md5) + + if(NOT \"\${md5}\" STREQUAL \"\${md5_actual}\") + message(FATAL_ERROR \"error: md5sum of '${local}' does not match expected value + md5_expected: \${md5} + md5_actual: \${md5_actual} +\") + endif() + + set(verified 1) +endif() + +if(verified) + message(STATUS \"verifying file... done\") +else() + message(STATUS \"verifying file... warning: did not verify file - no URL_MD5 checksum argument? corrupt file?\") +endif() +" +) + +endfunction(_ep_write_verifyfile_script) + + function(_ep_write_extractfile_script script_filename filename tmp directory) set(args "") @@ -678,9 +732,10 @@ function(_ep_add_download_command name) list(APPEND depends ${stamp_dir}/${name}-svninfo.txt) elseif(url) get_filename_component(work_dir "${source_dir}" PATH) + get_property(md5 TARGET ${name} PROPERTY _EP_URL_MD5) set(repository "external project URL") set(module "${url}") - set(tag "") + set(tag "${md5}") configure_file( "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in" "${stamp_dir}/${name}-urlinfo.txt" @@ -701,14 +756,16 @@ function(_ep_add_download_command name) endif() set(file ${download_dir}/${fname}) get_property(timeout TARGET ${name} PROPERTY _EP_TIMEOUT) - _ep_write_downloadfile_script("${stamp_dir}/download-${name}.cmake" "${url}" "${file}" "${timeout}") + _ep_write_downloadfile_script("${stamp_dir}/download-${name}.cmake" "${url}" "${file}" "${timeout}" "${md5}") set(cmd ${CMAKE_COMMAND} -P ${stamp_dir}/download-${name}.cmake COMMAND) - set(comment "Performing download step (download and extract) for '${name}'") + set(comment "Performing download step (download, verify and extract) for '${name}'") else() set(file "${url}") - set(comment "Performing download step (extract) for '${name}'") + set(comment "Performing download step (verify and extract) for '${name}'") endif() + _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${md5}") + list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake) # TODO: Support other archive formats. _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${file}" "${tmp_dir}" "${source_dir}") list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake) |