diff options
-rw-r--r-- | Help/release/dev/fetchcontent-performance.rst | 6 | ||||
-rw-r--r-- | Modules/ExternalProject.cmake | 226 | ||||
-rw-r--r-- | Modules/ExternalProject/captured_process_setup.cmake | 55 | ||||
-rw-r--r-- | Modules/ExternalProject/customcommand.cmake.in | 8 | ||||
-rw-r--r-- | Modules/ExternalProject/customcommand_preamble.cmake.in | 8 | ||||
-rw-r--r-- | Modules/ExternalProject/download.cmake.in | 46 | ||||
-rw-r--r-- | Modules/ExternalProject/extractfile.cmake.in | 32 | ||||
-rw-r--r-- | Modules/ExternalProject/gitclone.cmake.in | 77 | ||||
-rw-r--r-- | Modules/ExternalProject/gitupdate.cmake.in | 92 | ||||
-rw-r--r-- | Modules/ExternalProject/hgclone.cmake.in | 47 | ||||
-rw-r--r-- | Modules/ExternalProject/hgupdate.cmake.in | 12 | ||||
-rw-r--r-- | Modules/ExternalProject/verify.cmake.in | 22 | ||||
-rw-r--r-- | Modules/FetchContent.cmake | 131 | ||||
-rw-r--r-- | Modules/FetchContent/CMakeLists.cmake.in | 27 | ||||
-rw-r--r-- | Tests/RunCMake/FetchContent/RunCMakeTest.cmake | 1 | ||||
-rw-r--r-- | Tests/RunCMake/FetchContent/SameGenerator.cmake | 17 |
16 files changed, 481 insertions, 326 deletions
diff --git a/Help/release/dev/fetchcontent-performance.rst b/Help/release/dev/fetchcontent-performance.rst index 361c2b4..fcb68a1 100644 --- a/Help/release/dev/fetchcontent-performance.rst +++ b/Help/release/dev/fetchcontent-performance.rst @@ -5,3 +5,9 @@ fetchcontent-performance significantly refactored. The patch step gained support for using the terminal with a new ``USES_TERMINAL_PATCH`` keyword as a by-product of that work. +* The :module:`FetchContent` module no longer creates a separate + sub-build to implement the content population. It now invokes + the step scripts directly from within the main project's + configure stage. This significantly speeds up the configure + phase when the required content is already populated and + up-to-date. diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 5f00c87..2b413c2 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -1200,46 +1200,46 @@ function(_ep_parse_arguments keywords name ns args) endfunction() +if(NOT DEFINED CMAKE_SCRIPT_MODE_FILE) + define_property(DIRECTORY PROPERTY "EP_BASE" INHERITED + BRIEF_DOCS "Base directory for External Project storage." + FULL_DOCS + "See documentation of the ExternalProject_Add() function in the " + "ExternalProject module." + ) -define_property(DIRECTORY PROPERTY "EP_BASE" INHERITED - BRIEF_DOCS "Base directory for External Project storage." - FULL_DOCS - "See documentation of the ExternalProject_Add() function in the " - "ExternalProject module." - ) - -define_property(DIRECTORY PROPERTY "EP_PREFIX" INHERITED - BRIEF_DOCS "Top prefix for External Project storage." - FULL_DOCS - "See documentation of the ExternalProject_Add() function in the " - "ExternalProject module." - ) - -define_property(DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED - BRIEF_DOCS - "List of ExternalProject steps that automatically get corresponding targets" - FULL_DOCS - "These targets will be dependent on the main target dependencies. " - "See documentation of the ExternalProject_Add_StepTargets() function in the " - "ExternalProject module." - ) + define_property(DIRECTORY PROPERTY "EP_PREFIX" INHERITED + BRIEF_DOCS "Top prefix for External Project storage." + FULL_DOCS + "See documentation of the ExternalProject_Add() function in the " + "ExternalProject module." + ) -define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED - BRIEF_DOCS - "List of ExternalProject steps that automatically get corresponding targets" - FULL_DOCS - "These targets will not be dependent on the main target dependencies. " - "See documentation of the ExternalProject_Add_StepTargets() function in the " - "ExternalProject module." - ) + define_property(DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED + BRIEF_DOCS + "List of ExternalProject steps that automatically get corresponding targets" + FULL_DOCS + "These targets will be dependent on the main target dependencies. " + "See documentation of the ExternalProject_Add_StepTargets() function in the " + "ExternalProject module." + ) -define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED - BRIEF_DOCS "Never update automatically from the remote repo." - FULL_DOCS - "See documentation of the ExternalProject_Add() function in the " - "ExternalProject module." - ) + define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED + BRIEF_DOCS + "List of ExternalProject steps that automatically get corresponding targets" + FULL_DOCS + "These targets will not be dependent on the main target dependencies. " + "See documentation of the ExternalProject_Add_StepTargets() function in the " + "ExternalProject module." + ) + define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED + BRIEF_DOCS "Never update automatically from the remote repo." + FULL_DOCS + "See documentation of the ExternalProject_Add() function in the " + "ExternalProject module." + ) +endif() function(_ep_write_gitclone_script script_filename @@ -1258,7 +1258,8 @@ function(_ep_write_gitclone_script work_dir gitclone_infofile gitclone_stampfile - tls_verify) + tls_verify + quiet) if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5) # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path. @@ -1322,7 +1323,8 @@ function(_ep_write_hgclone_script src_name work_dir hgclone_infofile - hgclone_stampfile) + hgclone_stampfile + quiet) if("${hg_tag}" STREQUAL "") message(FATAL_ERROR "Tag for hg checkout should not be empty.") @@ -1347,7 +1349,8 @@ function(_ep_write_gitupdate_script git_submodules git_repository work_dir - git_update_strategy) + git_update_strategy + quiet) if("${git_tag}" STREQUAL "") message(FATAL_ERROR "Tag for git checkout should not be empty.") @@ -1372,7 +1375,8 @@ function(_ep_write_hgupdate_script script_filename hg_EXECUTABLE hg_tag - work_dir) + work_dir + quiet) configure_file( ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/hgupdate.cmake.in @@ -1408,7 +1412,8 @@ function(_ep_write_downloadfile_script http_headers netrc netrc_file - extract_script_filename) + extract_script_filename + quiet) if(timeout) set(TIMEOUT_ARGS TIMEOUT ${timeout}) @@ -1426,7 +1431,7 @@ function(_ep_write_downloadfile_script endif() - if(no_progress) + if(no_progress OR quiet) set(SHOW_PROGRESS "") else() set(SHOW_PROGRESS "SHOW_PROGRESS") @@ -1523,7 +1528,8 @@ function(_ep_write_verifyfile_script script_filename LOCAL hash - extract_script_filename) + extract_script_filename + quiet) _ep_get_hash_regex(_ep_hash_regex) if("${hash}" MATCHES "${_ep_hash_regex}") @@ -1551,7 +1557,8 @@ function(_ep_write_extractfile_script script_filename name filename - directory) + directory + quiet) set(args "") @@ -1578,7 +1585,8 @@ function(_ep_write_extractfile_script endfunction() -# This function is an implementation detail of ExternalProject_Add(). +# This function is an implementation detail of ExternalProject_Add() and +# _ep_do_preconfigure_steps_now(). # # The function expects keyword arguments to have already been parsed into # variables of the form _EP_<keyword>. It will create the various directories @@ -2059,7 +2067,7 @@ if(result) message(FATAL_ERROR \"\${msg}\") endif() else() - if(NOT \"${CMAKE_GENERATOR}\" MATCHES \"Ninja\") + if(NOT \"${CMAKE_GENERATOR}\" MATCHES \"Ninja\" AND NOT \"${_EP_QUIET}\") set(msg \"${name} ${step} command succeeded. See also ${logbase}-*.log\") message(STATUS \"\${msg}\") endif() @@ -2523,6 +2531,7 @@ function(_ep_write_command_script commands work_dir genex_supported + quiet have_commands_var) set(sep "${_EP_LIST_SEPARATOR}") @@ -2531,6 +2540,10 @@ function(_ep_write_command_script endif() _ep_replace_location_tags_from_vars(commands) + file(READ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/customcommand.cmake.in + exec_command_template + ) set(script_content) set(this_command) foreach(token IN LISTS commands) @@ -2539,13 +2552,8 @@ function(_ep_write_command_script # Silently skip empty commands continue() endif() - string(APPEND script_content " -execute_process( - COMMAND ${this_command} - COMMAND_ERROR_IS_FATAL LAST - WORKING_DIRECTORY [==[${work_dir}]==] -) -") + string(CONFIGURE "${exec_command_template}" content @ONLY) + string(APPEND script_content "${content}") set(this_command) else() # Ensure we quote every token so we preserve empty items, quotes, etc @@ -2554,20 +2562,20 @@ execute_process( endforeach() if(NOT "${this_command}" STREQUAL "") - string(APPEND script_content " -execute_process( - COMMAND ${this_command} - COMMAND_ERROR_IS_FATAL LAST - WORKING_DIRECTORY [==[${work_dir}]==] -) -") + string(CONFIGURE "${exec_command_template}" content @ONLY) + string(APPEND script_content "${content}") endif() if(script_content STREQUAL "") set(${have_commands_var} FALSE PARENT_SCOPE) else() set(${have_commands_var} TRUE PARENT_SCOPE) - string(PREPEND script_content "cmake_minimum_required(VERSION 3.19)\n") + file(READ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/customcommand_preamble.cmake.in + exec_command_preamble + ) + string(CONFIGURE "${exec_command_preamble}" exec_command_preamble @ONLY) + string(PREPEND script_content "${exec_command_preamble}") endif() if(genex_supported) @@ -2603,7 +2611,8 @@ function(_ep_add_preconfigure_command name step) ) endfunction() -# This function is an implementation detail of ExternalProject_Add(). +# This function is an implementation detail of ExternalProject_Add() and +# _ep_do_preconfigure_steps_now(). # # The function expects keyword arguments to have already been parsed into # variables of the form _EP_<keyword>. It will populate the variable @@ -2619,6 +2628,7 @@ function(_ep_prepare_download name genex_supported) set(tmp_dir "${_EP_TMP_DIR}") set(source_dir "${_EP_SOURCE_DIR}") set(download_dir "${_EP_DOWNLOAD_DIR}") + set(quiet "${_EP_QUIET}") set(comment) @@ -2628,6 +2638,7 @@ function(_ep_prepare_download name genex_supported) if(log) set(script_filename ${tmp_dir}/${name}-download-impl.cmake) set(log TRUE) + set(quiet FALSE) # Already quiet as a result of log being enabled else() set(script_filename ${tmp_dir}/${name}-download.cmake) set(log FALSE) @@ -2660,6 +2671,7 @@ work_dir=${work_dir} "${_EP_DOWNLOAD_COMMAND}" "${work_dir}" "${genex_supported}" + "${quiet}" script_does_something ) set(comment "Performing download step (custom command) for '${name}'") @@ -2698,6 +2710,7 @@ source_dir=${source_dir} "${cmd}" "${work_dir}" "${genex_supported}" + "${quiet}" script_does_something ) set(comment "Performing download step (CVS checkout) for '${name}'") @@ -2750,6 +2763,7 @@ source_dir=${source_dir} "${cmd}" "${work_dir}" "${genex_supported}" + "${quiet}" script_does_something ) set(comment "Performing download step (SVN checkout) for '${name}'") @@ -2835,6 +2849,7 @@ source_dir=${source_dir} "${repo_info_file}" "${last_run_file}" "${tls_verify}" + "${quiet}" ) set(comment "Performing download step (git clone) for '${name}'") @@ -2880,6 +2895,7 @@ source_dir=${source_dir} "${work_dir}" "${repo_info_file}" "${last_run_file}" + "${quiet}" ) set(comment "Performing download step (hg clone) for '${name}'") @@ -2982,6 +2998,7 @@ source_dir=${source_dir} "${_EP_NETRC}" "${_EP_NETRC_FILE}" "${extract_script}" + "${quiet}" ) if(no_extract) set(steps "download and verify") @@ -2995,6 +3012,7 @@ source_dir=${source_dir} "${file}" "${hash}" "${extract_script}" + "${quiet}" ) if(no_extract) set(steps "verify") @@ -3012,6 +3030,7 @@ source_dir=${source_dir} "${name}" "${file}" "${source_dir}" + "${quiet}" ) endif() endif() @@ -3079,7 +3098,8 @@ function(_ep_get_update_disconnected var) set(${var} "${update_disconnected}" PARENT_SCOPE) endfunction() -# This function is an implementation detail of ExternalProject_Add(). +# This function is an implementation detail of ExternalProject_Add() and +# _ep_do_preconfigure_steps_now(). # # The function expects keyword arguments to have already been parsed into # variables of the form _EP_<keyword>. @@ -3091,6 +3111,7 @@ function(_ep_prepare_update name genex_supported) set(tmp_dir "${_EP_TMP_DIR}") set(source_dir "${_EP_SOURCE_DIR}") + set(quiet "${_EP_QUIET}") set(comment) @@ -3102,6 +3123,7 @@ function(_ep_prepare_update name genex_supported) if(log) set(script_filename ${tmp_dir}/${name}-update-impl.cmake) set(log TRUE) + set(quiet FALSE) # Already quiet as a result of log being enabled else() set(script_filename ${tmp_dir}/${name}-update.cmake) set(log FALSE) @@ -3114,6 +3136,7 @@ function(_ep_prepare_update name genex_supported) "${_EP_UPDATE_COMMAND}" "${work_dir}" "${genex_supported}" + "${quiet}" script_does_something ) set(comment "Performing update step (custom command) for '${name}'") @@ -3132,6 +3155,7 @@ function(_ep_prepare_update name genex_supported) "${cmd}" "${work_dir}" "${genex_supported}" + "${quiet}" script_does_something ) set(comment "Performing update step (CVS update) for '${name}'") @@ -3165,6 +3189,7 @@ function(_ep_prepare_update name genex_supported) "${cmd}" "${work_dir}" "${genex_supported}" + "${quiet}" script_does_something ) set(comment "Performing update step (SVN update) for '${name}'") @@ -3222,6 +3247,7 @@ function(_ep_prepare_update name genex_supported) "${_EP_GIT_REPOSITORY}" "${work_dir}" "${git_update_strategy}" + "${quiet}" ) set(script_does_something TRUE) set(comment "Performing update step (git update) for '${name}'") @@ -3250,6 +3276,7 @@ Update to Mercurial >= 2.1.1. "${HG_EXECUTABLE}" "${hg_tag}" "${work_dir}" + "${quiet}" ) set(script_does_something TRUE) set(comment "Performing update step (hg pull) for '${name}'") @@ -3280,7 +3307,8 @@ Update to Mercurial >= 2.1.1. endfunction() -# This function is an implementation detail of ExternalProject_Add(). +# This function is an implementation detail of ExternalProject_Add() and +# _ep_do_preconfigure_steps_now(). # # The function expects keyword arguments to have already been parsed into # variables of the form _EP_<keyword>. @@ -3292,6 +3320,7 @@ function(_ep_prepare_patch name genex_supported) set(tmp_dir "${_EP_TMP_DIR}") set(source_dir "${_EP_SOURCE_DIR}") + set(quiet "${_EP_QUIET}") _ep_get_update_disconnected(update_disconnected) if(update_disconnected) @@ -3306,6 +3335,7 @@ function(_ep_prepare_patch name genex_supported) if(log) set(script_filename ${tmp_dir}/${name}-patch-impl.cmake) set(log TRUE) + set(quiet FALSE) # Already quiet as a result of log being enabled else() set(script_filename ${tmp_dir}/${name}-patch.cmake) set(log FALSE) @@ -3318,6 +3348,7 @@ function(_ep_prepare_patch name genex_supported) "${_EP_PATCH_COMMAND}" "${work_dir}" "${genex_supported}" + "${quiet}" script_does_something ) if(script_does_something) @@ -3837,6 +3868,73 @@ macro(_ep_get_add_keywords out_var) endmacro() +# Internal function called by FetchContent to populate immediately. +# It only executes steps up to and including "patch". It takes the same +# arguments as ExternalProject_Add() plus one additional argument: QUIET. +# +# Not to be used outside of CMake. +# +function(_ep_do_preconfigure_steps_now name) + + cmake_policy(GET CMP0097 _EP_CMP0097 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) + + set(genex_supported FALSE) + + _ep_get_add_keywords(keywords) + _ep_parse_arguments_to_vars("${keywords};QUIET" ${name} _EP_ "${ARGN}") + + _ep_get_update_disconnected(update_disconnected) + + _ep_prepare_directories(${name}) + _ep_prepare_download(${name} ${genex_supported}) + _ep_prepare_update(${name} ${genex_supported}) + _ep_prepare_patch(${name} ${genex_supported}) + + set(stamp_dir "${_EP_STAMP_DIR}") + set(tmp_dir "${_EP_TMP_DIR}") + + # Once any step has to run, all later steps have to be run too + set(need_to_run FALSE) + foreach(step IN ITEMS download update parse) + if(update_disconnected AND "${step}" STREQUAL "update") + continue() + endif() + + string(TOUPPER "${step}" STEP) + if("${_EPcommand_${STEP}}" STREQUAL "") + continue() + endif() + + set(stamp_file "${stamp_dir}/${name}-${step}") + set(script_file ${tmp_dir}/${name}-${step}.cmake) + + if(NOT EXISTS ${stamp_file}) + set(need_to_run TRUE) + endif() + + if(NOT need_to_run) + foreach(dep_file ${script_file} ${_EPdepends_${STEP}}) + if(NOT EXISTS ${dep_file} OR ${dep_file} IS_NEWER_THAN ${stamp_file}) + set(need_to_run TRUE) + break() + endif() + endforeach() + endif() + + if(need_to_run) + include(${script_file}) + file(TOUCH ${stamp_file}) + endif() + endforeach() + + if("${_EP_DOWNLOAD_NO_EXTRACT}") + file(COPY "${_EP_DOWNLOADED_FILE}" DESTINATION "${_EP_SOURCE_DIR}") + endif() + +endfunction() + function(ExternalProject_Add name) cmake_policy(GET CMP0097 _EP_CMP0097 PARENT_SCOPE # undocumented, do not use outside of CMake diff --git a/Modules/ExternalProject/captured_process_setup.cmake b/Modules/ExternalProject/captured_process_setup.cmake new file mode 100644 index 0000000..9c8abb1 --- /dev/null +++ b/Modules/ExternalProject/captured_process_setup.cmake @@ -0,0 +1,55 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +if(quiet) + set(capture_output + OUTPUT_VARIABLE out_var + ERROR_VARIABLE out_var + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE + ) + set(capture_error_only + ERROR_VARIABLE out_var + ERROR_STRIP_TRAILING_WHITESPACE + ) +else() + unset(capture_output) + unset(capture_error_only) +endif() + +set(out_var "") +set(accumulated_output "") + +macro(_ep_message_quiet_capture mode) + if("${mode}" STREQUAL "FATAL_ERROR") + string(JOIN "" detail "${ARGN}") + if(NOT detail STREQUAL "" AND NOT accumulated_output STREQUAL "") + string(PREPEND detail "\n") + endif() + message(FATAL_ERROR "${accumulated_output}${detail}") + endif() + + if(quiet) + if("${mode}" MATCHES "WARNING") + # We can't provide the full CMake backtrace, but we can at least record + # the warning message with a sensible prefix + string(APPEND accumulated_output "${mode}: ") + endif() + string(APPEND accumulated_output "${ARGN}\n") + else() + message(${mode} ${ARGN}) + endif() +endmacro() + +macro(_ep_accumulate_captured_output) + if(NOT "${out_var}" STREQUAL "") + string(APPEND accumulated_output "${out_var}\n") + endif() +endmacro() + +macro(_ep_command_check_result result) + _ep_accumulate_captured_output() + if(result) + _ep_message_quiet_capture(FATAL_ERROR ${ARGN}) + endif() +endmacro() diff --git a/Modules/ExternalProject/customcommand.cmake.in b/Modules/ExternalProject/customcommand.cmake.in new file mode 100644 index 0000000..d41f31b --- /dev/null +++ b/Modules/ExternalProject/customcommand.cmake.in @@ -0,0 +1,8 @@ + +execute_process( + COMMAND @this_command@ + WORKING_DIRECTORY "@work_dir@" + RESULT_VARIABLE result + ${capture_output} +) +_ep_command_check_result(result) diff --git a/Modules/ExternalProject/customcommand_preamble.cmake.in b/Modules/ExternalProject/customcommand_preamble.cmake.in new file mode 100644 index 0000000..ae4fec6 --- /dev/null +++ b/Modules/ExternalProject/customcommand_preamble.cmake.in @@ -0,0 +1,8 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.5) + +set(quiet "@quiet@") +set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject") +include(${script_dir}/captured_process_setup.cmake) diff --git a/Modules/ExternalProject/download.cmake.in b/Modules/ExternalProject/download.cmake.in index 6ef4eb1..c8d2f28 100644 --- a/Modules/ExternalProject/download.cmake.in +++ b/Modules/ExternalProject/download.cmake.in @@ -3,13 +3,17 @@ cmake_minimum_required(VERSION 3.5) +set(quiet "@quiet@") +set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject") +include(${script_dir}/captured_process_setup.cmake) + function(check_file_hash has_hash hash_is_good) if("${has_hash}" STREQUAL "") - message(FATAL_ERROR "has_hash Can't be empty") + _ep_message_quiet_capture(FATAL_ERROR "has_hash Can't be empty") endif() if("${hash_is_good}" STREQUAL "") - message(FATAL_ERROR "hash_is_good Can't be empty") + _ep_message_quiet_capture(FATAL_ERROR "hash_is_good Can't be empty") endif() if("@ALGO@" STREQUAL "") @@ -21,18 +25,20 @@ function(check_file_hash has_hash hash_is_good) set("${has_hash}" TRUE PARENT_SCOPE) - message(STATUS "verifying file... + _ep_message_quiet_capture(STATUS "verifying file... file='@LOCAL@'") + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) file("@ALGO@" "@LOCAL@" actual_value) if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@") set("${hash_is_good}" FALSE PARENT_SCOPE) - message(STATUS "@ALGO@ hash of + _ep_message_quiet_capture(STATUS "@ALGO@ hash of @LOCAL@ does not match expected value expected: '@EXPECT_VALUE@' actual: '${actual_value}'") + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) else() set("${hash_is_good}" TRUE PARENT_SCOPE) endif() @@ -44,7 +50,8 @@ function(sleep_before_download attempt) endif() if(attempt EQUAL 1) - message(STATUS "Retrying...") + _ep_message_quiet_capture(STATUS "Retrying...") + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) return() endif() @@ -66,7 +73,10 @@ function(sleep_before_download attempt) set(sleep_seconds 1200) endif() - message(STATUS "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ...") + _ep_message_quiet_capture(STATUS + "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ..." + ) + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep "${sleep_seconds}") endfunction() @@ -84,18 +94,22 @@ function(download_and_verify) check_file_hash(has_hash hash_is_good) if(has_hash) if(hash_is_good) - message(STATUS + _ep_message_quiet_capture(STATUS "File already exists and hash match (skip download): file='@LOCAL@' @ALGO@='@EXPECT_VALUE@'" ) + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) return() else() - message(STATUS "File already exists but hash mismatch. Removing...") + _ep_message_quiet_capture(STATUS + "File already exists but hash mismatch. Removing..." + ) + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) file(REMOVE "@LOCAL@") endif() else() - message(STATUS + _ep_message_quiet_capture(STATUS "File already exists but no hash specified (use URL_HASH): file='@LOCAL@' Old file will be removed and new file downloaded from URL." @@ -106,11 +120,12 @@ Old file will be removed and new file downloaded from URL." set(retry_number 5) - message(STATUS "Downloading... + _ep_message_quiet_capture(STATUS "Downloading... dst='@LOCAL@' timeout='@TIMEOUT_MSG@' inactivity timeout='@INACTIVITY_TIMEOUT_MSG@'" ) + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) set(download_retry_codes 7 6 8 15) set(skip_url_list) set(status_code) @@ -120,7 +135,8 @@ Old file will be removed and new file downloaded from URL." endif() foreach(url @REMOTE@) if(NOT url IN_LIST skip_url_list) - message(STATUS "Using src='${url}'") + _ep_message_quiet_capture(STATUS "Using src='${url}'") + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) @TLS_VERIFY_CODE@ @TLS_CAINFO_CODE@ @@ -145,10 +161,12 @@ Old file will be removed and new file downloaded from URL." if(status_code EQUAL 0) check_file_hash(has_hash hash_is_good) if(has_hash AND NOT hash_is_good) - message(STATUS "Hash mismatch, removing...") + _ep_message_quiet_capture(STATUS "Hash mismatch, removing...") + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) file(REMOVE "@LOCAL@") else() - message(STATUS "Downloading... done") + _ep_message_quiet_capture(STATUS "Downloading... done") + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) return() endif() else() @@ -171,7 +189,7 @@ Old file will be removed and new file downloaded from URL." endforeach() endforeach() - message(FATAL_ERROR + _ep_message_quiet_capture(FATAL_ERROR "Each download failed! ${logFailedURLs} " diff --git a/Modules/ExternalProject/extractfile.cmake.in b/Modules/ExternalProject/extractfile.cmake.in index d9e07f1..d46de73 100644 --- a/Modules/ExternalProject/extractfile.cmake.in +++ b/Modules/ExternalProject/extractfile.cmake.in @@ -3,17 +3,24 @@ cmake_minimum_required(VERSION 3.5) +set(quiet "@quiet@") +set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject") +include(${script_dir}/captured_process_setup.cmake) + # Make file names absolute: # get_filename_component(filename "@filename@" ABSOLUTE) get_filename_component(directory "@directory@" ABSOLUTE) -message(STATUS "extracting... +_ep_message_quiet_capture(STATUS "extracting... src='${filename}' - dst='${directory}'") + dst='${directory}'" +) if(NOT EXISTS "${filename}") - message(FATAL_ERROR "File to extract does not exist: '${filename}'") + _ep_message_quiet_capture(FATAL_ERROR + "File to extract does not exist: '${filename}'" + ) endif() # Prepare a space for extracting: @@ -27,20 +34,23 @@ file(MAKE_DIRECTORY "${ut_dir}") # Extract it: # -message(STATUS "extracting... [tar @args@]") +_ep_message_quiet_capture(STATUS "extracting... [tar @args@]") execute_process(COMMAND ${CMAKE_COMMAND} -E tar @args@ ${filename} WORKING_DIRECTORY ${ut_dir} - RESULT_VARIABLE rv) + RESULT_VARIABLE rv + ${capture_output} +) +_ep_accumulate_captured_output() if(NOT rv EQUAL 0) - message(STATUS "extracting... [error clean up]") + _ep_message_quiet_capture(STATUS "extracting... [error clean up]") file(REMOVE_RECURSE "${ut_dir}") - message(FATAL_ERROR "Extract of '${filename}' failed") + _ep_message_quiet_capture(FATAL_ERROR "Extract of '${filename}' failed") endif() # Analyze what came out of the tar file: # -message(STATUS "extracting... [analysis]") +_ep_message_quiet_capture(STATUS "extracting... [analysis]") file(GLOB contents "${ut_dir}/*") list(REMOVE_ITEM contents "${ut_dir}/.DS_Store") list(LENGTH contents n) @@ -50,14 +60,14 @@ endif() # Move "the one" directory to the final directory: # -message(STATUS "extracting... [rename]") +_ep_message_quiet_capture(STATUS "extracting... [rename]") file(REMOVE_RECURSE ${directory}) get_filename_component(contents ${contents} ABSOLUTE) file(RENAME ${contents} ${directory}) # Clean up: # -message(STATUS "extracting... [clean up]") +_ep_message_quiet_capture(STATUS "extracting... [clean up]") file(REMOVE_RECURSE "${ut_dir}") -message(STATUS "extracting... done") +_ep_message_quiet_capture(STATUS "extracting... done") diff --git a/Modules/ExternalProject/gitclone.cmake.in b/Modules/ExternalProject/gitclone.cmake.in index 5e5c415..a2e900c 100644 --- a/Modules/ExternalProject/gitclone.cmake.in +++ b/Modules/ExternalProject/gitclone.cmake.in @@ -3,57 +3,81 @@ cmake_minimum_required(VERSION 3.5) +set(quiet "@quiet@") +set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject") +include(${script_dir}/captured_process_setup.cmake) + if(NOT "@gitclone_infofile@" IS_NEWER_THAN "@gitclone_stampfile@") - message(STATUS "Avoiding repeated git clone, stamp file is up to date: '@gitclone_stampfile@'") + if(NOT quiet) + message(STATUS + "Avoiding repeated git clone, stamp file is up to date: " + "'@gitclone_stampfile@'" + ) + endif() return() endif() execute_process( COMMAND ${CMAKE_COMMAND} -E rm -rf "@source_dir@" RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR "Failed to remove directory: '@source_dir@'") -endif() + ${capture_output} +) +_ep_command_check_result( + error_code "Failed to remove directory: '@source_dir@'" +) # try the clone 3 times in case there is an odd git clone issue set(error_code 1) set(number_of_tries 0) while(error_code AND number_of_tries LESS 3) + # If you are seeing the following call hang and you have QUIET enabled, try + # turning QUIET off to show any output immediately. The command may be + # blocking while waiting for user input (e.g. a password to a SSH key). execute_process( - COMMAND "@git_EXECUTABLE@" @git_options@ clone @git_clone_options@ "@git_repository@" "@src_name@" + COMMAND "@git_EXECUTABLE@" @git_options@ + clone @git_clone_options@ "@git_repository@" "@src_name@" WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code - ) + ${capture_output} + ) + if(NOT "${out_var}" STREQUAL "") + string(APPEND accumulated_output "${out_var}\n") + endif() math(EXPR number_of_tries "${number_of_tries} + 1") endwhile() if(number_of_tries GREATER 1) - message(STATUS "Had to git clone more than once: - ${number_of_tries} times.") -endif() -if(error_code) - message(FATAL_ERROR "Failed to clone repository: '@git_repository@'") + set(msg "Had to git clone more than once: ${number_of_tries} times.") + if(quiet) + string(APPEND accumulated_output "${msg}\n") + else() + message(STATUS "${msg}") + endif() endif() +_ep_command_check_result( + error_code "Failed to clone repository: '@git_repository@'" +) execute_process( - COMMAND "@git_EXECUTABLE@" @git_options@ checkout "@git_tag@" @git_checkout_explicit--@ + COMMAND "@git_EXECUTABLE@" @git_options@ + checkout "@git_tag@" @git_checkout_explicit--@ WORKING_DIRECTORY "@work_dir@/@src_name@" RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR "Failed to checkout tag: '@git_tag@'") -endif() + ${capture_output} +) +_ep_command_check_result(error_code "Failed to checkout tag: '@git_tag@'") set(init_submodules @init_submodules@) if(init_submodules) execute_process( - COMMAND "@git_EXECUTABLE@" @git_options@ submodule update @git_submodules_recurse@ --init @git_submodules@ + COMMAND "@git_EXECUTABLE@" @git_options@ + submodule update @git_submodules_recurse@ --init @git_submodules@ WORKING_DIRECTORY "@work_dir@/@src_name@" RESULT_VARIABLE error_code - ) -endif() -if(error_code) - message(FATAL_ERROR "Failed to update submodules in: '@work_dir@/@src_name@'") + ${capture_output} + ) + _ep_command_check_result( + error_code "Failed to update submodules in: '@work_dir@/@src_name@'" + ) endif() # Complete success, update the script-last-run stamp file: @@ -61,7 +85,8 @@ endif() execute_process( COMMAND ${CMAKE_COMMAND} -E copy "@gitclone_infofile@" "@gitclone_stampfile@" RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR "Failed to copy script-last-run stamp file: '@gitclone_stampfile@'") -endif() + ${capture_output} +) +_ep_command_check_result( + error_code "Failed to copy script-last-run stamp file: '@gitclone_stampfile@'" +) diff --git a/Modules/ExternalProject/gitupdate.cmake.in b/Modules/ExternalProject/gitupdate.cmake.in index 7033918..fc2a6ab 100644 --- a/Modules/ExternalProject/gitupdate.cmake.in +++ b/Modules/ExternalProject/gitupdate.cmake.in @@ -3,6 +3,10 @@ cmake_minimum_required(VERSION 3.5) +set(quiet "@quiet@") +set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject") +include(${script_dir}/captured_process_setup.cmake) + function(get_hash_for_ref ref out_var err_var) execute_process( COMMAND "@git_EXECUTABLE@" rev-parse "${ref}" @@ -49,7 +53,7 @@ elseif(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/tags/") # FIXME: We should provide an option to always fetch for this case get_hash_for_ref("@git_tag@" tag_sha error_msg) if(tag_sha STREQUAL head_sha) - message(VERBOSE "Already at requested tag: ${tag_sha}") + _ep_message_quiet_capture(VERBOSE "Already at requested tag: ${tag_sha}") return() endif() @@ -65,7 +69,7 @@ else() get_hash_for_ref("@git_tag@" tag_sha error_msg) if(tag_sha STREQUAL head_sha) # Have the right commit checked out already - message(VERBOSE "Already at requested ref: ${tag_sha}") + _ep_message_quiet_capture(VERBOSE "Already at requested ref: ${tag_sha}") return() elseif(tag_sha STREQUAL "") @@ -76,7 +80,7 @@ else() set(fetch_required YES) set(checkout_name "@git_tag@") if(NOT error_msg STREQUAL "") - message(VERBOSE "${error_msg}") + _ep_message_quiet_capture(VERBOSE "${error_msg}") endif() else() @@ -86,18 +90,22 @@ else() set(fetch_required NO) set(checkout_name "@git_tag@") if(NOT error_msg STREQUAL "") - message(WARNING "${error_msg}") + _ep_message_quiet_capture(WARNING "${error_msg}") endif() endif() endif() if(fetch_required) - message(VERBOSE "Fetching latest from the remote @git_remote_name@") + _ep_message_quiet_capture(VERBOSE "Fetching latest from the remote @git_remote_name@") execute_process( COMMAND "@git_EXECUTABLE@" fetch --tags --force "@git_remote_name@" WORKING_DIRECTORY "@work_dir@" - COMMAND_ERROR_IS_FATAL ANY + RESULT_VARIABLE error_code + ${capture_output} + ) + _ep_command_check_result( + error_code "Failed to fetch from the remote @git_remote_name@'" ) endif() @@ -128,12 +136,15 @@ if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$") else() execute_process( - COMMAND "@git_EXECUTABLE@" for-each-ref "--format='%(upstream:short)'" "${current_branch}" + COMMAND "@git_EXECUTABLE@" for-each-ref + "--format='%(upstream:short)'" "${current_branch}" WORKING_DIRECTORY "@work_dir@" + RESULT_VARIABLE error_code # There is no error if no upstream is set OUTPUT_VARIABLE upstream_branch OUTPUT_STRIP_TRAILING_WHITESPACE - COMMAND_ERROR_IS_FATAL ANY # There is no error if no upstream is set + ${capture_error_only} ) + _ep_command_check_result(error_code) if(NOT upstream_branch STREQUAL checkout_name) # Not safe to rebase when asked to checkout a different branch to the one # we are tracking. If we did rebase, we could end up with arbitrary @@ -145,7 +156,9 @@ if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$") endif() elseif(NOT git_update_strategy STREQUAL "CHECKOUT") - message(FATAL_ERROR "Unsupported git update strategy: ${git_update_strategy}") + _ep_message_quiet_capture(FATAL_ERROR + "Unsupported git update strategy: ${git_update_strategy}" + ) endif() @@ -155,10 +168,9 @@ execute_process( WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code OUTPUT_VARIABLE repo_status + ${capture_error_only} ) -if(error_code) - message(FATAL_ERROR "Failed to get the status") -endif() +_ep_command_check_result(error_code "Failed to get the status") string(LENGTH "${repo_status}" need_stash) # If not in clean state, stash changes in order to be able to perform a @@ -167,16 +179,20 @@ if(need_stash) execute_process( COMMAND "@git_EXECUTABLE@" stash save @git_stash_save_options@ WORKING_DIRECTORY "@work_dir@" - COMMAND_ERROR_IS_FATAL ANY + RESULT_VARIABLE error_code + ${capture_output} ) + _ep_command_check_result(error_code) endif() if(git_update_strategy STREQUAL "CHECKOUT") execute_process( COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}" WORKING_DIRECTORY "@work_dir@" - COMMAND_ERROR_IS_FATAL ANY + RESULT_VARIABLE error_code + ${capture_output} ) + _ep_command_check_result(error_code) else() execute_process( COMMAND "@git_EXECUTABLE@" rebase "${checkout_name}" @@ -198,12 +214,14 @@ else() execute_process( COMMAND "@git_EXECUTABLE@" stash pop --index --quiet WORKING_DIRECTORY "@work_dir@" - ) + ) endif() - message(FATAL_ERROR "\nFailed to rebase in: '@work_dir@'." - "\nOutput from the attempted rebase follows:" - "\n${rebase_output}" - "\n\nYou will have to resolve the conflicts manually") + _ep_message_quiet_capture(FATAL_ERROR + "\nFailed to rebase in: '@work_dir@'." + "\nOutput from the attempted rebase follows:" + "\n${rebase_output}" + "\n\nYou will have to resolve the conflicts manually" + ) endif() # Fall back to checkout. We create an annotated tag so that the user @@ -215,21 +233,27 @@ else() set(tag_name _cmake_ExternalProject_moved_from_here_${tag_timestamp}Z) set(error_log_file ${CMAKE_CURRENT_LIST_DIR}/rebase_error_${tag_timestamp}Z.log) file(WRITE ${error_log_file} "${rebase_output}") - message(WARNING "Rebase failed, output has been saved to ${error_log_file}" - "\nFalling back to checkout, previous commit tagged as ${tag_name}") + _ep_message_quiet_capture(WARNING + "Rebase failed, output has been saved to ${error_log_file}" + "\nFalling back to checkout, previous commit tagged as ${tag_name}" + ) execute_process( COMMAND "@git_EXECUTABLE@" tag -a -m "ExternalProject attempting to move from here to ${checkout_name}" ${tag_name} WORKING_DIRECTORY "@work_dir@" - COMMAND_ERROR_IS_FATAL ANY + RESULT_VARIABLE error_code + ${capture_output} ) + _ep_command_check_result(error_code) execute_process( COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}" WORKING_DIRECTORY "@work_dir@" - COMMAND_ERROR_IS_FATAL ANY + RESULT_VARIABLE error_code + ${capture_output} ) + _ep_command_check_result(error_code) endif() endif() @@ -239,30 +263,42 @@ if(need_stash) COMMAND "@git_EXECUTABLE@" stash pop --index --quiet WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code - ) + ${capture_output} + ) + _ep_accumulate_captured_output() if(error_code) # Stash pop --index failed: Try again dropping the index execute_process( COMMAND "@git_EXECUTABLE@" reset --hard --quiet WORKING_DIRECTORY "@work_dir@" + ${capture_output} ) + _ep_accumulate_captured_output() execute_process( COMMAND "@git_EXECUTABLE@" stash pop --quiet WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code + ${capture_output} ) + _ep_accumulate_captured_output() if(error_code) # Stash pop failed: Restore previous state. execute_process( COMMAND "@git_EXECUTABLE@" reset --hard --quiet ${head_sha} WORKING_DIRECTORY "@work_dir@" + ${capture_output} ) + _ep_accumulate_captured_output() execute_process( COMMAND "@git_EXECUTABLE@" stash pop --index --quiet WORKING_DIRECTORY "@work_dir@" + ${capture_output} + ) + _ep_accumulate_captured_output() + _ep_message_quiet_capture(FATAL_ERROR + "Failed to unstash changes in: '@work_dir@'.\n" + "You will have to resolve the conflicts manually" ) - message(FATAL_ERROR "\nFailed to unstash changes in: '@work_dir@'." - "\nYou will have to resolve the conflicts manually") endif() endif() endif() @@ -272,6 +308,8 @@ if(init_submodules) execute_process( COMMAND "@git_EXECUTABLE@" submodule update @git_submodules_recurse@ --init @git_submodules@ WORKING_DIRECTORY "@work_dir@" - COMMAND_ERROR_IS_FATAL ANY + RESULT_VARIABLE error_code + ${capture_output} ) + _ep_command_check_result(error_code) endif() diff --git a/Modules/ExternalProject/hgclone.cmake.in b/Modules/ExternalProject/hgclone.cmake.in index 09395cc..5561955 100644 --- a/Modules/ExternalProject/hgclone.cmake.in +++ b/Modules/ExternalProject/hgclone.cmake.in @@ -3,43 +3,56 @@ cmake_minimum_required(VERSION 3.5) +set(quiet "@quiet@") +set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject") +include(${script_dir}/captured_process_setup.cmake) + if(NOT "@hgclone_infofile@" IS_NEWER_THAN "@hgclone_stampfile@") - message(STATUS "Avoiding repeated hg clone, stamp file is up to date: '@hgclone_stampfile@'") + if(NOT quiet) + message(STATUS + "Avoiding repeated hg clone, stamp file is up to date: " + "'@hgclone_stampfile@'" + ) + endif() return() endif() execute_process( COMMAND ${CMAKE_COMMAND} -E rm -rf "@source_dir@" RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR "Failed to remove directory: '@source_dir@'") -endif() + ${capture_output} +) +_ep_command_check_result( + error_code "Failed to remove directory: '@source_dir@'" +) execute_process( COMMAND "@hg_EXECUTABLE@" clone -U "@hg_repository@" "@src_name@" WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR "Failed to clone repository: '@hg_repository@'") -endif() + ${capture_output} +) +_ep_command_check_result( + error_code "Failed to clone repository: '@hg_repository@'" +) execute_process( COMMAND "@hg_EXECUTABLE@" update @hg_tag@ WORKING_DIRECTORY "@work_dir@/@src_name@" RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR "Failed to checkout tag: '@hg_tag@'") -endif() + ${capture_output} +) +_ep_command_check_result( + error_code "Failed to checkout tag: '@hg_tag@'" +) # Complete success, update the script-last-run stamp file: # execute_process( COMMAND ${CMAKE_COMMAND} -E copy "@hgclone_infofile@" "@hgclone_stampfile@" RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR "Failed to copy script-last-run stamp file: '@hgclone_stampfile@'") -endif() + ${capture_output} +) +_ep_command_check_result( + error_code "Failed to copy script-last-run stamp file: '@hgclone_stampfile@'" +) diff --git a/Modules/ExternalProject/hgupdate.cmake.in b/Modules/ExternalProject/hgupdate.cmake.in index f88e1ee..a82a819 100644 --- a/Modules/ExternalProject/hgupdate.cmake.in +++ b/Modules/ExternalProject/hgupdate.cmake.in @@ -3,14 +3,22 @@ cmake_minimum_required(VERSION 3.19) +set(quiet "@quiet@") +set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject") +include(${script_dir}/captured_process_setup.cmake) + execute_process( COMMAND "@hg_EXECUTABLE@" pull - COMMAND_ERROR_IS_FATAL ANY WORKING_DIRECTORY "@work_dir@" + RESULT_VARIABLE error_code + ${capture_output} ) +_ep_command_check_result(error_code) execute_process( COMMAND "@hg_EXECUTABLE@" update @hg_tag@ - COMMAND_ERROR_IS_FATAL ANY WORKING_DIRECTORY "@work_dir@" + RESULT_VARIABLE error_code + ${capture_output} ) +_ep_command_check_result(error_code) diff --git a/Modules/ExternalProject/verify.cmake.in b/Modules/ExternalProject/verify.cmake.in index f37059b..cd34ba9 100644 --- a/Modules/ExternalProject/verify.cmake.in +++ b/Modules/ExternalProject/verify.cmake.in @@ -3,6 +3,10 @@ cmake_minimum_required(VERSION 3.5) +set(quiet "@quiet@") +set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject") +include(${script_dir}/captured_process_setup.cmake) + if("@LOCAL@" STREQUAL "") message(FATAL_ERROR "LOCAL can't be empty") endif() @@ -13,22 +17,27 @@ endif() function(do_verify) if("@ALGO@" STREQUAL "") - message(WARNING "File will not be verified since no URL_HASH specified") + _ep_message_quiet_capture(WARNING + "File will not be verified since no URL_HASH specified" + ) + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) return() endif() if("@EXPECT_VALUE@" STREQUAL "") - message(FATAL_ERROR "EXPECT_VALUE can't be empty") + _ep_message_quiet_capture(FATAL_ERROR "EXPECT_VALUE can't be empty") endif() - message(STATUS + _ep_message_quiet_capture(STATUS "verifying file... - file='@LOCAL@'") + file='@LOCAL@'" + ) + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) file("@ALGO@" "@LOCAL@" actual_value) if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@") - message(FATAL_ERROR + _ep_message_quiet_capture(FATAL_ERROR "error: @ALGO@ hash of @LOCAL@ does not match expected value @@ -37,7 +46,8 @@ does not match expected value ") endif() - message(STATUS "verifying file... done") + _ep_message_quiet_capture(STATUS "verifying file... done") + set(accumulated_output "${accumulated_output}" PARENT_SCOPE) endfunction() do_verify() diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 8adef47..6a4cf38 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -849,8 +849,6 @@ function(__FetchContent_directPopulate contentName) SUBBUILD_DIR SOURCE_DIR BINARY_DIR - # We need special processing if DOWNLOAD_NO_EXTRACT is true - DOWNLOAD_NO_EXTRACT # Prevent the following from being passed through CONFIGURE_COMMAND BUILD_COMMAND @@ -894,123 +892,28 @@ function(__FetchContent_directPopulate contentName) set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE) set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE) - # The unparsed arguments may contain spaces, so build up ARG_EXTRA - # in such a way that it correctly substitutes into the generated - # CMakeLists.txt file with each argument quoted. - unset(ARG_EXTRA) - foreach(arg IN LISTS ARG_UNPARSED_ARGUMENTS) - set(ARG_EXTRA "${ARG_EXTRA} \"${arg}\"") - endforeach() - - if(ARG_DOWNLOAD_NO_EXTRACT) - set(ARG_EXTRA "${ARG_EXTRA} DOWNLOAD_NO_EXTRACT YES") - set(__FETCHCONTENT_COPY_FILE -" -ExternalProject_Get_Property(${contentName}-populate DOWNLOADED_FILE) -get_filename_component(dlFileName \"\${DOWNLOADED_FILE}\" NAME) - -ExternalProject_Add_Step(${contentName}-populate copyfile - COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different - \"<DOWNLOADED_FILE>\" \"${ARG_SOURCE_DIR}\" - DEPENDEES patch - DEPENDERS configure - BYPRODUCTS \"${ARG_SOURCE_DIR}/\${dlFileName}\" - COMMENT \"Copying file to SOURCE_DIR\" -) -") + if(ARG_QUIET) + set(quiet TRUE) else() - unset(__FETCHCONTENT_COPY_FILE) - endif() - - # Hide output if requested, but save it to a variable in case there's an - # error so we can show the output upon failure. When not quiet, don't - # capture the output to a variable because the user may want to see the - # output as it happens (e.g. progress during long downloads). Combine both - # stdout and stderr in the one capture variable so the output stays in order. - if (ARG_QUIET) - set(outputOptions - OUTPUT_VARIABLE capturedOutput - ERROR_VARIABLE capturedOutput - ) - else() - set(capturedOutput) - set(outputOptions) + set(quiet FALSE) message(STATUS "Populating ${contentName}") endif() - if(CMAKE_GENERATOR) - set(subCMakeOpts "-G${CMAKE_GENERATOR}") - if(CMAKE_GENERATOR_PLATFORM) - list(APPEND subCMakeOpts "-A${CMAKE_GENERATOR_PLATFORM}") - endif() - if(CMAKE_GENERATOR_TOOLSET) - list(APPEND subCMakeOpts "-T${CMAKE_GENERATOR_TOOLSET}") - endif() - - if(CMAKE_MAKE_PROGRAM) - list(APPEND subCMakeOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}") - endif() - - else() - # Likely we've been invoked via CMake's script mode where no - # generator is set (and hence CMAKE_MAKE_PROGRAM could not be - # trusted even if provided). We will have to rely on being - # able to find the default generator and build tool. - unset(subCMakeOpts) - endif() - - if(DEFINED CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY) - list(APPEND subCMakeOpts - "-DCMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY=${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}") - endif() - - # Avoid using if(... IN_LIST ...) so we don't have to alter policy settings - set(__FETCHCONTENT_CACHED_INFO "") - list(FIND ARG_UNPARSED_ARGUMENTS GIT_REPOSITORY indexResult) - if(indexResult GREATER_EQUAL 0) - find_package(Git QUIET) - set(__FETCHCONTENT_CACHED_INFO -"# Pass through things we've already detected in the main project to avoid -# paying the cost of redetecting them again in ExternalProject_Add() -set(GIT_EXECUTABLE [==[${GIT_EXECUTABLE}]==]) -set(GIT_VERSION_STRING [==[${GIT_VERSION_STRING}]==]) -set_property(GLOBAL PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION - [==[${GIT_EXECUTABLE};${GIT_VERSION_STRING}]==] -) -") - endif() - - # Create and build a separate CMake project to carry out the population. - # If we've already previously done these steps, they will not cause - # anything to be updated, so extra rebuilds of the project won't occur. - # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project - # has this set to something not findable on the PATH. - configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FetchContent/CMakeLists.cmake.in" - "${ARG_SUBBUILD_DIR}/CMakeLists.txt") - execute_process( - COMMAND ${CMAKE_COMMAND} ${subCMakeOpts} . - RESULT_VARIABLE result - ${outputOptions} - WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" - ) - if(result) - if(capturedOutput) - message("${capturedOutput}") - endif() - message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}") - endif() - execute_process( - COMMAND ${CMAKE_COMMAND} --build . - RESULT_VARIABLE result - ${outputOptions} - WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" + include(ExternalProject) + set(argsQuoted) + foreach(__item IN LISTS ARG_UNPARSED_ARGUMENTS) + string(APPEND argsQuoted " [==[${__item}]==]") + endforeach() + cmake_language(EVAL CODE " + _ep_do_preconfigure_steps_now(${contentName} + ${argsQuoted} + QUIET ${quiet} + SOURCE_DIR [==[${ARG_SOURCE_DIR}]==] + BINARY_DIR [==[${ARG_BINARY_DIR}]==] + USES_TERMINAL_DOWNLOAD YES + USES_TERMINAL_UPDATE YES + )" ) - if(result) - if(capturedOutput) - message("${capturedOutput}") - endif() - message(FATAL_ERROR "Build step for ${contentName} failed: ${result}") - endif() endfunction() diff --git a/Modules/FetchContent/CMakeLists.cmake.in b/Modules/FetchContent/CMakeLists.cmake.in deleted file mode 100644 index 5ebb12f..0000000 --- a/Modules/FetchContent/CMakeLists.cmake.in +++ /dev/null @@ -1,27 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -cmake_minimum_required(VERSION ${CMAKE_VERSION}) - -# We name the project and the target for the ExternalProject_Add() call -# to something that will highlight to the user what we are working on if -# something goes wrong and an error message is produced. - -project(${contentName}-populate NONE) - -@__FETCHCONTENT_CACHED_INFO@ - -include(ExternalProject) -ExternalProject_Add(${contentName}-populate - ${ARG_EXTRA} - SOURCE_DIR "${ARG_SOURCE_DIR}" - BINARY_DIR "${ARG_BINARY_DIR}" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" - USES_TERMINAL_DOWNLOAD YES - USES_TERMINAL_UPDATE YES -) - -@__FETCHCONTENT_COPY_FILE@ diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake index 9baeab7..b497382 100644 --- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake +++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake @@ -7,7 +7,6 @@ run_cmake(DirectIgnoresDetails) run_cmake(FirstDetailsWin) run_cmake(DownloadTwice) run_cmake(DownloadFile) -run_cmake(SameGenerator) run_cmake(VarDefinitions) run_cmake(GetProperties) run_cmake(UsesTerminalOverride) diff --git a/Tests/RunCMake/FetchContent/SameGenerator.cmake b/Tests/RunCMake/FetchContent/SameGenerator.cmake deleted file mode 100644 index 58204ef..0000000 --- a/Tests/RunCMake/FetchContent/SameGenerator.cmake +++ /dev/null @@ -1,17 +0,0 @@ -include(FetchContent) - -FetchContent_Declare( - t1 - DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Download command executed" -) - -FetchContent_Populate(t1) - -file(STRINGS "${FETCHCONTENT_BASE_DIR}/t1-subbuild/CMakeCache.txt" - matchLine REGEX "^CMAKE_GENERATOR:.*=" - LIMIT_COUNT 1 -) -if(NOT matchLine MATCHES "${CMAKE_GENERATOR}") - message(FATAL_ERROR "Generator line mismatch: ${matchLine}\n" - " Expected type: ${CMAKE_GENERATOR}") -endif() |