summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Help/release/3.20.rst12
-rw-r--r--Modules/ExternalProject-download.cmake.in173
-rw-r--r--Modules/ExternalProject-gitupdate.cmake.in (renamed from Modules/ExternalProject/gitupdate.cmake.in)92
-rw-r--r--Modules/ExternalProject-verify.cmake.in37
-rw-r--r--Modules/ExternalProject.cmake1792
-rw-r--r--Modules/ExternalProject/RepositoryInfo.txt.in1
-rw-r--r--Modules/ExternalProject/captured_process_setup.cmake55
-rw-r--r--Modules/ExternalProject/cfgcmd.txt.in1
-rw-r--r--Modules/ExternalProject/copydir.cmake.in10
-rw-r--r--Modules/ExternalProject/customcommand.cmake.in8
-rw-r--r--Modules/ExternalProject/customcommand_preamble.cmake.in8
-rw-r--r--Modules/ExternalProject/download.cmake.in205
-rw-r--r--Modules/ExternalProject/extractfile.cmake.in73
-rw-r--r--Modules/ExternalProject/gitclone.cmake.in93
-rw-r--r--Modules/ExternalProject/hgclone.cmake.in59
-rw-r--r--Modules/ExternalProject/hgupdate.cmake.in24
-rw-r--r--Modules/ExternalProject/mkdirs.cmake.in19
-rw-r--r--Modules/ExternalProject/verify.cmake.in58
-rw-r--r--Modules/FetchContent.cmake131
-rw-r--r--Modules/FetchContent/CMakeLists.cmake.in27
-rw-r--r--Modules/RepositoryInfo.txt.in3
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt2
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt4
-rw-r--r--Tests/RunCMake/ExternalProject/NoOptions-stderr.txt2
-rw-r--r--Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt2
-rw-r--r--Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt2
-rw-r--r--Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake2
-rw-r--r--Tests/RunCMake/FetchContent/MultiCommand-stdout.txt6
-rw-r--r--Tests/RunCMake/FetchContent/MultiCommand.cmake18
-rw-r--r--Tests/RunCMake/FetchContent/RunCMakeTest.cmake32
-rw-r--r--Tests/RunCMake/FetchContent/SameGenerator.cmake17
-rw-r--r--Tests/RunCMake/FetchContent/TimeStamps-stdout.txt2
-rw-r--r--Tests/RunCMake/FetchContent/TimeStamps.cmake14
-rw-r--r--Tests/RunCMake/FetchContent/TimeStampsRerun-check.cmake38
-rw-r--r--Tests/RunCMake/FetchContent/TimeStampsRerun.cmake1
35 files changed, 1112 insertions, 1911 deletions
diff --git a/Help/release/3.20.rst b/Help/release/3.20.rst
index eede36278b..176447d165 100644
--- a/Help/release/3.20.rst
+++ b/Help/release/3.20.rst
@@ -318,18 +318,6 @@ Other Changes
* Ninja generators now transform the ``DEPFILE`` generated by an
:command:`add_custom_command`. See policy :policy:`CMP0116` for details.
-* The implementation of the :module:`ExternalProject` module was
- 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.
-
* The precompiled Linux binaries provided on
`cmake.org <https://cmake.org/download/>`_ have changed their naming pattern
to ``cmake-$ver-linux-$arch``, where ``$arch`` is either ``x86_64`` or
diff --git a/Modules/ExternalProject-download.cmake.in b/Modules/ExternalProject-download.cmake.in
new file mode 100644
index 0000000000..ff8c659082
--- /dev/null
+++ b/Modules/ExternalProject-download.cmake.in
@@ -0,0 +1,173 @@
+# 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)
+
+function(check_file_hash has_hash hash_is_good)
+ if("${has_hash}" STREQUAL "")
+ message(FATAL_ERROR "has_hash Can't be empty")
+ endif()
+
+ if("${hash_is_good}" STREQUAL "")
+ message(FATAL_ERROR "hash_is_good Can't be empty")
+ endif()
+
+ if("@ALGO@" STREQUAL "")
+ # No check
+ set("${has_hash}" FALSE PARENT_SCOPE)
+ set("${hash_is_good}" FALSE PARENT_SCOPE)
+ return()
+ endif()
+
+ set("${has_hash}" TRUE PARENT_SCOPE)
+
+ message(STATUS "verifying file...
+ file='@LOCAL@'")
+
+ file("@ALGO@" "@LOCAL@" actual_value)
+
+ if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@")
+ set("${hash_is_good}" FALSE PARENT_SCOPE)
+ message(STATUS "@ALGO@ hash of
+ @LOCAL@
+ does not match expected value
+ expected: '@EXPECT_VALUE@'
+ actual: '${actual_value}'")
+ else()
+ set("${hash_is_good}" TRUE PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(sleep_before_download attempt)
+ if(attempt EQUAL 0)
+ return()
+ endif()
+
+ if(attempt EQUAL 1)
+ message(STATUS "Retrying...")
+ return()
+ endif()
+
+ set(sleep_seconds 0)
+
+ if(attempt EQUAL 2)
+ set(sleep_seconds 5)
+ elseif(attempt EQUAL 3)
+ set(sleep_seconds 5)
+ elseif(attempt EQUAL 4)
+ set(sleep_seconds 15)
+ elseif(attempt EQUAL 5)
+ set(sleep_seconds 60)
+ elseif(attempt EQUAL 6)
+ set(sleep_seconds 90)
+ elseif(attempt EQUAL 7)
+ set(sleep_seconds 300)
+ else()
+ set(sleep_seconds 1200)
+ endif()
+
+ message(STATUS "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ...")
+
+ execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep "${sleep_seconds}")
+endfunction()
+
+if("@LOCAL@" STREQUAL "")
+ message(FATAL_ERROR "LOCAL can't be empty")
+endif()
+
+if("@REMOTE@" STREQUAL "")
+ message(FATAL_ERROR "REMOTE can't be empty")
+endif()
+
+if(EXISTS "@LOCAL@")
+ check_file_hash(has_hash hash_is_good)
+ if(has_hash)
+ if(hash_is_good)
+ message(STATUS "File already exists and hash match (skip download):
+ file='@LOCAL@'
+ @ALGO@='@EXPECT_VALUE@'"
+ )
+ return()
+ else()
+ message(STATUS "File already exists but hash mismatch. Removing...")
+ file(REMOVE "@LOCAL@")
+ endif()
+ else()
+ message(STATUS "File already exists but no hash specified (use URL_HASH):
+ file='@LOCAL@'
+Old file will be removed and new file downloaded from URL."
+ )
+ file(REMOVE "@LOCAL@")
+ endif()
+endif()
+
+set(retry_number 5)
+
+message(STATUS "Downloading...
+ dst='@LOCAL@'
+ timeout='@TIMEOUT_MSG@'
+ inactivity timeout='@INACTIVITY_TIMEOUT_MSG@'"
+)
+set(download_retry_codes 7 6 8 15)
+set(skip_url_list)
+set(status_code)
+foreach(i RANGE ${retry_number})
+ if(status_code IN_LIST download_retry_codes)
+ sleep_before_download(${i})
+ endif()
+ foreach(url @REMOTE@)
+ if(NOT url IN_LIST skip_url_list)
+ message(STATUS "Using src='${url}'")
+
+ @TLS_VERIFY_CODE@
+ @TLS_CAINFO_CODE@
+ @NETRC_CODE@
+ @NETRC_FILE_CODE@
+
+ file(
+ DOWNLOAD
+ "${url}" "@LOCAL@"
+ @SHOW_PROGRESS@
+ @TIMEOUT_ARGS@
+ @INACTIVITY_TIMEOUT_ARGS@
+ STATUS status
+ LOG log
+ @USERPWD_ARGS@
+ @HTTP_HEADERS_ARGS@
+ )
+
+ list(GET status 0 status_code)
+ list(GET status 1 status_string)
+
+ 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...")
+ file(REMOVE "@LOCAL@")
+ else()
+ message(STATUS "Downloading... done")
+ return()
+ endif()
+ else()
+ string(APPEND logFailedURLs "error: downloading '${url}' failed
+ status_code: ${status_code}
+ status_string: ${status_string}
+ log:
+ --- LOG BEGIN ---
+ ${log}
+ --- LOG END ---
+ "
+ )
+ if(NOT status_code IN_LIST download_retry_codes)
+ list(APPEND skip_url_list "${url}")
+ break()
+ endif()
+ endif()
+ endif()
+ endforeach()
+endforeach()
+
+message(FATAL_ERROR "Each download failed!
+ ${logFailedURLs}
+ "
+)
diff --git a/Modules/ExternalProject/gitupdate.cmake.in b/Modules/ExternalProject-gitupdate.cmake.in
index fc2a6aba5e..7033918056 100644
--- a/Modules/ExternalProject/gitupdate.cmake.in
+++ b/Modules/ExternalProject-gitupdate.cmake.in
@@ -3,10 +3,6 @@
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}"
@@ -53,7 +49,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)
- _ep_message_quiet_capture(VERBOSE "Already at requested tag: ${tag_sha}")
+ message(VERBOSE "Already at requested tag: ${tag_sha}")
return()
endif()
@@ -69,7 +65,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
- _ep_message_quiet_capture(VERBOSE "Already at requested ref: ${tag_sha}")
+ message(VERBOSE "Already at requested ref: ${tag_sha}")
return()
elseif(tag_sha STREQUAL "")
@@ -80,7 +76,7 @@ else()
set(fetch_required YES)
set(checkout_name "@git_tag@")
if(NOT error_msg STREQUAL "")
- _ep_message_quiet_capture(VERBOSE "${error_msg}")
+ message(VERBOSE "${error_msg}")
endif()
else()
@@ -90,22 +86,18 @@ else()
set(fetch_required NO)
set(checkout_name "@git_tag@")
if(NOT error_msg STREQUAL "")
- _ep_message_quiet_capture(WARNING "${error_msg}")
+ message(WARNING "${error_msg}")
endif()
endif()
endif()
if(fetch_required)
- _ep_message_quiet_capture(VERBOSE "Fetching latest from the remote @git_remote_name@")
+ message(VERBOSE "Fetching latest from the remote @git_remote_name@")
execute_process(
COMMAND "@git_EXECUTABLE@" fetch --tags --force "@git_remote_name@"
WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- ${capture_output}
- )
- _ep_command_check_result(
- error_code "Failed to fetch from the remote @git_remote_name@'"
+ COMMAND_ERROR_IS_FATAL ANY
)
endif()
@@ -136,15 +128,12 @@ 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
- ${capture_error_only}
+ COMMAND_ERROR_IS_FATAL ANY # There is no error if no upstream is set
)
- _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
@@ -156,9 +145,7 @@ if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$")
endif()
elseif(NOT git_update_strategy STREQUAL "CHECKOUT")
- _ep_message_quiet_capture(FATAL_ERROR
- "Unsupported git update strategy: ${git_update_strategy}"
- )
+ message(FATAL_ERROR "Unsupported git update strategy: ${git_update_strategy}")
endif()
@@ -168,9 +155,10 @@ execute_process(
WORKING_DIRECTORY "@work_dir@"
RESULT_VARIABLE error_code
OUTPUT_VARIABLE repo_status
- ${capture_error_only}
)
-_ep_command_check_result(error_code "Failed to get the status")
+if(error_code)
+ message(FATAL_ERROR "Failed to get the status")
+endif()
string(LENGTH "${repo_status}" need_stash)
# If not in clean state, stash changes in order to be able to perform a
@@ -179,20 +167,16 @@ if(need_stash)
execute_process(
COMMAND "@git_EXECUTABLE@" stash save @git_stash_save_options@
WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- ${capture_output}
+ COMMAND_ERROR_IS_FATAL ANY
)
- _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@"
- RESULT_VARIABLE error_code
- ${capture_output}
+ COMMAND_ERROR_IS_FATAL ANY
)
- _ep_command_check_result(error_code)
else()
execute_process(
COMMAND "@git_EXECUTABLE@" rebase "${checkout_name}"
@@ -214,14 +198,12 @@ else()
execute_process(
COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
WORKING_DIRECTORY "@work_dir@"
- )
+ )
endif()
- _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"
- )
+ 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")
endif()
# Fall back to checkout. We create an annotated tag so that the user
@@ -233,27 +215,21 @@ 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}")
- _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}"
- )
+ message(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@"
- RESULT_VARIABLE error_code
- ${capture_output}
+ COMMAND_ERROR_IS_FATAL ANY
)
- _ep_command_check_result(error_code)
execute_process(
COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}"
WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- ${capture_output}
+ COMMAND_ERROR_IS_FATAL ANY
)
- _ep_command_check_result(error_code)
endif()
endif()
@@ -263,42 +239,30 @@ 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()
@@ -308,8 +272,6 @@ if(init_submodules)
execute_process(
COMMAND "@git_EXECUTABLE@" submodule update @git_submodules_recurse@ --init @git_submodules@
WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- ${capture_output}
+ COMMAND_ERROR_IS_FATAL ANY
)
- _ep_command_check_result(error_code)
endif()
diff --git a/Modules/ExternalProject-verify.cmake.in b/Modules/ExternalProject-verify.cmake.in
new file mode 100644
index 0000000000..c06da4ec8c
--- /dev/null
+++ b/Modules/ExternalProject-verify.cmake.in
@@ -0,0 +1,37 @@
+# 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)
+
+if("@LOCAL@" STREQUAL "")
+ message(FATAL_ERROR "LOCAL can't be empty")
+endif()
+
+if(NOT EXISTS "@LOCAL@")
+ message(FATAL_ERROR "File not found: @LOCAL@")
+endif()
+
+if("@ALGO@" STREQUAL "")
+ message(WARNING "File will not be verified since no URL_HASH specified")
+ return()
+endif()
+
+if("@EXPECT_VALUE@" STREQUAL "")
+ message(FATAL_ERROR "EXPECT_VALUE can't be empty")
+endif()
+
+message(STATUS "verifying file...
+ file='@LOCAL@'")
+
+file("@ALGO@" "@LOCAL@" actual_value)
+
+if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@")
+ message(FATAL_ERROR "error: @ALGO@ hash of
+ @LOCAL@
+does not match expected value
+ expected: '@EXPECT_VALUE@'
+ actual: '${actual_value}'
+")
+endif()
+
+message(STATUS "verifying file... done")
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 987b69a0c9..56525080cc 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -407,7 +407,7 @@ External Project Definition
``CVS_TAG <tag>``
Tag to checkout from the CVS repository.
- **Update Step Options:**
+ **Update/Patch Step Options:**
Whenever CMake is re-run, by default the external project's sources will be
updated if the download method supports updates (e.g. a git repository
would be checked if the ``GIT_TAG`` does not refer to a specific commit).
@@ -442,7 +442,6 @@ External Project Definition
This may cause a step target to be created automatically for the
``download`` step. See policy :policy:`CMP0114`.
- **Patch Step Options:**
``PATCH_COMMAND <cmd>...``
Specifies a custom command to patch the sources after an update. By
default, no patch command is defined. Note that it can be quite difficult
@@ -718,11 +717,6 @@ External Project Definition
``USES_TERMINAL_UPDATE <bool>``
Give the update step access to the terminal.
- ``USES_TERMINAL_PATCH <bool>``
- .. versionadded:: 3.20
-
- Give the patch step access to the terminal.
-
``USES_TERMINAL_CONFIGURE <bool>``
Give the configure step access to the terminal.
@@ -1140,17 +1134,16 @@ macro(_ep_get_hash_regex out_var)
set(${out_var} "^(${${out_var}})=([0-9A-Fa-f]+)$")
endmacro()
-function(_ep_parse_arguments_to_vars keywords name ns args)
- # Transfer the arguments into variables in the calling scope.
+function(_ep_parse_arguments f keywords name ns args)
+ # Transfer the arguments to this function into target properties for the
+ # new custom target we just added so that we can set up all the build steps
+ # correctly based on target properties.
+ #
# Because some keywords can be repeated, we can't use cmake_parse_arguments().
- # Instead, we loop through the args and consider the namespace starting with
- # an upper-case letter followed by at least two more upper-case letters,
+ # Instead, we loop through ARGN and consider the namespace starting with an
+ # upper-case letter followed by at least two more upper-case letters,
# numbers or underscores to be keywords.
- foreach(key IN LISTS keywords)
- unset(${ns}${key})
- endforeach()
-
set(key)
foreach(arg IN LISTS args)
@@ -1167,100 +1160,68 @@ function(_ep_parse_arguments_to_vars keywords name ns args)
if(is_value)
if(key)
# Value
- list(APPEND ${ns}${key} "${arg}")
+ if(NOT arg STREQUAL "")
+ set_property(TARGET ${name} APPEND PROPERTY ${ns}${key} "${arg}")
+ else()
+ get_property(have_key TARGET ${name} PROPERTY ${ns}${key} SET)
+ if(have_key)
+ get_property(value TARGET ${name} PROPERTY ${ns}${key})
+ set_property(TARGET ${name} PROPERTY ${ns}${key} "${value};${arg}")
+ else()
+ set_property(TARGET ${name} PROPERTY ${ns}${key} "${arg}")
+ endif()
+ endif()
else()
# Missing Keyword
- message(AUTHOR_WARNING "value '${arg}' with no previous keyword")
+ message(AUTHOR_WARNING "value '${arg}' with no previous keyword in ${f}")
endif()
else()
set(key "${arg}")
endif()
endforeach()
-
- foreach(key IN LISTS keywords)
- if(DEFINED ${ns}${key})
- set(${ns}${key} "${${ns}${key}}" PARENT_SCOPE)
- else()
- unset(${ns}${key} PARENT_SCOPE)
- endif()
- endforeach()
-
-endfunction()
-
-function(_ep_parse_arguments keywords name ns args)
- _ep_parse_arguments_to_vars("${keywords}" ${name} ${ns} "${args}")
-
- # Transfer the arguments to the target as target properties. These are
- # read by the various steps, potentially from different scopes.
- foreach(key IN LISTS keywords)
- if(DEFINED ${ns}${key})
- set_property(TARGET ${name} PROPERTY ${ns}${key} "${${ns}${key}}")
- endif()
- endforeach()
-
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_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_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_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."
- )
-endif()
+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."
+ )
-function(_ep_write_gitclone_script
- script_filename
- source_dir
- git_EXECUTABLE
- git_repository
- git_tag
- git_remote_name
- init_submodules
- git_submodules_recurse
- git_submodules
- git_shallow
- git_progress
- git_config
- src_name
- work_dir
- gitclone_infofile
- gitclone_stampfile
- tls_verify
- quiet)
+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."
+ )
+function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify)
if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5)
# Use `git checkout <tree-ish> --` to avoid ambiguity with a local path.
set(git_checkout_explicit-- "--")
@@ -1306,52 +1267,134 @@ function(_ep_write_gitclone_script
endif()
string (REPLACE ";" " " git_options "${git_options}")
- configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/gitclone.cmake.in
- ${script_filename}
- @ONLY
+ file(WRITE ${script_filename}
+"
+if(NOT \"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\")
+ message(STATUS \"Avoiding repeated git clone, stamp file is up to date: '${gitclone_stampfile}'\")
+ 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()
-endfunction()
+# 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)
+ execute_process(
+ COMMAND \"${git_EXECUTABLE}\" ${git_options} clone ${git_clone_options} \"${git_repository}\" \"${src_name}\"
+ WORKING_DIRECTORY \"${work_dir}\"
+ RESULT_VARIABLE error_code
+ )
+ 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}'\")
+endif()
+
+execute_process(
+ 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()
+
+set(init_submodules ${init_submodules})
+if(init_submodules)
+ execute_process(
+ 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}'\")
+endif()
+
+# Complete success, update the script-last-run stamp file:
+#
+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()
-function(_ep_write_hgclone_script
- script_filename
- source_dir
- hg_EXECUTABLE
- hg_repository
- hg_tag
- src_name
- work_dir
- hgclone_infofile
- hgclone_stampfile
- quiet)
+"
+)
+endfunction()
+
+function(_ep_write_hgclone_script script_filename source_dir hg_EXECUTABLE hg_repository hg_tag src_name work_dir hgclone_infofile hgclone_stampfile)
if("${hg_tag}" STREQUAL "")
message(FATAL_ERROR "Tag for hg checkout should not be empty.")
endif()
+ file(WRITE ${script_filename}
+"
+if(NOT \"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\")
+ message(STATUS \"Avoiding repeated hg clone, stamp file is up to date: '${hgclone_stampfile}'\")
+ return()
+endif()
- configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/hgclone.cmake.in
- ${script_filename}
- @ONLY
+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()
-endfunction()
+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()
+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()
-function(_ep_write_gitupdate_script
- script_filename
- git_EXECUTABLE
- git_tag
- git_remote_name
- init_submodules
- git_submodules_recurse
- git_submodules
- git_repository
- work_dir
- git_update_strategy
- quiet)
+# 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()
+"
+)
+
+endfunction()
+
+
+function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_repository work_dir git_update_strategy)
if("${git_tag}" STREQUAL "")
message(FATAL_ERROR "Tag for git checkout should not be empty.")
endif()
@@ -1365,56 +1408,13 @@ function(_ep_write_gitupdate_script
endif()
configure_file(
- "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/gitupdate.cmake.in"
- "${script_filename}"
- @ONLY
- )
-endfunction()
-
-function(_ep_write_hgupdate_script
- script_filename
- hg_EXECUTABLE
- hg_tag
- work_dir
- quiet)
-
- configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/hgupdate.cmake.in
- ${script_filename}
- @ONLY
- )
-
-endfunction()
-
-function(_ep_write_copydir_script
- script_filename
- from_dir
- to_dir)
-
- configure_file(
- "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/copydir.cmake.in"
- "${script_filename}"
- @ONLY
+ "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-gitupdate.cmake.in"
+ "${script_filename}"
+ @ONLY
)
endfunction()
-function(_ep_write_downloadfile_script
- script_filename
- REMOTE
- LOCAL
- timeout
- inactivity_timeout
- no_progress
- hash
- tls_verify
- tls_cainfo
- userpwd
- http_headers
- netrc
- netrc_file
- extract_script_filename
- quiet)
-
+function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout inactivity_timeout no_progress hash tls_verify tls_cainfo userpwd http_headers netrc netrc_file)
if(timeout)
set(TIMEOUT_ARGS TIMEOUT ${timeout})
set(TIMEOUT_MSG "${timeout} seconds")
@@ -1431,7 +1431,7 @@ function(_ep_write_downloadfile_script
endif()
- if(no_progress OR quiet)
+ if(no_progress)
set(SHOW_PROGRESS "")
else()
set(SHOW_PROGRESS "SHOW_PROGRESS")
@@ -1518,19 +1518,13 @@ function(_ep_write_downloadfile_script
# * USERPWD_ARGS
# * HTTP_HEADERS_ARGS
configure_file(
- "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/download.cmake.in"
- "${script_filename}"
- @ONLY
+ "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-download.cmake.in"
+ "${script_filename}"
+ @ONLY
)
endfunction()
-function(_ep_write_verifyfile_script
- script_filename
- LOCAL
- hash
- extract_script_filename
- quiet)
-
+function(_ep_write_verifyfile_script script_filename LOCAL hash)
_ep_get_hash_regex(_ep_hash_regex)
if("${hash}" MATCHES "${_ep_hash_regex}")
set(ALGO "${CMAKE_MATCH_1}")
@@ -1544,22 +1538,15 @@ function(_ep_write_verifyfile_script
# * ALGO
# * EXPECT_VALUE
# * LOCAL
- # * extract_script_filename
configure_file(
- "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/verify.cmake.in"
- "${script_filename}"
- @ONLY
+ "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-verify.cmake.in"
+ "${script_filename}"
+ @ONLY
)
endfunction()
-function(_ep_write_extractfile_script
- script_filename
- name
- filename
- directory
- quiet)
-
+function(_ep_write_extractfile_script script_filename name filename directory)
set(args "")
if(filename MATCHES "(\\.|=)(7z|tar\\.bz2|tar\\.gz|tar\\.xz|tbz2|tgz|txz|zip)$")
@@ -1571,34 +1558,77 @@ function(_ep_write_extractfile_script
endif()
if(args STREQUAL "")
- message(FATAL_ERROR
- "Do not know how to extract '${filename}' -- known types are: "
- ".7z, .tar, .tar.bz2, .tar.gz, .tar.xz, .tbz2, .tgz, .txz and .zip")
+ message(SEND_ERROR "error: do not know how to extract '${filename}' -- known types are .7z, .tar, .tar.bz2, .tar.gz, .tar.xz, .tbz2, .tgz, .txz and .zip")
+ return()
endif()
- configure_file(
- "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/extractfile.cmake.in"
- "${script_filename}"
- @ONLY
- )
+ file(WRITE ${script_filename}
+"# Make file names absolute:
+#
+get_filename_component(filename \"${filename}\" ABSOLUTE)
+get_filename_component(directory \"${directory}\" ABSOLUTE)
-endfunction()
+message(STATUS \"extracting...
+ src='\${filename}'
+ dst='\${directory}'\")
+
+if(NOT EXISTS \"\${filename}\")
+ message(FATAL_ERROR \"error: file to extract does not exist: '\${filename}'\")
+endif()
+# Prepare a space for extracting:
+#
+set(i 1234)
+while(EXISTS \"\${directory}/../ex-${name}\${i}\")
+ math(EXPR i \"\${i} + 1\")
+endwhile()
+set(ut_dir \"\${directory}/../ex-${name}\${i}\")
+file(MAKE_DIRECTORY \"\${ut_dir}\")
+
+# Extract it:
+#
+message(STATUS \"extracting... [tar ${args}]\")
+execute_process(COMMAND \${CMAKE_COMMAND} -E tar ${args} \${filename}
+ WORKING_DIRECTORY \${ut_dir}
+ RESULT_VARIABLE rv)
+
+if(NOT rv EQUAL 0)
+ message(STATUS \"extracting... [error clean up]\")
+ file(REMOVE_RECURSE \"\${ut_dir}\")
+ message(FATAL_ERROR \"error: extract of '\${filename}' failed\")
+endif()
-# This function is an implementation detail of ExternalProject_Add() and
-# _ep_do_preconfigure_steps_now().
+# Analyze what came out of the tar file:
#
-# The function expects keyword arguments to have already been parsed into
-# variables of the form _EP_<keyword>. It will create the various directories
-# before returning and it will populate variables of the form
-# _EP_<location>_DIR in the calling scope.
+message(STATUS \"extracting... [analysis]\")
+file(GLOB contents \"\${ut_dir}/*\")
+list(REMOVE_ITEM contents \"\${ut_dir}/.DS_Store\")
+list(LENGTH contents n)
+if(NOT n EQUAL 1 OR NOT IS_DIRECTORY \"\${contents}\")
+ set(contents \"\${ut_dir}\")
+endif()
+
+# Move \"the one\" directory to the final directory:
#
-# Variables will also be set in the calling scope to enable subsequently
-# calling _ep_add_preconfigure_command() for the mkdir step.
+message(STATUS \"extracting... [rename]\")
+file(REMOVE_RECURSE \${directory})
+get_filename_component(contents \${contents} ABSOLUTE)
+file(RENAME \${contents} \${directory})
+
+# Clean up:
#
-function(_ep_prepare_directories name)
+message(STATUS \"extracting... [clean up]\")
+file(REMOVE_RECURSE \"\${ut_dir}\")
- set(prefix ${_EP_PREFIX})
+message(STATUS \"extracting... done\")
+"
+)
+
+endfunction()
+
+
+function(_ep_set_directories name)
+ get_property(prefix TARGET ${name} PROPERTY _EP_PREFIX)
if(NOT prefix)
get_property(prefix DIRECTORY PROPERTY EP_PREFIX)
if(NOT prefix)
@@ -1609,7 +1639,6 @@ function(_ep_prepare_directories name)
endif()
endif()
if(prefix)
- file(TO_CMAKE_PATH "${prefix}" prefix)
set(tmp_default "${prefix}/tmp")
set(download_default "${prefix}/src")
set(source_default "${prefix}/src/${name}")
@@ -1617,7 +1646,6 @@ function(_ep_prepare_directories name)
set(stamp_default "${prefix}/src/${name}-stamp")
set(install_default "${prefix}")
else()
- file(TO_CMAKE_PATH "${base}" base)
set(tmp_default "${base}/tmp/${name}")
set(download_default "${base}/Download/${name}")
set(source_default "${base}/Source/${name}")
@@ -1625,10 +1653,10 @@ function(_ep_prepare_directories name)
set(stamp_default "${base}/Stamp/${name}")
set(install_default "${base}/Install/${name}")
endif()
-
- set(build_in_source "${_EP_BUILD_IN_SOURCE}")
+ get_property(build_in_source TARGET ${name} PROPERTY _EP_BUILD_IN_SOURCE)
if(build_in_source)
- if(DEFINED _EP_BINARY_DIR)
+ get_property(have_binary_dir TARGET ${name} PROPERTY _EP_BINARY_DIR SET)
+ if(have_binary_dir)
message(FATAL_ERROR
"External project ${name} has both BINARY_DIR and BUILD_IN_SOURCE!")
endif()
@@ -1639,78 +1667,65 @@ function(_ep_prepare_directories name)
set(places stamp download source binary install tmp)
foreach(var ${places})
string(TOUPPER "${var}" VAR)
- set(${var}_dir "${_EP_${VAR}_DIR}")
+ get_property(${var}_dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
if(NOT ${var}_dir)
set(${var}_dir "${${var}_default}")
endif()
if(NOT IS_ABSOLUTE "${${var}_dir}")
get_filename_component(${var}_dir "${top}/${${var}_dir}" ABSOLUTE)
endif()
- file(TO_CMAKE_PATH "${${var}_dir}" ${var}_dir)
+ set_property(TARGET ${name} PROPERTY _EP_${VAR}_DIR "${${var}_dir}")
endforeach()
# Special case for default log directory based on stamp directory.
- set(log_dir "${_EP_LOG_DIR}")
+ get_property(log_dir TARGET ${name} PROPERTY _EP_LOG_DIR)
if(NOT log_dir)
- set(log_dir "${stamp_dir}")
- else()
- if(NOT IS_ABSOLUTE "${log_dir}")
- get_filename_component(log_dir "${top}/${log_dir}" ABSOLUTE)
- endif()
+ get_property(log_dir TARGET ${name} PROPERTY _EP_STAMP_DIR)
+ endif()
+ if(NOT IS_ABSOLUTE "${log_dir}")
+ get_filename_component(log_dir "${top}/${log_dir}" ABSOLUTE)
endif()
- file(TO_CMAKE_PATH "${log_dir}" log_dir)
- list(APPEND places log)
+ set_property(TARGET ${name} PROPERTY _EP_LOG_DIR "${log_dir}")
- set(source_subdir "${_EP_SOURCE_SUBDIR}")
- if(source_subdir)
- if(IS_ABSOLUTE "${source_subdir}")
- message(FATAL_ERROR
- "External project ${name} has non-relative SOURCE_SUBDIR!")
- endif()
- string(REPLACE "\\" "/" source_subdir "${source_subdir}")
+ get_property(source_subdir TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR)
+ if(NOT source_subdir)
+ set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "")
+ elseif(IS_ABSOLUTE "${source_subdir}")
+ message(FATAL_ERROR
+ "External project ${name} has non-relative SOURCE_SUBDIR!")
+ else()
# Prefix with a slash so that when appended to the source directory, it
# behaves as expected.
- string(PREPEND source_subdir "/")
+ set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "/${source_subdir}")
endif()
-
if(build_in_source)
- set(binary_dir "${source_dir}${source_subdir}")
+ get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR)
+ if(source_subdir)
+ set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}/${source_subdir}")
+ else()
+ set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}")
+ endif()
endif()
- # This script will be used both here and by the mkdir step. We create the
- # directories now at configure time and ensure they exists again at build
- # time (since somebody might remove one of the required directories and try
- # to rebuild without re-running cmake). They need to exist now at makefile
- # generation time for Borland make and wmake so that CMake may generate
- # makefiles with "cd C:\short\paths\with\no\spaces" commands in them.
- set(script_filename "${tmp_dir}/${name}-mkdirs.cmake")
- configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/mkdirs.cmake.in
- ${script_filename}
- @ONLY
- )
- include(${script_filename})
-
- set(comment "Creating directories for '${name}'")
- set(cmd ${CMAKE_COMMAND} -P ${script_filename})
-
- # Provide variables that can be used later to create a custom command or
- # invoke the step directly
- set(_EPcomment_MKDIR "${comment}" PARENT_SCOPE)
- set(_EPcommand_MKDIR "${cmd}" PARENT_SCOPE)
- set(_EPalways_MKDIR FALSE PARENT_SCOPE)
- set(_EPexcludefrommain_MKDIR FALSE PARENT_SCOPE)
- set(_EPdepends_MKDIR "" PARENT_SCOPE)
- set(_EPdependees_MKDIR "" PARENT_SCOPE)
-
+ # Make the directories at CMake configure time *and* add a custom command
+ # to make them at build time. They need to exist at makefile generation
+ # time for Borland make and wmake so that CMake may generate makefiles
+ # with "cd C:\short\paths\with\no\spaces" commands in them.
+ #
+ # Additionally, the add_custom_command is still used in case somebody
+ # removes one of the necessary directories and tries to rebuild without
+ # re-running cmake.
foreach(var ${places})
string(TOUPPER "${var}" VAR)
- set(_EP_${VAR}_DIR "${${var}_dir}" PARENT_SCOPE)
+ get_property(dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
+ file(MAKE_DIRECTORY "${dir}")
+ if(NOT EXISTS "${dir}")
+ message(FATAL_ERROR "dir '${dir}' does not exist after file(MAKE_DIRECTORY)")
+ endif()
endforeach()
- set(_EP_SOURCE_SUBDIR "${source_subdir}" PARENT_SCOPE)
-
endfunction()
+
# IMPORTANT: this MUST be a macro and not a function because of the
# in-place replacements that occur in each ${var}
#
@@ -1726,17 +1741,6 @@ macro(_ep_replace_location_tags target_name)
endforeach()
endmacro()
-macro(_ep_replace_location_tags_from_vars)
- set(vars ${ARGN})
- foreach(var ${vars})
- if(${var})
- foreach(dir SOURCE_DIR SOURCE_SUBDIR BINARY_DIR INSTALL_DIR TMP_DIR DOWNLOAD_DIR DOWNLOADED_FILE LOG_DIR)
- string(REPLACE "<${dir}>" "${_EP_${dir}}" ${var} "${${var}}")
- endforeach()
- endif()
- endforeach()
-endmacro()
-
function(_ep_command_line_to_initial_cache var args force)
set(script_initial_cache "")
@@ -1919,24 +1923,17 @@ function(_ep_get_build_command name step cmd_var)
set(${cmd_var} "${cmd}" PARENT_SCOPE)
endfunction()
-function(_ep_write_log_script name step genex_supported cmd_var)
-
- set(log_dir "${_EP_LOG_DIR}")
- set(tmp_dir "${_EP_TMP_DIR}")
-
- if(genex_supported)
- set(script_base ${tmp_dir}/${name}-${step}-$<CONFIG>)
- else()
- set(script_base ${tmp_dir}/${name}-${step})
- endif()
+function(_ep_write_log_script name step cmd_var)
+ ExternalProject_Get_Property(${name} log_dir)
+ ExternalProject_Get_Property(${name} stamp_dir)
set(command "${${cmd_var}}")
set(make "")
set(code_cygpath_make "")
- if(command MATCHES [[^\$\(MAKE\)]])
+ if(command MATCHES "^\\$\\(MAKE\\)")
# GNU make recognizes the string "$(MAKE)" as recursive make, so
# ensure that it appears directly in the makefile.
- string(REGEX REPLACE [[^\$\(MAKE\)]] [[${make}]] command "${command}")
+ string(REGEX REPLACE "^\\$\\(MAKE\\)" "\${make}" command "${command}")
set(make "-Dmake=$(MAKE)")
if(WIN32 AND NOT CYGWIN)
@@ -1958,8 +1955,8 @@ endif()
endif()
set(config "")
- if("${CMAKE_CFG_INTDIR}" MATCHES [[^\$]])
- string(REPLACE "${CMAKE_CFG_INTDIR}" [[${config}]] command "${command}")
+ if("${CMAKE_CFG_INTDIR}" MATCHES "^\\$")
+ string(REPLACE "${CMAKE_CFG_INTDIR}" "\${config}" command "${command}")
set(config "-Dconfig=${CMAKE_CFG_INTDIR}")
endif()
@@ -1993,22 +1990,15 @@ endif()
endif()
endforeach()
string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
- if(genex_supported)
- file(GENERATE OUTPUT "${script_base}-impl.cmake" CONTENT "${code}")
- else()
- file(WRITE "${script_base}-impl.cmake" "${code}")
- endif()
- set(command ${CMAKE_COMMAND}
- -D "make=\${make}"
- -D "config=\${config}"
- -P ${script_base}-impl.cmake
- )
+ file(GENERATE OUTPUT "${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake" CONTENT "${code}")
+ set(command ${CMAKE_COMMAND} "-Dmake=\${make}" "-Dconfig=\${config}" -P ${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake)
endif()
# Wrap the command in a script to log output to files.
+ set(script ${stamp_dir}/${name}-${step}-$<CONFIG>.cmake)
set(logbase ${log_dir}/${name}-${step})
- set(log_merged "${_EP_LOG_MERGED_STDOUTERR}")
- set(log_output_on_failure "${_EP_LOG_OUTPUT_ON_FAILURE}")
+ get_property(log_merged TARGET ${name} PROPERTY _EP_LOG_MERGED_STDOUTERR)
+ get_property(log_output_on_failure TARGET ${name} PROPERTY _EP_LOG_OUTPUT_ON_FAILURE)
if (log_merged)
set(stdout_log "${logbase}.log")
set(stderr_log "${logbase}.log")
@@ -2067,19 +2057,14 @@ if(result)
message(FATAL_ERROR \"\${msg}\")
endif()
else()
- if(NOT \"${CMAKE_GENERATOR}\" MATCHES \"Ninja\" AND NOT \"${_EP_QUIET}\")
+ if(NOT \"${CMAKE_GENERATOR}\" MATCHES \"Ninja\")
set(msg \"${name} ${step} command succeeded. See also ${logbase}-*.log\")
message(STATUS \"\${msg}\")
endif()
endif()
")
- set(script_filename ${script_base}.cmake)
- if(genex_supported)
- file(GENERATE OUTPUT ${script_filename} CONTENT "${code}")
- else()
- file(WRITE ${script_filename} "${code}")
- endif()
- set(command ${CMAKE_COMMAND} ${make} ${config} -P ${script_filename})
+ file(GENERATE OUTPUT "${script}" CONTENT "${code}")
+ set(command ${CMAKE_COMMAND} ${make} ${config} -P ${script})
set(${cmd_var} "${command}" PARENT_SCOPE)
endfunction()
@@ -2257,7 +2242,8 @@ function(ExternalProject_Add_Step name step)
LOG
USES_TERMINAL
)
- _ep_parse_arguments("${keywords}" ${name} _EP_${step}_ "${ARGN}")
+ _ep_parse_arguments(ExternalProject_Add_Step "${keywords}"
+ ${name} _EP_${step}_ "${ARGN}")
get_property(independent TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT)
if(independent STREQUAL "")
@@ -2368,8 +2354,7 @@ function(ExternalProject_Add_Step name step)
# Wrap with log script?
get_property(log TARGET ${name} PROPERTY _EP_${step}_LOG)
if(command AND log)
- set(genex_supported TRUE)
- _ep_write_log_script(${name} ${step} ${genex_supported} command)
+ _ep_write_log_script(${name} ${step} command)
endif()
if("${command}" STREQUAL "")
@@ -2501,6 +2486,27 @@ function(ExternalProject_Add_StepDependencies name step)
endfunction()
+
+function(_ep_add_mkdir_command name)
+ ExternalProject_Get_Property(${name}
+ source_dir binary_dir install_dir stamp_dir download_dir tmp_dir log_dir)
+
+ _ep_get_configuration_subdir_suffix(cfgdir)
+
+ ExternalProject_Add_Step(${name} mkdir
+ INDEPENDENT TRUE
+ COMMENT "Creating directories for '${name}'"
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${source_dir}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${binary_dir}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${install_dir}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${tmp_dir}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${stamp_dir}${cfgdir}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${download_dir}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${log_dir}
+ )
+endfunction()
+
+
function(_ep_is_dir_empty dir empty_var)
file(GLOB gr "${dir}/*")
if("${gr}" STREQUAL "")
@@ -2511,277 +2517,114 @@ function(_ep_is_dir_empty dir empty_var)
endfunction()
function(_ep_get_git_submodules_recurse git_submodules_recurse)
-
- if(NOT DEFINED _EP_GIT_SUBMODULES_RECURSE OR _EP_GIT_SUBMODULES_RECURSE)
- # The git submodule update '--recursive' flag requires git >= v1.6.5
- if(recurseFlag AND GIT_VERSION_STRING VERSION_LESS 1.6.5)
- message(FATAL_ERROR
- "git version 1.6.5 or later required for --recursive flag with "
- "'git submodule ...': GIT_VERSION_STRING='${GIT_VERSION_STRING}'")
- endif()
- set(${git_submodules_recurse} "--recursive" PARENT_SCOPE)
+ # Checks for GIT_SUBMODULES_RECURSE property
+ # Default is ON, which sets git_submodules_recurse output variable to "--recursive"
+ # Otherwise, the output variable is set to an empty value ""
+ get_property(git_submodules_recurse_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE SET)
+ if(NOT git_submodules_recurse_set)
+ set(recurseFlag "--recursive")
else()
- set(${git_submodules_recurse} "" PARENT_SCOPE)
- endif()
-
-endfunction()
-
-function(_ep_write_command_script
- script_filename
- commands
- work_dir
- genex_supported
- quiet
- have_commands_var)
-
- set(sep "${_EP_LIST_SEPARATOR}")
- if(sep AND commands)
- string(REPLACE "${sep}" "\\;" commands "${commands}")
- 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)
- if(token STREQUAL "COMMAND")
- if("${this_command}" STREQUAL "")
- # Silently skip empty commands
- continue()
- endif()
- string(CONFIGURE "${exec_command_template}" content @ONLY)
- string(APPEND script_content "${content}")
- set(this_command)
+ get_property(git_submodules_recurse_value TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE)
+ if(git_submodules_recurse_value)
+ set(recurseFlag "--recursive")
else()
- # Ensure we quote every token so we preserve empty items, quotes, etc
- string(APPEND this_command " [==[${token}]==]")
+ set(recurseFlag "")
endif()
- endforeach()
-
- if(NOT "${this_command}" STREQUAL "")
- 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)
- 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()
+ set(${git_submodules_recurse} "${recurseFlag}" PARENT_SCOPE)
- if(genex_supported)
- # Only written at generation phase. This will only change the file's
- # timestamp if the contents change.
- file(GENERATE OUTPUT "${script_filename}" CONTENT "${script_content}")
- else()
- # Update the file immediately, needed if script has to be invoked in the
- # configure phase (e.g. via FetchContent). We need to be careful to avoid
- # updating the timestamp if the file contents don't change. The file(WRITE)
- # command always updates the file, so avoid it if we don't need to call it.
- set(doWrite TRUE)
- if(EXISTS "${script_filename}")
- file(READ "${script_filename}" existing_content)
- if(existing_content STREQUAL script_content)
- set(doWrite FALSE)
- endif()
- endif()
- if(doWrite)
- file(WRITE "${script_filename}" "${script_content}")
- endif()
+ # The git submodule update '--recursive' flag requires git >= v1.6.5
+ if(recurseFlag AND GIT_VERSION_STRING VERSION_LESS 1.6.5)
+ message(FATAL_ERROR "error: git version 1.6.5 or later required for --recursive flag with 'git submodule ...': GIT_VERSION_STRING='${GIT_VERSION_STRING}'")
endif()
-
endfunction()
-function(_ep_add_preconfigure_command name step)
- string(TOUPPER "${step}" STEP)
- set(uses_terminal "${_EP_USES_TERMINAL_${STEP}}")
- if(uses_terminal)
- set(uses_terminal TRUE)
- else()
- set(uses_terminal FALSE)
- endif()
-
- # Pre-configure steps are expected to set their own work_dir
- ExternalProject_Add_Step(${name} ${step}
- INDEPENDENT TRUE
- COMMENT "${_EPcomment_${STEP}}"
- COMMAND ${_EPcommand_${STEP}}
- ALWAYS ${_EPalways_${STEP}}
- EXCLUDE_FROM_MAIN ${_EPexcludefrommain_${STEP}}
- DEPENDS ${_EPdepends_${STEP}}
- DEPENDEES ${_EPdependees_${STEP}}
- USES_TERMINAL ${uses_terminal}
- )
-endfunction()
+function(_ep_add_download_command name)
+ ExternalProject_Get_Property(${name} source_dir stamp_dir download_dir tmp_dir)
-# 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
-# _EP_DOWNLOADED_FILE in the calling scope only if the download method is
-# URL-based and extraction has been turned off.
-#
-# Variables will also be set in the calling scope to enable subsequently
-# calling _ep_add_preconfigure_command() for the download step.
-#
-function(_ep_prepare_download name genex_supported)
+ get_property(cmd_set TARGET ${name} PROPERTY _EP_DOWNLOAD_COMMAND SET)
+ get_property(cmd TARGET ${name} PROPERTY _EP_DOWNLOAD_COMMAND)
+ get_property(cvs_repository TARGET ${name} PROPERTY _EP_CVS_REPOSITORY)
+ get_property(svn_repository TARGET ${name} PROPERTY _EP_SVN_REPOSITORY)
+ get_property(git_repository TARGET ${name} PROPERTY _EP_GIT_REPOSITORY)
+ get_property(hg_repository TARGET ${name} PROPERTY _EP_HG_REPOSITORY )
+ get_property(url TARGET ${name} PROPERTY _EP_URL)
+ get_property(fname TARGET ${name} PROPERTY _EP_DOWNLOAD_NAME)
- set(stamp_dir "${_EP_STAMP_DIR}")
- set(tmp_dir "${_EP_TMP_DIR}")
- set(source_dir "${_EP_SOURCE_DIR}")
- set(download_dir "${_EP_DOWNLOAD_DIR}")
- set(quiet "${_EP_QUIET}")
+ # TODO: Perhaps file:// should be copied to download dir before extraction.
+ string(REGEX REPLACE "file://" "" url "${url}")
+ set(depends)
set(comment)
+ set(work_dir)
- # We handle the log setting directly here rather than deferring it to
- # be handled by ExternalProject_Add_Step()
- set(log "${_EP_LOG_DOWNLOAD}")
- 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)
- endif()
-
- set(repo_info_file ${tmp_dir}/${name}-download-repoinfo.txt)
- set(last_run_file ${stamp_dir}/${name}-download-lastrun.txt)
- set(script_does_something TRUE)
-
- # We use configure_file() to write the repo_info_file below so that the
- # file's timestamp is not updated if we don't change the contents of an
- # existing file.
-
- if(DEFINED _EP_DOWNLOAD_COMMAND)
+ if(cmd_set)
set(work_dir ${download_dir})
- set(repo_info_content
-"method=custom
-command=${_EP_DOWNLOAD_COMMAND}
-source_dir=${source_dir}
-work_dir=${work_dir}
-")
- configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/RepositoryInfo.txt.in
- ${repo_info_file}
- @ONLY
- )
-
- _ep_write_command_script(
- "${script_filename}"
- "${_EP_DOWNLOAD_COMMAND}"
- "${work_dir}"
- "${genex_supported}"
- "${quiet}"
- script_does_something
- )
- set(comment "Performing download step (custom command) for '${name}'")
-
- elseif(DEFINED _EP_CVS_REPOSITORY)
+ elseif(cvs_repository)
find_package(CVS QUIET)
if(NOT CVS_EXECUTABLE)
message(FATAL_ERROR "error: could not find cvs for checkout of ${name}")
endif()
- if("${_EP_CVS_MODULE}" STREQUAL "")
+ get_target_property(cvs_module ${name} _EP_CVS_MODULE)
+ if(NOT cvs_module)
message(FATAL_ERROR "error: no CVS_MODULE")
endif()
- set(repo_info_content
-"method=cvs
-repository=${_EP_CVS_REPOSITORY}
-module=${_EP_CVS_MODULE}
-tag=${_EP_CVS_TAG}
-source_dir=${source_dir}
-")
+ get_property(cvs_tag TARGET ${name} PROPERTY _EP_CVS_TAG)
+
+ set(repository ${cvs_repository})
+ set(module ${cvs_module})
+ set(tag ${cvs_tag})
configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/RepositoryInfo.txt.in
- ${repo_info_file}
+ "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
+ "${stamp_dir}/${name}-cvsinfo.txt"
@ONLY
- )
+ )
get_filename_component(src_name "${source_dir}" NAME)
get_filename_component(work_dir "${source_dir}" PATH)
-
- set(cmd "${CVS_EXECUTABLE}" -d "${_EP_CVS_REPOSITORY}" -q
- co ${_EP_CVS_TAG} -d "${src_name}" "${_EP_CVS_MODULE}"
- )
- _ep_write_command_script(
- "${script_filename}"
- "${cmd}"
- "${work_dir}"
- "${genex_supported}"
- "${quiet}"
- script_does_something
- )
set(comment "Performing download step (CVS checkout) for '${name}'")
-
- elseif(DEFINED _EP_SVN_REPOSITORY)
+ set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q co ${cvs_tag} -d ${src_name} ${cvs_module})
+ list(APPEND depends ${stamp_dir}/${name}-cvsinfo.txt)
+ elseif(svn_repository)
find_package(Subversion QUIET)
if(NOT Subversion_SVN_EXECUTABLE)
message(FATAL_ERROR "error: could not find svn for checkout of ${name}")
endif()
- set(svn_repository "${_EP_SVN_REPOSITORY}")
- set(svn_revision "${_EP_SVN_REVISION}")
- set(svn_username "${_EP_SVN_USERNAME}")
- set(svn_password "${_EP_SVN_PASSWORD}")
- set(svn_trust_cert "${_EP_SVN_TRUST_CERT}")
+ get_property(svn_revision TARGET ${name} PROPERTY _EP_SVN_REVISION)
+ get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME)
+ get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD)
+ get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT)
- set(svn_options --non-interactive)
- if(DEFINED _EP_SVN_USERNAME)
- list(APPEND svn_options "--username=${svn_username}")
- endif()
- if(DEFINED _EP_SVN_PASSWORD)
- list(APPEND svn_options "--password=${svn_password}")
- endif()
- if(svn_trust_cert)
- list(APPEND svn_options --trust-server-cert)
- endif()
-
- set(repo_info_content
-"method=svn
-repository=${svn_repository}
-user=${svn_username}
-password=${svn_password}
-revision=${svn_revision}
-source_dir=${source_dir}
-")
+ set(repository "${svn_repository} user=${svn_username} password=${svn_password}")
+ set(module)
+ set(tag ${svn_revision})
configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/RepositoryInfo.txt.in
- ${repo_info_file}
+ "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
+ "${stamp_dir}/${name}-svninfo.txt"
@ONLY
- )
+ )
get_filename_component(src_name "${source_dir}" NAME)
get_filename_component(work_dir "${source_dir}" PATH)
-
- set(cmd "${Subversion_SVN_EXECUTABLE}" co "${svn_repository}"
- ${svn_revision} ${svn_options} "${src_name}"
- )
- _ep_write_command_script(
- "${script_filename}"
- "${cmd}"
- "${work_dir}"
- "${genex_supported}"
- "${quiet}"
- script_does_something
- )
set(comment "Performing download step (SVN checkout) for '${name}'")
-
- elseif(DEFINED _EP_GIT_REPOSITORY)
+ set(svn_user_pw_args "")
+ if(DEFINED svn_username)
+ set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
+ endif()
+ if(DEFINED svn_password)
+ set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}")
+ endif()
+ if(svn_trust_cert)
+ set(svn_trust_cert_args --trust-server-cert)
+ endif()
+ set(cmd ${Subversion_SVN_EXECUTABLE} co ${svn_repository} ${svn_revision}
+ --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args} ${src_name})
+ list(APPEND depends ${stamp_dir}/${name}-svninfo.txt)
+ elseif(git_repository)
# FetchContent gives us these directly, so don't try to recompute them
if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
@@ -2791,133 +2634,111 @@ source_dir=${source_dir}
endif()
endif()
- set(git_tag "${_EP_GIT_TAG}")
+ _ep_get_git_submodules_recurse(git_submodules_recurse)
+
+ get_property(git_tag TARGET ${name} PROPERTY _EP_GIT_TAG)
if(NOT git_tag)
set(git_tag "master")
endif()
- set(git_remote_name "${_EP_GIT_REMOTE_NAME}")
- if(NOT git_remote_name)
- set(git_remote_name "origin")
- endif()
-
set(git_init_submodules TRUE)
- if(DEFINED _EP_GIT_SUBMODULES)
- set(git_submodules "${_EP_GIT_SUBMODULES}")
- if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
+ get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET)
+ if(git_submodules_set)
+ get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
+ if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
set(git_init_submodules FALSE)
endif()
endif()
- _ep_get_git_submodules_recurse(git_submodules_recurse)
- set(tls_verify "${_EP_TLS_VERIFY}")
+ get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME)
+ if(NOT git_remote_name)
+ set(git_remote_name "origin")
+ endif()
+
+ get_property(tls_verify TARGET ${name} PROPERTY _EP_TLS_VERIFY)
if("x${tls_verify}" STREQUAL "x" AND DEFINED CMAKE_TLS_VERIFY)
set(tls_verify "${CMAKE_TLS_VERIFY}")
endif()
- set(git_shallow "${_EP_GIT_SHALLOW}")
- set(git_progress "${_EP_GIT_PROGRESS}")
- set(git_config "${_EP_GIT_CONFIG}")
+ get_property(git_shallow TARGET ${name} PROPERTY _EP_GIT_SHALLOW)
+ get_property(git_progress TARGET ${name} PROPERTY _EP_GIT_PROGRESS)
+ get_property(git_config TARGET ${name} PROPERTY _EP_GIT_CONFIG)
# Make checkouts quiet when checking out a git hash (this avoids the
# very noisy detached head message)
list(PREPEND git_config advice.detachedHead=false)
- # For the git clone operation, only the repository and remote should be
- # recorded in a configured repository info file. If the repo or remote
- # name changes, the clone script should be run again. But if only the tag
+ # For the download step, and the git clone operation, only the repository
+ # should be recorded in a configured RepositoryInfo file. If the repo
+ # changes, the clone script should be run again. But if only the tag
# changes, avoid running the clone script again. Let the 'always' running
# update step checkout the new tag.
- set(repo_info_content
-"method=git
-repository=${_EP_GIT_REPOSITORY}
-remote=${git_remote_name}
-source_dir=${source_dir}
-")
+ #
+ set(repository ${git_repository})
+ set(module)
+ set(tag ${git_remote_name})
configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/RepositoryInfo.txt.in
- ${repo_info_file}
+ "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
+ "${stamp_dir}/${name}-gitinfo.txt"
@ONLY
- )
+ )
get_filename_component(src_name "${source_dir}" NAME)
get_filename_component(work_dir "${source_dir}" PATH)
# Since git clone doesn't succeed if the non-empty source_dir exists,
- # the script will delete the source directory and then call git clone.
- _ep_write_gitclone_script(
- "${script_filename}"
- "${source_dir}"
- "${GIT_EXECUTABLE}"
- "${_EP_GIT_REPOSITORY}"
- "${git_tag}"
- "${git_remote_name}"
- "${git_init_submodules}"
- "${git_submodules_recurse}"
- "${git_submodules}"
- "${git_shallow}"
- "${git_progress}"
- "${git_config}"
- "${src_name}"
- "${work_dir}"
- "${repo_info_file}"
- "${last_run_file}"
- "${tls_verify}"
- "${quiet}"
- )
+ # create a cmake script to invoke as download command.
+ # The script will delete the source directory and then call git clone.
+ #
+ _ep_write_gitclone_script(${tmp_dir}/${name}-gitclone.cmake ${source_dir}
+ ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir}
+ ${stamp_dir}/${name}-gitinfo.txt ${stamp_dir}/${name}-gitclone-lastrun.txt "${tls_verify}"
+ )
set(comment "Performing download step (git clone) for '${name}'")
-
- elseif(DEFINED _EP_HG_REPOSITORY)
+ set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitclone.cmake)
+ list(APPEND depends ${stamp_dir}/${name}-gitinfo.txt)
+ elseif(hg_repository)
find_package(Hg QUIET)
if(NOT HG_EXECUTABLE)
message(FATAL_ERROR "error: could not find hg for clone of ${name}")
endif()
- set(hg_tag "${_EP_HG_TAG}")
+ get_property(hg_tag TARGET ${name} PROPERTY _EP_HG_TAG)
if(NOT hg_tag)
set(hg_tag "tip")
endif()
- # For the hg clone operation, only the repository should be recorded in a
- # configured repository info file. If the repo changes, the clone script
- # should be run again. But if only the tag changes, avoid running the
- # clone script again. Let the 'always' running update step checkout the
- # new tag.
- set(repo_info_content
-"method=hg
-repository=${_EP_HG_REPOSITORY}
-source_dir=${source_dir}
-")
+ # For the download step, and the hg clone operation, only the repository
+ # should be recorded in a configured RepositoryInfo file. If the repo
+ # changes, the clone script should be run again. But if only the tag
+ # changes, avoid running the clone script again. Let the 'always' running
+ # update step checkout the new tag.
+ #
+ set(repository ${hg_repository})
+ set(module)
+ set(tag)
configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/RepositoryInfo.txt.in
- ${repo_info_file}
+ "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
+ "${stamp_dir}/${name}-hginfo.txt"
@ONLY
- )
+ )
get_filename_component(src_name "${source_dir}" NAME)
get_filename_component(work_dir "${source_dir}" PATH)
# Since hg clone doesn't succeed if the non-empty source_dir exists,
- # the script will delete the source directory and then call hg clone.
- _ep_write_hgclone_script(
- "${script_filename}"
- "${source_dir}"
- "${HG_EXECUTABLE}"
- "${_EP_HG_REPOSITORY}"
- "${hg_tag}"
- "${src_name}"
- "${work_dir}"
- "${repo_info_file}"
- "${last_run_file}"
- "${quiet}"
- )
+ # create a cmake script to invoke as download command.
+ # The script will delete the source directory and then call hg clone.
+ #
+ _ep_write_hgclone_script(${tmp_dir}/${name}-hgclone.cmake ${source_dir}
+ ${HG_EXECUTABLE} ${hg_repository} ${hg_tag} ${src_name} ${work_dir}
+ ${stamp_dir}/${name}-hginfo.txt ${stamp_dir}/${name}-hgclone-lastrun.txt
+ )
set(comment "Performing download step (hg clone) for '${name}'")
-
- elseif(DEFINED _EP_URL)
- set(url "${_EP_URL}")
- # TODO: Perhaps file:// should be copied to download dir before extraction.
- string(REGEX REPLACE "file://" "" url "${url}")
-
- set(hash "${_EP_URL_HASH}")
+ set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-hgclone.cmake)
+ list(APPEND depends ${stamp_dir}/${name}-hginfo.txt)
+ elseif(url)
+ get_filename_component(work_dir "${source_dir}" PATH)
+ get_property(hash TARGET ${name} PROPERTY _EP_URL_HASH)
_ep_get_hash_regex(_ep_hash_regex)
if(hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}")
_ep_get_hash_algos(_ep_hash_algos)
@@ -2926,27 +2747,22 @@ source_dir=${source_dir}
"but must be ALGO=value where ALGO is\n ${_ep_hash_algos}\n"
"and value is a hex string.")
endif()
- set(md5 "${_EP_URL_MD5}")
+ get_property(md5 TARGET ${name} PROPERTY _EP_URL_MD5)
if(md5 AND NOT "MD5=${md5}" MATCHES "${_ep_hash_regex}")
message(FATAL_ERROR "URL_MD5 is set to\n ${md5}\nbut must be a hex string.")
endif()
if(md5 AND NOT hash)
set(hash "MD5=${md5}")
endif()
-
- set(repo_info_content
-"method=url
-url=${url}
-hash=${hash}
-source_dir=${source_dir}
-")
+ set(repository "external project URL")
+ set(module "${url}")
+ set(tag "${hash}")
configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/RepositoryInfo.txt.in
- ${repo_info_file}
+ "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
+ "${stamp_dir}/${name}-urlinfo.txt"
@ONLY
- )
-
- set(fname "${_EP_DOWNLOAD_NAME}")
+ )
+ list(APPEND depends ${stamp_dir}/${name}-urlinfo.txt)
list(LENGTH url url_list_length)
if(NOT "${url_list_length}" STREQUAL "1")
@@ -2961,21 +2777,12 @@ source_dir=${source_dir}
endif()
if(IS_DIRECTORY "${url}")
- get_filename_component(from_dir "${url}" ABSOLUTE)
- _ep_write_copydir_script(
- ${script_filename}
- ${from_dir}
- ${source_dir}
- )
- set(steps "DIR copy")
+ get_filename_component(abs_dir "${url}" ABSOLUTE)
+ set(comment "Performing download step (DIR copy) for '${name}'")
+ set(cmd ${CMAKE_COMMAND} -E rm -rf ${source_dir}
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir})
else()
- set(no_extract "${_EP_DOWNLOAD_NO_EXTRACT}")
- if(no_extract)
- set(extract_script)
- else()
- set(extract_script "${tmp_dir}/extract-${name}.cmake")
- endif()
-
+ get_property(no_extract TARGET "${name}" PROPERTY _EP_DOWNLOAD_NO_EXTRACT)
if("${url}" MATCHES "^[a-z]+://")
# TODO: Should download and extraction be different steps?
if("x${fname}" STREQUAL "x")
@@ -2989,70 +2796,55 @@ source_dir=${source_dir}
# Fall back to a default file name. The actual file name does not
# matter because it is used only internally and our extraction tool
# inspects the file content directly. If it turns out the wrong URL
- # was given, that will be revealed when the download is attempted
- # (during the build unless we are being invoked by FetchContent)
- # which is an easier place for users to diagnose than an error here.
+ # was given that will be revealed during the build which is an easier
+ # place for users to diagnose than an error here anyway.
set(fname "archive.tar")
endif()
string(REPLACE ";" "-" fname "${fname}")
set(file ${download_dir}/${fname})
- _ep_write_downloadfile_script(
- "${script_filename}"
- "${url}"
- "${file}"
- "${_EP_TIMEOUT}"
- "${_EP_INACTIVITY_TIMEOUT}"
- "${_EP_DOWNLOAD_NO_PROGRESS}"
- "${hash}"
- "${_EP_TLS_VERIFY}"
- "${_EP_TLS_CAINFO}"
- "${_EP_HTTP_USERNAME}:${_EP_HTTP_PASSWORD}"
- "${_EP_HTTP_HEADER}"
- "${_EP_NETRC}"
- "${_EP_NETRC_FILE}"
- "${extract_script}"
- "${quiet}"
- )
- if(no_extract)
+ get_property(timeout TARGET ${name} PROPERTY _EP_TIMEOUT)
+ get_property(inactivity_timeout TARGET ${name} PROPERTY _EP_INACTIVITY_TIMEOUT)
+ get_property(no_progress TARGET ${name} PROPERTY _EP_DOWNLOAD_NO_PROGRESS)
+ get_property(tls_verify TARGET ${name} PROPERTY _EP_TLS_VERIFY)
+ get_property(tls_cainfo TARGET ${name} PROPERTY _EP_TLS_CAINFO)
+ get_property(netrc TARGET ${name} PROPERTY _EP_NETRC)
+ get_property(netrc_file TARGET ${name} PROPERTY _EP_NETRC_FILE)
+ get_property(http_username TARGET ${name} PROPERTY _EP_HTTP_USERNAME)
+ get_property(http_password TARGET ${name} PROPERTY _EP_HTTP_PASSWORD)
+ get_property(http_headers TARGET ${name} PROPERTY _EP_HTTP_HEADER)
+ set(download_script "${stamp_dir}/download-${name}.cmake")
+ _ep_write_downloadfile_script("${download_script}" "${url}" "${file}" "${timeout}" "${inactivity_timeout}" "${no_progress}" "${hash}" "${tls_verify}" "${tls_cainfo}" "${http_username}:${http_password}" "${http_headers}" "${netrc}" "${netrc_file}")
+ set(cmd ${CMAKE_COMMAND} -P "${download_script}"
+ COMMAND)
+ if (no_extract)
set(steps "download and verify")
- else()
+ else ()
set(steps "download, verify and extract")
- endif()
+ endif ()
+ set(comment "Performing download step (${steps}) for '${name}'")
+ file(WRITE "${stamp_dir}/verify-${name}.cmake" "") # already verified by 'download_script'
else()
set(file "${url}")
- _ep_write_verifyfile_script(
- "${script_filename}"
- "${file}"
- "${hash}"
- "${extract_script}"
- "${quiet}"
- )
- if(no_extract)
+ if (no_extract)
set(steps "verify")
- else()
+ else ()
set(steps "verify and extract")
- endif()
- endif()
-
- if(no_extract)
- set(_EP_DOWNLOADED_FILE ${file} PARENT_SCOPE)
- else()
- # This will be pulled in by the download/verify script written above
- _ep_write_extractfile_script(
- "${extract_script}"
- "${name}"
- "${file}"
- "${source_dir}"
- "${quiet}"
- )
+ endif ()
+ set(comment "Performing download step (${steps}) for '${name}'")
+ _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}")
endif()
+ list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake)
+ if (NOT no_extract)
+ _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}")
+ list(APPEND cmd COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake)
+ else ()
+ set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
+ endif ()
endif()
- set(comment "Performing download step (${steps}) for '${name}'")
-
else()
_ep_is_dir_empty("${source_dir}" empty)
if(${empty})
- message(FATAL_ERROR
+ message(SEND_ERROR
"No download info given for '${name}' and its source directory:\n"
" ${source_dir}\n"
"is not an existing non-empty directory. Please specify one of:\n"
@@ -3065,149 +2857,105 @@ source_dir=${source_dir}
" * CVS_REPOSITORY and CVS_MODULE"
)
endif()
- set(repo_info_content
-"method=source_dir
-source_dir=${source_dir}
-")
- configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/RepositoryInfo.txt.in
- ${repo_info_file}
- @ONLY
- )
-
- set(comment "Skipping download step (SOURCE_DIR given) for '${name}'")
- set(script_does_something FALSE)
endif()
- # Provide variables that can be used later to create a custom command or
- # invoke the step directly
- if(script_does_something)
- set(cmd ${CMAKE_COMMAND} -P ${script_filename})
- if(log)
- _ep_write_log_script(${name} download "${genex_supported}" cmd)
- endif()
- set(depends ${repo_info_file})
+ get_property(log TARGET ${name} PROPERTY _EP_LOG_DOWNLOAD)
+ if(log)
+ set(log LOG 1)
else()
- set(cmd)
- set(depends)
- string(REPLACE "Performing" "Skipping" comment "${comment}")
+ set(log "")
endif()
- set(_EPcomment_DOWNLOAD "${comment}" PARENT_SCOPE)
- set(_EPcommand_DOWNLOAD "${cmd}" PARENT_SCOPE)
- set(_EPalways_DOWNLOAD FALSE PARENT_SCOPE)
- set(_EPexcludefrommain_DOWNLOAD FALSE PARENT_SCOPE)
- set(_EPdepends_DOWNLOAD "${depends}" PARENT_SCOPE)
- set(_EPdependees_DOWNLOAD mkdir PARENT_SCOPE)
+ get_property(uses_terminal TARGET ${name} PROPERTY
+ _EP_USES_TERMINAL_DOWNLOAD)
+ if(uses_terminal)
+ set(uses_terminal USES_TERMINAL 1)
+ else()
+ set(uses_terminal "")
+ endif()
+ set(__cmdQuoted)
+ foreach(__item IN LISTS cmd)
+ string(APPEND __cmdQuoted " [==[${__item}]==]")
+ endforeach()
+ cmake_language(EVAL CODE "
+ ExternalProject_Add_Step(\${name} download
+ INDEPENDENT TRUE
+ COMMENT \${comment}
+ COMMAND ${__cmdQuoted}
+ WORKING_DIRECTORY \${work_dir}
+ DEPENDS \${depends}
+ DEPENDEES mkdir
+ ${log}
+ ${uses_terminal}
+ )"
+ )
endfunction()
-function(_ep_get_update_disconnected var)
- if(DEFINED _EP_UPDATE_DISCONNECTED)
- set(update_disconnected "${_EP_UPDATE_DISCONNECTED}")
+function(_ep_get_update_disconnected var name)
+ get_property(update_disconnected_set TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED SET)
+ if(update_disconnected_set)
+ get_property(update_disconnected TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED)
else()
get_property(update_disconnected DIRECTORY PROPERTY EP_UPDATE_DISCONNECTED)
endif()
set(${var} "${update_disconnected}" PARENT_SCOPE)
endfunction()
-# 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>.
-#
-# Variables will also be set in the calling scope to enable subsequently
-# calling _ep_add_preconfigure_command() for the updated step.
-#
-function(_ep_prepare_update name genex_supported)
-
- set(tmp_dir "${_EP_TMP_DIR}")
- set(source_dir "${_EP_SOURCE_DIR}")
- set(quiet "${_EP_QUIET}")
+function(_ep_add_update_command name)
+ ExternalProject_Get_Property(${name} source_dir tmp_dir)
- set(comment)
+ get_property(cmd_set TARGET ${name} PROPERTY _EP_UPDATE_COMMAND SET)
+ get_property(cmd TARGET ${name} PROPERTY _EP_UPDATE_COMMAND)
+ get_property(cvs_repository TARGET ${name} PROPERTY _EP_CVS_REPOSITORY)
+ get_property(svn_repository TARGET ${name} PROPERTY _EP_SVN_REPOSITORY)
+ get_property(git_repository TARGET ${name} PROPERTY _EP_GIT_REPOSITORY)
+ get_property(hg_repository TARGET ${name} PROPERTY _EP_HG_REPOSITORY )
- _ep_get_update_disconnected(update_disconnected)
+ _ep_get_update_disconnected(update_disconnected ${name})
- # We handle the log setting directly here rather than deferring it to
- # be handled by ExternalProject_Add_Step()
- set(log "${_EP_LOG_UPDATE}")
- 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)
- endif()
+ set(work_dir)
+ set(comment)
+ set(always)
- if(DEFINED _EP_UPDATE_COMMAND)
+ if(cmd_set)
set(work_dir ${source_dir})
- _ep_write_command_script(
- "${script_filename}"
- "${_EP_UPDATE_COMMAND}"
- "${work_dir}"
- "${genex_supported}"
- "${quiet}"
- script_does_something
- )
- set(comment "Performing update step (custom command) for '${name}'")
-
- elseif(DEFINED _EP_CVS_REPOSITORY)
+ if(NOT "x${cmd}" STREQUAL "x")
+ set(always 1)
+ endif()
+ elseif(cvs_repository)
if(NOT CVS_EXECUTABLE)
message(FATAL_ERROR "error: could not find cvs for update of ${name}")
endif()
-
set(work_dir ${source_dir})
- set(cmd "${CVS_EXECUTABLE}" -d "${_EP_CVS_REPOSITORY}" -q
- up -dP ${_EP_CVS_TAG}
- )
- _ep_write_command_script(
- "${script_filename}"
- "${cmd}"
- "${work_dir}"
- "${genex_supported}"
- "${quiet}"
- script_does_something
- )
set(comment "Performing update step (CVS update) for '${name}'")
-
- elseif(DEFINED _EP_SVN_REPOSITORY)
+ get_property(cvs_tag TARGET ${name} PROPERTY _EP_CVS_TAG)
+ set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q up -dP ${cvs_tag})
+ set(always 1)
+ elseif(svn_repository)
if(NOT Subversion_SVN_EXECUTABLE)
message(FATAL_ERROR "error: could not find svn for update of ${name}")
endif()
-
- set(svn_revision "${_EP_SVN_REVISION}")
- set(svn_username "${_EP_SVN_USERNAME}")
- set(svn_password "${_EP_SVN_PASSWORD}")
- set(svn_trust_cert "${_EP_SVN_TRUST_CERT}")
-
- set(svn_options --non-interactive)
- if(DEFINED _EP_SVN_USERNAME)
- list(APPEND svn_options "--username=${svn_username}")
+ set(work_dir ${source_dir})
+ set(comment "Performing update step (SVN update) for '${name}'")
+ get_property(svn_revision TARGET ${name} PROPERTY _EP_SVN_REVISION)
+ get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME)
+ get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD)
+ get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT)
+ set(svn_user_pw_args "")
+ if(DEFINED svn_username)
+ set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
endif()
- if(DEFINED _EP_SVN_PASSWORD)
- list(APPEND svn_options "--password=${svn_password}")
+ if(DEFINED svn_password)
+ set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}")
endif()
if(svn_trust_cert)
- list(APPEND svn_options --trust-server-cert)
+ set(svn_trust_cert_args --trust-server-cert)
endif()
-
- set(work_dir ${source_dir})
- set(cmd "${Subversion_SVN_EXECUTABLE}" up ${svn_revision} ${svn_options})
-
- _ep_write_command_script(
- "${script_filename}"
- "${cmd}"
- "${work_dir}"
- "${genex_supported}"
- "${quiet}"
- script_does_something
- )
- set(comment "Performing update step (SVN update) for '${name}'")
-
- elseif(DEFINED _EP_GIT_REPOSITORY)
+ set(cmd ${Subversion_SVN_EXECUTABLE} up ${svn_revision}
+ --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args})
+ set(always 1)
+ elseif(git_repository)
# FetchContent gives us these directly, so don't try to recompute them
if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
@@ -3216,27 +2964,27 @@ function(_ep_prepare_update name genex_supported)
message(FATAL_ERROR "error: could not find git for fetch of ${name}")
endif()
endif()
-
- set(git_tag "${_EP_GIT_TAG}")
+ set(work_dir ${source_dir})
+ set(comment "Performing update step for '${name}'")
+ get_property(git_tag TARGET ${name} PROPERTY _EP_GIT_TAG)
if(NOT git_tag)
set(git_tag "master")
endif()
-
- set(git_remote_name "${_EP_GIT_REMOTE_NAME}")
+ get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME)
if(NOT git_remote_name)
set(git_remote_name "origin")
endif()
set(git_init_submodules TRUE)
- if(DEFINED _EP_GIT_SUBMODULES)
- set(git_submodules "${_EP_GIT_SUBMODULES}")
+ get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET)
+ if(git_submodules_set)
+ get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
set(git_init_submodules FALSE)
endif()
endif()
- _ep_get_git_submodules_recurse(git_submodules_recurse)
- set(git_update_strategy "${_EP_GIT_REMOTE_UPDATE_STRATEGY}")
+ get_property(git_update_strategy TARGET ${name} PROPERTY _EP_GIT_REMOTE_UPDATE_STRATEGY)
if(NOT git_update_strategy)
set(git_update_strategy "${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}")
endif()
@@ -3248,28 +2996,23 @@ function(_ep_prepare_update name genex_supported)
message(FATAL_ERROR "'${git_update_strategy}' is not one of the supported strategies: ${strategies}")
endif()
- set(work_dir ${source_dir})
- _ep_write_gitupdate_script(
- "${script_filename}"
- "${GIT_EXECUTABLE}"
- "${git_tag}"
- "${git_remote_name}"
- "${git_init_submodules}"
- "${git_submodules_recurse}"
- "${git_submodules}"
- "${_EP_GIT_REPOSITORY}"
- "${work_dir}"
- "${git_update_strategy}"
- "${quiet}"
- )
- set(script_does_something TRUE)
- set(comment "Performing update step (git update) for '${name}'")
+ _ep_get_git_submodules_recurse(git_submodules_recurse)
- elseif(DEFINED _EP_HG_REPOSITORY)
+ _ep_write_gitupdate_script(${tmp_dir}/${name}-gitupdate.cmake
+ ${GIT_EXECUTABLE} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" ${git_repository} ${work_dir} ${git_update_strategy}
+ )
+ set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitupdate.cmake)
+ set(always 1)
+ elseif(hg_repository)
if(NOT HG_EXECUTABLE)
message(FATAL_ERROR "error: could not find hg for pull of ${name}")
endif()
-
+ set(work_dir ${source_dir})
+ set(comment "Performing update step (hg pull) for '${name}'")
+ get_property(hg_tag TARGET ${name} PROPERTY _EP_HG_TAG)
+ if(NOT hg_tag)
+ set(hg_tag "tip")
+ endif()
if("${HG_VERSION_STRING}" STREQUAL "2.1")
message(WARNING "Mercurial 2.1 does not distinguish an empty pull from a failed pull:
http://mercurial.selenic.com/wiki/UpgradeNotes#A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X
@@ -3277,117 +3020,87 @@ function(_ep_prepare_update name genex_supported)
Update to Mercurial >= 2.1.1.
")
endif()
+ set(cmd ${HG_EXECUTABLE} pull
+ COMMAND ${HG_EXECUTABLE} update ${hg_tag}
+ )
+ set(always 1)
+ endif()
- set(hg_tag "${_EP_HG_TAG}")
- if(NOT hg_tag)
- set(hg_tag "tip")
- endif()
-
- set(work_dir ${source_dir})
- _ep_write_hgupdate_script(
- "${script_filename}"
- "${HG_EXECUTABLE}"
- "${hg_tag}"
- "${work_dir}"
- "${quiet}"
- )
- set(script_does_something TRUE)
- set(comment "Performing update step (hg pull) for '${name}'")
-
+ get_property(log TARGET ${name} PROPERTY _EP_LOG_UPDATE)
+ if(log)
+ set(log LOG 1)
else()
- set(script_does_something FALSE)
+ set(log "")
endif()
- # Provide variables that can be used later to create a custom command or
- # invoke the step directly
- if(script_does_something)
- set(always TRUE)
- set(cmd ${CMAKE_COMMAND} -P ${script_filename})
- if(log)
- _ep_write_log_script(${name} update "${genex_supported}" cmd)
- endif()
+ get_property(uses_terminal TARGET ${name} PROPERTY
+ _EP_USES_TERMINAL_UPDATE)
+ if(uses_terminal)
+ set(uses_terminal USES_TERMINAL 1)
else()
- set(always FALSE)
- set(cmd)
+ set(uses_terminal "")
endif()
- set(_EPcomment_UPDATE "${comment}" PARENT_SCOPE)
- set(_EPcommand_UPDATE "${cmd}" PARENT_SCOPE)
- set(_EPalways_UPDATE "${always}" PARENT_SCOPE)
- set(_EPexcludefrommain_UPDATE "${update_disconnected}" PARENT_SCOPE)
- set(_EPdepends_UPDATE "" PARENT_SCOPE)
- set(_EPdependees_UPDATE download PARENT_SCOPE)
+ set(__cmdQuoted)
+ foreach(__item IN LISTS cmd)
+ string(APPEND __cmdQuoted " [==[${__item}]==]")
+ endforeach()
+ cmake_language(EVAL CODE "
+ ExternalProject_Add_Step(${name} update
+ INDEPENDENT TRUE
+ COMMENT \${comment}
+ COMMAND ${__cmdQuoted}
+ ALWAYS \${always}
+ EXCLUDE_FROM_MAIN \${update_disconnected}
+ WORKING_DIRECTORY \${work_dir}
+ DEPENDEES download
+ ${log}
+ ${uses_terminal}
+ )"
+ )
endfunction()
-# 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>.
-#
-# Variables will also be set in the calling scope to enable subsequently
-# calling _ep_add_preconfigure_command() for the patch step.
-#
-function(_ep_prepare_patch name genex_supported)
- set(tmp_dir "${_EP_TMP_DIR}")
- set(source_dir "${_EP_SOURCE_DIR}")
- set(quiet "${_EP_QUIET}")
+function(_ep_add_patch_command name)
+ ExternalProject_Get_Property(${name} source_dir)
- _ep_get_update_disconnected(update_disconnected)
- if(update_disconnected)
- set(patch_dep download)
- else()
- set(patch_dep update)
+ get_property(cmd_set TARGET ${name} PROPERTY _EP_PATCH_COMMAND SET)
+ get_property(cmd TARGET ${name} PROPERTY _EP_PATCH_COMMAND)
+
+ set(work_dir)
+
+ if(cmd_set)
+ set(work_dir ${source_dir})
endif()
- # We handle the log setting directly here rather than deferring it to
- # be handled by ExternalProject_Add_Step()
- set(log "${_EP_LOG_PATCH}")
+ get_property(log TARGET ${name} PROPERTY _EP_LOG_PATCH)
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
+ set(log LOG 1)
else()
- set(script_filename ${tmp_dir}/${name}-patch.cmake)
- set(log FALSE)
+ set(log "")
endif()
- if(DEFINED _EP_PATCH_COMMAND)
- set(work_dir "${source_dir}")
- _ep_write_command_script(
- "${script_filename}"
- "${_EP_PATCH_COMMAND}"
- "${work_dir}"
- "${genex_supported}"
- "${quiet}"
- script_does_something
- )
- if(script_does_something)
- set(cmd ${CMAKE_COMMAND} -P ${script_filename})
- if(log)
- _ep_write_log_script(${name} patch "${genex_supported}" cmd)
- endif()
- set(comment "Performing patch step (custom command) for '${name}'")
- else()
- set(cmd)
- set(comment "Skipping patch step (empty custom command) for '${name}'")
- endif()
+ _ep_get_update_disconnected(update_disconnected ${name})
+ if(update_disconnected)
+ set(patch_dep download)
else()
- set(cmd)
- set(comment "Skipping patch step (no custom command) for '${name}'")
+ set(patch_dep update)
endif()
- # Provide variables that can be used later to create a custom command or
- # invoke the step directly
- set(_EPcomment_PATCH "${comment}" PARENT_SCOPE)
- set(_EPcommand_PATCH "${cmd}" PARENT_SCOPE)
- set(_EPalways_PATCH FALSE PARENT_SCOPE)
- set(_EPexcludefrommain_PATCH FALSE PARENT_SCOPE)
- set(_EPdepends_PATCH "" PARENT_SCOPE)
- set(_EPdependees_PATCH "${patch_dep}" PARENT_SCOPE)
-
+ set(__cmdQuoted)
+ foreach(__item IN LISTS cmd)
+ string(APPEND __cmdQuoted " [==[${__item}]==]")
+ endforeach()
+ cmake_language(EVAL CODE "
+ ExternalProject_Add_Step(${name} patch
+ INDEPENDENT TRUE
+ COMMAND ${__cmdQuoted}
+ WORKING_DIRECTORY \${work_dir}
+ DEPENDEES \${patch_dep}
+ ${log}
+ )"
+ )
endfunction()
function(_ep_get_file_deps var name)
@@ -3497,11 +3210,7 @@ function(_ep_extract_configure_command var name)
if(has_cmake_cache_default_args)
_ep_command_line_to_initial_cache(script_initial_cache_default "${cmake_cache_default_args}" 0)
endif()
- _ep_write_initial_cache(
- ${name}
- "${_ep_cache_args_script}"
- "${script_initial_cache_force}${script_initial_cache_default}"
- )
+ _ep_write_initial_cache(${name} "${_ep_cache_args_script}" "${script_initial_cache_force}${script_initial_cache_default}")
list(APPEND cmd "-C${_ep_cache_args_script}")
_ep_replace_location_tags(${name} _ep_cache_args_script)
set(_ep_cache_args_script
@@ -3533,11 +3242,10 @@ function(_ep_add_configure_command name)
# used, cmake args or cmake generator) then re-run the configure step.
# Fixes issue https://gitlab.kitware.com/cmake/cmake/-/issues/10258
#
- configure_file(
- ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/cfgcmd.txt.in
- ${tmp_dir}/${name}-cfgcmd.txt
- @ONLY
- )
+ if(NOT EXISTS ${tmp_dir}/${name}-cfgcmd.txt.in)
+ file(WRITE ${tmp_dir}/${name}-cfgcmd.txt.in "cmd='\@cmd\@'\n")
+ endif()
+ configure_file(${tmp_dir}/${name}-cfgcmd.txt.in ${tmp_dir}/${name}-cfgcmd.txt)
list(APPEND file_deps ${tmp_dir}/${name}-cfgcmd.txt)
list(APPEND file_deps ${_ep_cache_args_script})
@@ -3748,8 +3456,51 @@ function(_ep_add_test_command name)
endif()
endfunction()
-macro(_ep_get_add_keywords out_var)
- set(${out_var}
+
+function(ExternalProject_Add name)
+ cmake_policy(GET CMP0097 _EP_CMP0097
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
+ cmake_policy(GET CMP0114 cmp0114
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
+ if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12 AND NOT cmp0114 STREQUAL "NEW")
+ message(AUTHOR_WARNING
+ "Policy CMP0114 is not set to NEW. "
+ "In order to support the Xcode \"new build system\", "
+ "this project must be updated to set policy CMP0114 to NEW."
+ "\n"
+ "Since CMake is generating for the Xcode \"new build system\", "
+ "ExternalProject_Add will use policy CMP0114's NEW behavior anyway, "
+ "but the generated build system may not match what the project intends."
+ )
+ set(cmp0114 "NEW")
+ endif()
+
+ _ep_get_configuration_subdir_suffix(cfgdir)
+
+ # Add a custom target for the external project.
+ set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles)
+ _ep_get_complete_stampfile(${name} complete_stamp_file)
+
+ cmake_policy(PUSH)
+ if(cmp0114 STREQUAL "NEW")
+ # To implement CMP0114 NEW behavior with Makefile generators,
+ # we need CMP0113 NEW behavior.
+ cmake_policy(SET CMP0113 NEW)
+ endif()
+ # The "ALL" option to add_custom_target just tells it to not set the
+ # EXCLUDE_FROM_ALL target property. Later, if the EXCLUDE_FROM_ALL
+ # argument was passed, we explicitly set it for the target.
+ add_custom_target(${name} ALL DEPENDS ${complete_stamp_file})
+ cmake_policy(POP)
+ set_property(TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT 1)
+ set_property(TARGET ${name} PROPERTY LABELS ${name})
+ set_property(TARGET ${name} PROPERTY FOLDER "ExternalProjectTargets/${name}")
+
+ set_property(TARGET ${name} PROPERTY _EP_CMP0114 "${cmp0114}")
+
+ set(keywords
#
# Directory options
#
@@ -3878,145 +3629,14 @@ macro(_ep_get_add_keywords out_var)
#
LIST_SEPARATOR
)
-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 patch)
- 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}})
- # IS_NEWER_THAN is also true if the timestamps are the same. On some
- # file systems, we only have second resolution timestamps and the
- # likelihood of having the same timestamp is high. Use the negative
- # form to ensure we actually get a true "is newer than" test.
- if(NOT EXISTS ${dep_file} OR
- NOT ${stamp_file} IS_NEWER_THAN ${dep_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
- )
- cmake_policy(GET CMP0114 cmp0114
- PARENT_SCOPE # undocumented, do not use outside of CMake
- )
- if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12 AND NOT cmp0114 STREQUAL "NEW")
- message(AUTHOR_WARNING
- "Policy CMP0114 is not set to NEW. "
- "In order to support the Xcode \"new build system\", "
- "this project must be updated to set policy CMP0114 to NEW."
- "\n"
- "Since CMake is generating for the Xcode \"new build system\", "
- "ExternalProject_Add will use policy CMP0114's NEW behavior anyway, "
- "but the generated build system may not match what the project intends."
- )
- set(cmp0114 "NEW")
- endif()
-
- set(genex_supported TRUE)
-
- _ep_get_add_keywords(keywords)
- _ep_parse_arguments_to_vars("${keywords}" ${name} _EP_ "${ARGN}")
- _ep_prepare_directories(${name})
- _ep_prepare_download(${name} ${genex_supported})
- _ep_prepare_update(${name} ${genex_supported})
- _ep_prepare_patch(${name} ${genex_supported})
-
- _ep_get_configuration_subdir_suffix(cfgdir)
-
- # Add a custom target for the external project.
- set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles)
- _ep_get_complete_stampfile(${name} complete_stamp_file)
-
- cmake_policy(PUSH)
- if(cmp0114 STREQUAL "NEW")
- # To implement CMP0114 NEW behavior with Makefile generators,
- # we need CMP0113 NEW behavior.
- cmake_policy(SET CMP0113 NEW)
- endif()
- # The "ALL" option to add_custom_target just tells it to not set the
- # EXCLUDE_FROM_ALL target property. Later, if the EXCLUDE_FROM_ALL
- # argument was passed, we explicitly set it for the target.
- add_custom_target(${name} ALL DEPENDS ${complete_stamp_file})
- cmake_policy(POP)
- set_property(TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT 1)
- set_property(TARGET ${name} PROPERTY LABELS ${name})
- set_property(TARGET ${name} PROPERTY FOLDER "ExternalProjectTargets/${name}")
-
- set_property(TARGET ${name} PROPERTY _EP_CMP0114 "${cmp0114}")
-
- # Transfer the arguments to the target as target properties. These are
- # read by the various steps, potentially from different scopes.
- foreach(key IN LISTS keywords ITEMS DOWNLOADED_FILE)
- if(DEFINED _EP_${key})
- set_property(TARGET ${name} PROPERTY _EP_${key} "${_EP_${key}}")
- endif()
- endforeach()
-
+ _ep_parse_arguments(ExternalProject_Add "${keywords}" ${name} _EP_ "${ARGN}")
+ _ep_set_directories(${name})
_ep_get_step_stampfile(${name} "done" done_stamp_file)
_ep_get_step_stampfile(${name} "install" install_stamp_file)
- if(arg_EXCLUDE_FROM_ALL)
+ # Set the EXCLUDE_FROM_ALL target property if required.
+ get_property(exclude_from_all TARGET ${name} PROPERTY _EP_EXCLUDE_FROM_ALL)
+ if(exclude_from_all)
set_property(TARGET ${name} PROPERTY EXCLUDE_FROM_ALL TRUE)
endif()
@@ -4057,10 +3677,10 @@ function(ExternalProject_Add name)
# The target depends on the output of the final step.
# (Already set up above in the DEPENDS of the add_custom_target command.)
#
- _ep_add_preconfigure_command(${name} mkdir)
- _ep_add_preconfigure_command(${name} download)
- _ep_add_preconfigure_command(${name} update)
- _ep_add_preconfigure_command(${name} patch)
+ _ep_add_mkdir_command(${name})
+ _ep_add_download_command(${name})
+ _ep_add_update_command(${name})
+ _ep_add_patch_command(${name})
_ep_add_configure_command(${name})
_ep_add_build_command(${name})
_ep_add_install_command(${name})
diff --git a/Modules/ExternalProject/RepositoryInfo.txt.in b/Modules/ExternalProject/RepositoryInfo.txt.in
deleted file mode 100644
index d82f04c724..0000000000
--- a/Modules/ExternalProject/RepositoryInfo.txt.in
+++ /dev/null
@@ -1 +0,0 @@
-@repo_info_content@
diff --git a/Modules/ExternalProject/captured_process_setup.cmake b/Modules/ExternalProject/captured_process_setup.cmake
deleted file mode 100644
index 9c8abb1203..0000000000
--- a/Modules/ExternalProject/captured_process_setup.cmake
+++ /dev/null
@@ -1,55 +0,0 @@
-# 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/cfgcmd.txt.in b/Modules/ExternalProject/cfgcmd.txt.in
deleted file mode 100644
index b3f09efc8d..0000000000
--- a/Modules/ExternalProject/cfgcmd.txt.in
+++ /dev/null
@@ -1 +0,0 @@
-cmd='@cmd@'
diff --git a/Modules/ExternalProject/copydir.cmake.in b/Modules/ExternalProject/copydir.cmake.in
deleted file mode 100644
index 5dd3891c3f..0000000000
--- a/Modules/ExternalProject/copydir.cmake.in
+++ /dev/null
@@ -1,10 +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 3.5)
-
-file(REMOVE_RECURSE "@to_dir@")
-
-# Copy the _contents_ of the source dir into the destination dir, hence the
-# trailing slash on the from_dir
-file(COPY "@from_dir@/" DESTINATION "@to_dir@")
diff --git a/Modules/ExternalProject/customcommand.cmake.in b/Modules/ExternalProject/customcommand.cmake.in
deleted file mode 100644
index d41f31b83e..0000000000
--- a/Modules/ExternalProject/customcommand.cmake.in
+++ /dev/null
@@ -1,8 +0,0 @@
-
-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
deleted file mode 100644
index ae4fec66cd..0000000000
--- a/Modules/ExternalProject/customcommand_preamble.cmake.in
+++ /dev/null
@@ -1,8 +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 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
deleted file mode 100644
index c8d2f28f18..0000000000
--- a/Modules/ExternalProject/download.cmake.in
+++ /dev/null
@@ -1,205 +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 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 "")
- _ep_message_quiet_capture(FATAL_ERROR "has_hash Can't be empty")
- endif()
-
- if("${hash_is_good}" STREQUAL "")
- _ep_message_quiet_capture(FATAL_ERROR "hash_is_good Can't be empty")
- endif()
-
- if("@ALGO@" STREQUAL "")
- # No check
- set("${has_hash}" FALSE PARENT_SCOPE)
- set("${hash_is_good}" FALSE PARENT_SCOPE)
- return()
- endif()
-
- set("${has_hash}" TRUE PARENT_SCOPE)
-
- _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)
- _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()
-endfunction()
-
-function(sleep_before_download attempt)
- if(attempt EQUAL 0)
- return()
- endif()
-
- if(attempt EQUAL 1)
- _ep_message_quiet_capture(STATUS "Retrying...")
- set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
- return()
- endif()
-
- set(sleep_seconds 0)
-
- if(attempt EQUAL 2)
- set(sleep_seconds 5)
- elseif(attempt EQUAL 3)
- set(sleep_seconds 5)
- elseif(attempt EQUAL 4)
- set(sleep_seconds 15)
- elseif(attempt EQUAL 5)
- set(sleep_seconds 60)
- elseif(attempt EQUAL 6)
- set(sleep_seconds 90)
- elseif(attempt EQUAL 7)
- set(sleep_seconds 300)
- else()
- set(sleep_seconds 1200)
- endif()
-
- _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()
-
-if("@LOCAL@" STREQUAL "")
- message(FATAL_ERROR "LOCAL can't be empty")
-endif()
-
-if("@REMOTE@" STREQUAL "")
- message(FATAL_ERROR "REMOTE can't be empty")
-endif()
-
-function(download_and_verify)
- if(EXISTS "@LOCAL@")
- check_file_hash(has_hash hash_is_good)
- if(has_hash)
- if(hash_is_good)
- _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()
- _ep_message_quiet_capture(STATUS
- "File already exists but hash mismatch. Removing..."
- )
- set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
- file(REMOVE "@LOCAL@")
- endif()
- else()
- _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."
- )
- file(REMOVE "@LOCAL@")
- endif()
- endif()
-
- set(retry_number 5)
-
- _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)
- foreach(i RANGE ${retry_number})
- if(status_code IN_LIST download_retry_codes)
- sleep_before_download(${i})
- endif()
- foreach(url @REMOTE@)
- if(NOT url IN_LIST skip_url_list)
- _ep_message_quiet_capture(STATUS "Using src='${url}'")
- set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
-
- @TLS_VERIFY_CODE@
- @TLS_CAINFO_CODE@
- @NETRC_CODE@
- @NETRC_FILE_CODE@
-
- file(
- DOWNLOAD
- "${url}" "@LOCAL@"
- @SHOW_PROGRESS@
- @TIMEOUT_ARGS@
- @INACTIVITY_TIMEOUT_ARGS@
- STATUS status
- LOG log
- @USERPWD_ARGS@
- @HTTP_HEADERS_ARGS@
- )
-
- list(GET status 0 status_code)
- list(GET status 1 status_string)
-
- if(status_code EQUAL 0)
- check_file_hash(has_hash hash_is_good)
- if(has_hash AND NOT hash_is_good)
- _ep_message_quiet_capture(STATUS "Hash mismatch, removing...")
- set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
- file(REMOVE "@LOCAL@")
- else()
- _ep_message_quiet_capture(STATUS "Downloading... done")
- set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
- return()
- endif()
- else()
- string(APPEND logFailedURLs
-"error: downloading '${url}' failed
- status_code: ${status_code}
- status_string: ${status_string}
- log:
- --- LOG BEGIN ---
- ${log}
- --- LOG END ---
- "
- )
- if(NOT status_code IN_LIST download_retry_codes)
- list(APPEND skip_url_list "${url}")
- break()
- endif()
- endif()
- endif()
- endforeach()
- endforeach()
-
- _ep_message_quiet_capture(FATAL_ERROR
-"Each download failed!
- ${logFailedURLs}
- "
- )
-
-endfunction()
-
-download_and_verify()
-
-set(extract_script @extract_script_filename@)
-if(NOT "${extract_script}" STREQUAL "")
- include(${extract_script})
-endif()
diff --git a/Modules/ExternalProject/extractfile.cmake.in b/Modules/ExternalProject/extractfile.cmake.in
deleted file mode 100644
index d46de73408..0000000000
--- a/Modules/ExternalProject/extractfile.cmake.in
+++ /dev/null
@@ -1,73 +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 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)
-
-_ep_message_quiet_capture(STATUS "extracting...
- src='${filename}'
- dst='${directory}'"
-)
-
-if(NOT EXISTS "${filename}")
- _ep_message_quiet_capture(FATAL_ERROR
- "File to extract does not exist: '${filename}'"
- )
-endif()
-
-# Prepare a space for extracting:
-#
-set(i 1234)
-while(EXISTS "${directory}/../ex-@name@${i}")
- math(EXPR i "${i} + 1")
-endwhile()
-set(ut_dir "${directory}/../ex-@name@${i}")
-file(MAKE_DIRECTORY "${ut_dir}")
-
-# Extract it:
-#
-_ep_message_quiet_capture(STATUS "extracting... [tar @args@]")
-execute_process(COMMAND ${CMAKE_COMMAND} -E tar @args@ ${filename}
- WORKING_DIRECTORY ${ut_dir}
- RESULT_VARIABLE rv
- ${capture_output}
-)
-_ep_accumulate_captured_output()
-
-if(NOT rv EQUAL 0)
- _ep_message_quiet_capture(STATUS "extracting... [error clean up]")
- file(REMOVE_RECURSE "${ut_dir}")
- _ep_message_quiet_capture(FATAL_ERROR "Extract of '${filename}' failed")
-endif()
-
-# Analyze what came out of the tar file:
-#
-_ep_message_quiet_capture(STATUS "extracting... [analysis]")
-file(GLOB contents "${ut_dir}/*")
-list(REMOVE_ITEM contents "${ut_dir}/.DS_Store")
-list(LENGTH contents n)
-if(NOT n EQUAL 1 OR NOT IS_DIRECTORY "${contents}")
- set(contents "${ut_dir}")
-endif()
-
-# Move "the one" directory to the final directory:
-#
-_ep_message_quiet_capture(STATUS "extracting... [rename]")
-file(REMOVE_RECURSE ${directory})
-get_filename_component(contents ${contents} ABSOLUTE)
-file(RENAME ${contents} ${directory})
-
-# Clean up:
-#
-_ep_message_quiet_capture(STATUS "extracting... [clean up]")
-file(REMOVE_RECURSE "${ut_dir}")
-
-_ep_message_quiet_capture(STATUS "extracting... done")
diff --git a/Modules/ExternalProject/gitclone.cmake.in b/Modules/ExternalProject/gitclone.cmake.in
deleted file mode 100644
index edbdd72bde..0000000000
--- a/Modules/ExternalProject/gitclone.cmake.in
+++ /dev/null
@@ -1,93 +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 3.5)
-
-set(quiet "@quiet@")
-set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject")
-include(${script_dir}/captured_process_setup.cmake)
-
-if(EXISTS "@gitclone_stampfile@" AND EXISTS "@gitclone_infofile@" AND
- "@gitclone_stampfile@" IS_NEWER_THAN "@gitclone_infofile@")
- 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
- ${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@"
- 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)
- 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--@
- WORKING_DIRECTORY "@work_dir@/@src_name@"
- RESULT_VARIABLE error_code
- ${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@
- WORKING_DIRECTORY "@work_dir@/@src_name@"
- RESULT_VARIABLE error_code
- ${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:
-#
-execute_process(
- COMMAND ${CMAKE_COMMAND} -E copy "@gitclone_infofile@" "@gitclone_stampfile@"
- RESULT_VARIABLE error_code
- ${capture_output}
-)
-_ep_command_check_result(
- error_code "Failed to copy script-last-run stamp file: '@gitclone_stampfile@'"
-)
diff --git a/Modules/ExternalProject/hgclone.cmake.in b/Modules/ExternalProject/hgclone.cmake.in
deleted file mode 100644
index 9a574d201c..0000000000
--- a/Modules/ExternalProject/hgclone.cmake.in
+++ /dev/null
@@ -1,59 +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 3.5)
-
-set(quiet "@quiet@")
-set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject")
-include(${script_dir}/captured_process_setup.cmake)
-
-if(EXISTS "@hgclone_stampfile@" AND EXISTS "@hgclone_infofile@" AND
- "@hgclone_stampfile@" IS_NEWER_THAN "@hgclone_infofile@")
- 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
- ${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
- ${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
- ${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
- ${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
deleted file mode 100644
index a82a819f47..0000000000
--- a/Modules/ExternalProject/hgupdate.cmake.in
+++ /dev/null
@@ -1,24 +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 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
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- ${capture_output}
-)
-_ep_command_check_result(error_code)
-
-execute_process(
- COMMAND "@hg_EXECUTABLE@" update @hg_tag@
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- ${capture_output}
-)
-_ep_command_check_result(error_code)
diff --git a/Modules/ExternalProject/mkdirs.cmake.in b/Modules/ExternalProject/mkdirs.cmake.in
deleted file mode 100644
index 73e80fad29..0000000000
--- a/Modules/ExternalProject/mkdirs.cmake.in
+++ /dev/null
@@ -1,19 +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 3.5)
-
-file(MAKE_DIRECTORY
- "@source_dir@"
- "@binary_dir@"
- "@install_dir@"
- "@tmp_dir@"
- "@stamp_dir@"
- "@download_dir@"
- "@log_dir@"
-)
-
-set(configSubDirs @CMAKE_CONFIGURATION_TYPES@)
-foreach(subDir IN LISTS configSubDirs)
- file(MAKE_DIRECTORY "@stamp_dir@/${subDir}")
-endforeach()
diff --git a/Modules/ExternalProject/verify.cmake.in b/Modules/ExternalProject/verify.cmake.in
deleted file mode 100644
index cd34ba95ea..0000000000
--- a/Modules/ExternalProject/verify.cmake.in
+++ /dev/null
@@ -1,58 +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 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()
-
-if(NOT EXISTS "@LOCAL@")
- message(FATAL_ERROR "File not found: @LOCAL@")
-endif()
-
-function(do_verify)
- if("@ALGO@" STREQUAL "")
- _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 "")
- _ep_message_quiet_capture(FATAL_ERROR "EXPECT_VALUE can't be empty")
- endif()
-
- _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@")
- _ep_message_quiet_capture(FATAL_ERROR
-"error: @ALGO@ hash of
- @LOCAL@
-does not match expected value
- expected: '@EXPECT_VALUE@'
- actual: '${actual_value}'
-")
- endif()
-
- _ep_message_quiet_capture(STATUS "verifying file... done")
- set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
-endfunction()
-
-do_verify()
-
-set(extract_script "@extract_script_filename@")
-if(NOT "${extract_script}" STREQUAL "")
- include("${extract_script}")
-endif()
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 6a4cf38884..8adef47778 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -849,6 +849,8 @@ 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
@@ -892,28 +894,123 @@ function(__FetchContent_directPopulate contentName)
set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE)
set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE)
- if(ARG_QUIET)
- set(quiet TRUE)
+ # 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\"
+)
+")
else()
- set(quiet FALSE)
+ 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)
message(STATUS "Populating ${contentName}")
endif()
- 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(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}"
)
+ 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
new file mode 100644
index 0000000000..5ebb12f1ad
--- /dev/null
+++ b/Modules/FetchContent/CMakeLists.cmake.in
@@ -0,0 +1,27 @@
+# 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/Modules/RepositoryInfo.txt.in b/Modules/RepositoryInfo.txt.in
new file mode 100644
index 0000000000..df8e32272d
--- /dev/null
+++ b/Modules/RepositoryInfo.txt.in
@@ -0,0 +1,3 @@
+repository='@repository@'
+module='@module@'
+tag='@tag@'
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt
index 22d7ac050b..5a5ba891d4 100644
--- a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-stderr.txt
@@ -10,7 +10,7 @@ Call Stack \(most recent call first\):
[^
]*/Modules/ExternalProject.cmake:[0-9]+ \(ExternalProject_Add_Step\)
[^
-]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_preconfigure_command\)
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_mkdir_command\)
NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
NO_DEPENDS-CMP0114-NEW.cmake:[0-9]+ \(include\)
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt
index 0172e3f4e8..bbf7178f27 100644
--- a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-WARN-stderr.txt
@@ -13,7 +13,7 @@ Call Stack \(most recent call first\):
[^
]*/Modules/ExternalProject.cmake:[0-9]+ \(ExternalProject_Add_Step\)
[^
-]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_preconfigure_command\)
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_mkdir_command\)
NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
CMakeLists.txt:[0-9]+ \(include\)
@@ -68,7 +68,7 @@ Call Stack \(most recent call first\):
[^
]*/Modules/ExternalProject.cmake:[0-9]+ \(ExternalProject_Add_Step\)
[^
-]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_preconfigure_command\)
+]*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_mkdir_command\)
NO_DEPENDS-CMP0114-Common.cmake:[0-9]+ \(ExternalProject_Add\)
NO_DEPENDS-CMP0114-WARN.cmake:[0-9]+ \(include\)
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt b/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt
index 9576ae1edf..2fc7d291b6 100644
--- a/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt
+++ b/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt
@@ -13,6 +13,6 @@
\* HG_REPOSITORY
\* CVS_REPOSITORY and CVS_MODULE
Call Stack \(most recent call first\):
- .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_prepare_download\)
+ .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\)
NoOptions.cmake:[0-9]+ \(ExternalProject_Add\)
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt b/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt
index 648f28b25f..07c6e87984 100644
--- a/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt
+++ b/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt
@@ -13,6 +13,6 @@
\* HG_REPOSITORY
\* CVS_REPOSITORY and CVS_MODULE
Call Stack \(most recent call first\):
- .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_prepare_download\)
+ .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\)
SourceEmpty.cmake:[0-9]+ \(ExternalProject_Add\)
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt b/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt
index e061cf6aee..373f6e3aac 100644
--- a/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt
+++ b/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt
@@ -13,6 +13,6 @@
\* HG_REPOSITORY
\* CVS_REPOSITORY and CVS_MODULE
Call Stack \(most recent call first\):
- .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_prepare_download\)
+ .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\)
SourceMissing.cmake:[0-9]+ \(ExternalProject_Add\)
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake b/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake
index 2850bed839..201d822ba2 100644
--- a/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake
+++ b/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake
@@ -19,7 +19,7 @@ cmake_minimum_required(VERSION 3.3)
# console pool.
macro(CheckNinjaStep _target _step _require)
if("${_build}" MATCHES
-" DESC = Performing ${_step} step (\\([a-zA-Z0-9 ]*\\) )?for '${_target}'
+" DESC = Performing ${_step} step for '${_target}'
pool = console"
)
if(NOT ${_require})
diff --git a/Tests/RunCMake/FetchContent/MultiCommand-stdout.txt b/Tests/RunCMake/FetchContent/MultiCommand-stdout.txt
deleted file mode 100644
index 7f2c0f8585..0000000000
--- a/Tests/RunCMake/FetchContent/MultiCommand-stdout.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-.* *download 1
-.* *download 2
-.* *update 1
-.* *update 2
-.* *patch 1
-.* *patch 2
diff --git a/Tests/RunCMake/FetchContent/MultiCommand.cmake b/Tests/RunCMake/FetchContent/MultiCommand.cmake
deleted file mode 100644
index 92e08e4f11..0000000000
--- a/Tests/RunCMake/FetchContent/MultiCommand.cmake
+++ /dev/null
@@ -1,18 +0,0 @@
-include(FetchContent)
-
-# Verify COMMAND keyword is recognised after various *_COMMAND options
-FetchContent_Declare(multiCommand
- DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E echo "download 1"
- COMMAND "${CMAKE_COMMAND}" -E echo "download 2"
- UPDATE_COMMAND "${CMAKE_COMMAND}" -E echo "update 1"
- COMMAND "${CMAKE_COMMAND}" -E echo "update 2"
- PATCH_COMMAND "${CMAKE_COMMAND}" -E echo "patch 1"
- COMMAND "${CMAKE_COMMAND}" -E echo "patch 2"
-)
-
-# Force all steps to be re-run by removing timestamps, scripts, etc. from any
-# previous run
-file(REMOVE_RECURSE "${FETCHCONTENT_BASE_DIR}/multiCommand-subbuild")
-
-set(FETCHCONTENT_QUIET FALSE)
-FetchContent_MakeAvailable(multiCommand)
diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
index d7fd009275..9baeab75e2 100644
--- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
@@ -2,12 +2,12 @@ include(RunCMake)
unset(RunCMake_TEST_NO_CLEAN)
-run_cmake(MultiCommand)
run_cmake(MissingDetails)
run_cmake(DirectIgnoresDetails)
run_cmake(FirstDetailsWin)
run_cmake(DownloadTwice)
run_cmake(DownloadFile)
+run_cmake(SameGenerator)
run_cmake(VarDefinitions)
run_cmake(GetProperties)
run_cmake(UsesTerminalOverride)
@@ -27,36 +27,6 @@ run_cmake_with_options(ManualSourceDirectoryRelative
-D "FETCHCONTENT_SOURCE_DIR_WITHPROJECT:STRING=WithProject"
)
-function(run_FetchContent_TimeStamps)
- set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TimeStamps)
- file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
- file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
-
- # First run should execute the commands
- run_cmake(TimeStamps)
-
- # Ensure that the file checks we use in the TimeStampsRerun-check.cmake script
- # will not be defeated by file systems with only one second resolution.
- # The IS_NEWER_THAN check returns TRUE if the timestamps of the two files are
- # the same, which has been observed where filesystems only have one second
- # resolution.
- set(cmpTimeStamp ${RunCMake_TEST_BINARY_DIR}/cmpTimeStamp.txt)
- set(checkTimeStamp ${RunCMake_TEST_BINARY_DIR}/cmpTimeStampCheck.txt)
- file(TOUCH ${cmpTimeStamp})
- file(TOUCH ${checkTimeStamp})
- if("${cmpTimeStamp}" IS_NEWER_THAN "${checkTimeStamp}")
- execute_process(
- COMMAND ${CMAKE_COMMAND} -E sleep 1.125
- COMMAND_ERROR_IS_FATAL LAST
- )
- endif()
-
- # Run again with no changes, no commands should re-execute
- set(RunCMake_TEST_NO_CLEAN 1)
- run_cmake(TimeStampsRerun)
-endfunction()
-run_FetchContent_TimeStamps()
-
function(run_FetchContent_DirOverrides)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/DirOverrides-build)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
diff --git a/Tests/RunCMake/FetchContent/SameGenerator.cmake b/Tests/RunCMake/FetchContent/SameGenerator.cmake
new file mode 100644
index 0000000000..58204ef041
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/SameGenerator.cmake
@@ -0,0 +1,17 @@
+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()
diff --git a/Tests/RunCMake/FetchContent/TimeStamps-stdout.txt b/Tests/RunCMake/FetchContent/TimeStamps-stdout.txt
deleted file mode 100644
index 2ba1ff4c3f..0000000000
--- a/Tests/RunCMake/FetchContent/TimeStamps-stdout.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-.* *download executed
-.* *patch executed
diff --git a/Tests/RunCMake/FetchContent/TimeStamps.cmake b/Tests/RunCMake/FetchContent/TimeStamps.cmake
deleted file mode 100644
index 33874f9a84..0000000000
--- a/Tests/RunCMake/FetchContent/TimeStamps.cmake
+++ /dev/null
@@ -1,14 +0,0 @@
-include(FetchContent)
-
-# Do nothing for an update because it would result in always re-running the
-# patch step. We want to test that a patch step that only depends on the
-# download step is not re-run unnecessarily.
-FetchContent_Declare(customCommands
- PREFIX ${CMAKE_CURRENT_BINARY_DIR}
- DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E echo "download executed"
- UPDATE_COMMAND ""
- PATCH_COMMAND "${CMAKE_COMMAND}" -E echo "patch executed"
-)
-
-set(FETCHCONTENT_QUIET FALSE)
-FetchContent_MakeAvailable(customCommands)
diff --git a/Tests/RunCMake/FetchContent/TimeStampsRerun-check.cmake b/Tests/RunCMake/FetchContent/TimeStampsRerun-check.cmake
deleted file mode 100644
index c12a5f4457..0000000000
--- a/Tests/RunCMake/FetchContent/TimeStampsRerun-check.cmake
+++ /dev/null
@@ -1,38 +0,0 @@
-set(cmpFile ${RunCMake_TEST_BINARY_DIR}/cmpTimeStamp.txt)
-set(scriptDir ${RunCMake_TEST_BINARY_DIR}/tmp)
-set(stampDir ${RunCMake_TEST_BINARY_DIR}/src/customcommands-stamp)
-
-set(errorMessages)
-if(NOT EXISTS "${cmpFile}")
- list(APPEND errorMessages " ${cmpFile} is missing")
-else()
- foreach(script IN ITEMS mkdirs download patch)
- set(scriptFile "${scriptDir}/customcommands-${script}.cmake")
- if(NOT EXISTS "${scriptFile}")
- list(APPEND errorMessages " ${scriptFile} is missing")
- elseif(NOT "${cmpFile}" IS_NEWER_THAN "${scriptFile}")
- list(APPEND errorMessages " ${scriptFile} was unexectedly updated")
- endif()
- endforeach()
-
- # special case, not a script, has different extension
- set(repoInfoFile "${scriptDir}/customcommands-download-repoinfo.txt")
- if(NOT EXISTS "${repoInfoFile}")
- list(APPEND errorMessages " ${repoInfoFile} is missing")
- elseif(NOT "${cmpFile}" IS_NEWER_THAN "${repoInfoFile}")
- list(APPEND errorMessages " ${repoInfoFile} was unexectedly updated")
- endif()
-
- foreach(step IN ITEMS download patch)
- set(stampFile "${stampDir}/customcommands-${step}")
- if(NOT EXISTS "${stampFile}")
- list(APPEND errorMessages " ${stampFile} is missing")
- elseif(NOT "${cmpFile}" IS_NEWER_THAN "${stampFile}")
- list(APPEND errorMessages " ${stampFile} was unexectedly updated")
- endif()
- endforeach()
-endif()
-
-if(errorMessages)
- list(JOIN errorMessages "\n" RunCMake_TEST_FAILED)
-endif()
diff --git a/Tests/RunCMake/FetchContent/TimeStampsRerun.cmake b/Tests/RunCMake/FetchContent/TimeStampsRerun.cmake
deleted file mode 100644
index e13667a1a8..0000000000
--- a/Tests/RunCMake/FetchContent/TimeStampsRerun.cmake
+++ /dev/null
@@ -1 +0,0 @@
-include(${CMAKE_CURRENT_LIST_DIR}/TimeStamps.cmake)