mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-14 02:59:53 -06:00
@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.30
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
CMP0168: FetchContent implements steps directly instead of through a sub-build. </policy/CMP0168>
|
||||
CMP0167: The FindBoost module is removed. </policy/CMP0167>
|
||||
CMP0166: TARGET_PROPERTY evaluates link properties transitively over private dependencies of static libraries. </policy/CMP0166>
|
||||
CMP0165: enable_language() must not be called before project(). </policy/CMP0165>
|
||||
|
||||
64
Help/policy/CMP0168.rst
Normal file
64
Help/policy/CMP0168.rst
Normal file
@@ -0,0 +1,64 @@
|
||||
CMP0168
|
||||
-------
|
||||
|
||||
.. versionadded:: 3.30
|
||||
|
||||
The :module:`FetchContent` module implements steps directly instead of through
|
||||
a sub-build.
|
||||
|
||||
CMake 3.29 and below implement FetchContent as a separate sub-build.
|
||||
This required configuring that separate project and using a build tool.
|
||||
This approach can be very slow with some generators and operating systems.
|
||||
CMake 3.30 and above prefer to implement the download, update, and patch
|
||||
steps directly as part of the main project.
|
||||
|
||||
The ``NEW`` behavior has the following characteristics:
|
||||
|
||||
* No sub-build is used. All operations are implemented directly from the
|
||||
main project's CMake configure step. When running in CMake script mode,
|
||||
no build tool needs to be available.
|
||||
* Generator expressions and GNU Make variables of the form ``$(SOMEVAR)`` are
|
||||
not supported. They should not be used in any argument to
|
||||
:command:`FetchContent_Declare` or :command:`FetchContent_Populate`.
|
||||
* All ``LOG_...`` and ``USES_TERMINAL_...`` options, the ``QUIET`` option, and
|
||||
the :variable:`FETCHCONTENT_QUIET` variable are ignored.
|
||||
:module:`FetchContent` output is always part of the main project's configure
|
||||
output. This also means it now respects the message logging level (see
|
||||
:variable:`CMAKE_MESSAGE_LOG_LEVEL` and
|
||||
:option:`--log-level <cmake --log-level>`). The default message log level
|
||||
should be comparable to using ``QUIET`` with the ``OLD`` policy setting,
|
||||
except that warnings will now be shown.
|
||||
* The ``PREFIX``, ``TMP_DIR``, ``STAMP_DIR``, ``LOG_DIR``, and ``DOWNLOAD_DIR``
|
||||
options and their associated directory properties are ignored. The
|
||||
:module:`FetchContent` module controls those locations internally.
|
||||
|
||||
The ``OLD`` behavior has the following characteristics:
|
||||
|
||||
* A sub-build is always used to implement the download, update, and patch
|
||||
steps. A build tool must be available, even when using
|
||||
:command:`FetchContent_Populate` in CMake script mode.
|
||||
* Generator expressions and GNU Make variables of the form ``$(SOMEVAR)`` can
|
||||
be used, although such use is almost always inappropriate. They are evaluated
|
||||
in the sub-build, so they do not see any information from the main build.
|
||||
* All logging, terminal control, and directory options related to the download,
|
||||
update, or patch steps are supported.
|
||||
* If the ``QUIET`` option is used, or the :variable:`FETCHCONTENT_QUIET`
|
||||
variable is set to true, warnings will not be shown in the output.
|
||||
|
||||
There's a reasonably good chance that users can set the
|
||||
:variable:`CMAKE_POLICY_DEFAULT_CMP0168 <CMAKE_POLICY_DEFAULT_CMP<NNNN>>`
|
||||
variable to ``NEW`` to globally switch to the ``NEW`` behavior while waiting
|
||||
for the project and its dependencies to be updated use the ``NEW`` policy
|
||||
setting by default. Projects don't typically make use of the features that the
|
||||
``NEW`` behavior no longer supports, and even those projects that do will often
|
||||
still work fine when those options are ignored. Before setting this behavior
|
||||
globally, check whether any :command:`FetchContent_Declare` or
|
||||
:command:`FetchContent_Populate` calls use the ignored options in a way that
|
||||
would change observable behavior, other than putting temporary or
|
||||
internally-generated files in different locations.
|
||||
|
||||
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.30
|
||||
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
|
||||
.. include:: STANDARD_ADVICE.txt
|
||||
|
||||
.. include:: DEPRECATED.txt
|
||||
9
Help/release/dev/fetchcontent-direct.rst
Normal file
9
Help/release/dev/fetchcontent-direct.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
fetchcontent-direct
|
||||
-------------------
|
||||
|
||||
* :module:`FetchContent` now prefers to populate content directly rather
|
||||
than using a separate sub-build. This may significantly improve configure
|
||||
times on some systems (Windows especially, but also on macOS when using
|
||||
the Xcode generator). Policy :policy:`CMP0168` provides backward
|
||||
compatibility for those projects that still rely on using a sub-build for
|
||||
content population.
|
||||
@@ -21,14 +21,14 @@ function(check_file_hash has_hash hash_is_good)
|
||||
|
||||
set("${has_hash}" TRUE PARENT_SCOPE)
|
||||
|
||||
message(STATUS "verifying file...
|
||||
message(VERBOSE "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
|
||||
message(VERBOSE "@ALGO@ hash of
|
||||
@LOCAL@
|
||||
does not match expected value
|
||||
expected: '@EXPECT_VALUE@'
|
||||
@@ -44,7 +44,7 @@ function(sleep_before_download attempt)
|
||||
endif()
|
||||
|
||||
if(attempt EQUAL 1)
|
||||
message(STATUS "Retrying...")
|
||||
message(VERBOSE "Retrying...")
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -66,7 +66,7 @@ function(sleep_before_download attempt)
|
||||
set(sleep_seconds 1200)
|
||||
endif()
|
||||
|
||||
message(STATUS "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ...")
|
||||
message(VERBOSE "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ...")
|
||||
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep "${sleep_seconds}")
|
||||
endfunction()
|
||||
@@ -75,17 +75,17 @@ 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):
|
||||
message(VERBOSE "File already exists and hash match (skip download):
|
||||
file='@LOCAL@'
|
||||
@ALGO@='@EXPECT_VALUE@'"
|
||||
)
|
||||
return()
|
||||
else()
|
||||
message(STATUS "File already exists but hash mismatch. Removing...")
|
||||
message(VERBOSE "File already exists but hash mismatch. Removing...")
|
||||
file(REMOVE "@LOCAL@")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "File already exists but no hash specified (use URL_HASH):
|
||||
message(VERBOSE "File already exists but no hash specified (use URL_HASH):
|
||||
file='@LOCAL@'
|
||||
Old file will be removed and new file downloaded from URL."
|
||||
)
|
||||
@@ -95,7 +95,7 @@ endif()
|
||||
|
||||
set(retry_number 5)
|
||||
|
||||
message(STATUS "Downloading...
|
||||
message(VERBOSE "Downloading...
|
||||
dst='@LOCAL@'
|
||||
timeout='@TIMEOUT_MSG@'
|
||||
inactivity timeout='@INACTIVITY_TIMEOUT_MSG@'"
|
||||
@@ -109,7 +109,7 @@ foreach(i RANGE ${retry_number})
|
||||
endif()
|
||||
foreach(url IN ITEMS @REMOTE@)
|
||||
if(NOT url IN_LIST skip_url_list)
|
||||
message(STATUS "Using src='${url}'")
|
||||
message(VERBOSE "Using src='${url}'")
|
||||
|
||||
@TLS_VERSION_CODE@
|
||||
@TLS_VERIFY_CODE@
|
||||
@@ -135,10 +135,10 @@ foreach(i RANGE ${retry_number})
|
||||
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...")
|
||||
message(VERBOSE "Hash mismatch, removing...")
|
||||
file(REMOVE "@LOCAL@")
|
||||
else()
|
||||
message(STATUS "Downloading... done")
|
||||
message(VERBOSE "Downloading... done")
|
||||
return()
|
||||
endif()
|
||||
else()
|
||||
|
||||
@@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
get_filename_component(filename "@filename@" ABSOLUTE)
|
||||
get_filename_component(directory "@directory@" ABSOLUTE)
|
||||
|
||||
message(STATUS "extracting...
|
||||
message(VERBOSE "extracting...
|
||||
src='${filename}'
|
||||
dst='${directory}'"
|
||||
)
|
||||
@@ -28,21 +28,21 @@ file(MAKE_DIRECTORY "${ut_dir}")
|
||||
|
||||
# Extract it:
|
||||
#
|
||||
message(STATUS "extracting... [tar @args@]")
|
||||
message(VERBOSE "extracting... [tar @args@]")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar @args@ ${filename} @options@
|
||||
WORKING_DIRECTORY ${ut_dir}
|
||||
RESULT_VARIABLE rv
|
||||
)
|
||||
|
||||
if(NOT rv EQUAL 0)
|
||||
message(STATUS "extracting... [error clean up]")
|
||||
message(VERBOSE "extracting... [error clean up]")
|
||||
file(REMOVE_RECURSE "${ut_dir}")
|
||||
message(FATAL_ERROR "Extract of '${filename}' failed")
|
||||
endif()
|
||||
|
||||
# Analyze what came out of the tar file:
|
||||
#
|
||||
message(STATUS "extracting... [analysis]")
|
||||
message(VERBOSE "extracting... [analysis]")
|
||||
file(GLOB contents "${ut_dir}/*")
|
||||
list(REMOVE_ITEM contents "${ut_dir}/.DS_Store")
|
||||
list(LENGTH contents n)
|
||||
@@ -52,14 +52,14 @@ endif()
|
||||
|
||||
# Move "the one" directory to the final directory:
|
||||
#
|
||||
message(STATUS "extracting... [rename]")
|
||||
message(VERBOSE "extracting... [rename]")
|
||||
file(REMOVE_RECURSE ${directory})
|
||||
get_filename_component(contents ${contents} ABSOLUTE)
|
||||
file(RENAME ${contents} ${directory})
|
||||
|
||||
# Clean up:
|
||||
#
|
||||
message(STATUS "extracting... [clean up]")
|
||||
message(VERBOSE "extracting... [clean up]")
|
||||
file(REMOVE_RECURSE "${ut_dir}")
|
||||
|
||||
message(STATUS "extracting... done")
|
||||
message(VERBOSE "extracting... done")
|
||||
|
||||
@@ -5,16 +5,26 @@ cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
if(EXISTS "@gitclone_stampfile@" AND EXISTS "@gitclone_infofile@" AND
|
||||
"@gitclone_stampfile@" IS_NEWER_THAN "@gitclone_infofile@")
|
||||
message(STATUS
|
||||
message(VERBOSE
|
||||
"Avoiding repeated git clone, stamp file is up to date: "
|
||||
"'@gitclone_stampfile@'"
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Even at VERBOSE level, we don't want to see the commands executed, but
|
||||
# enabling them to be shown for DEBUG may be useful to help diagnose problems.
|
||||
cmake_language(GET_MESSAGE_LOG_LEVEL active_log_level)
|
||||
if(active_log_level MATCHES "DEBUG|TRACE")
|
||||
set(maybe_show_command "COMMAND_ECHO STDOUT")
|
||||
else()
|
||||
set(maybe_show_command "")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf "@source_dir@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
message(FATAL_ERROR "Failed to remove directory: '@source_dir@'")
|
||||
@@ -29,11 +39,12 @@ while(error_code AND number_of_tries LESS 3)
|
||||
clone @git_clone_options@ "@git_repository@" "@src_name@"
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
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.")
|
||||
message(NOTICE "Had to git clone more than once: ${number_of_tries} times.")
|
||||
endif()
|
||||
if(error_code)
|
||||
message(FATAL_ERROR "Failed to clone repository: '@git_repository@'")
|
||||
@@ -44,6 +55,7 @@ execute_process(
|
||||
checkout "@git_tag@" @git_checkout_explicit--@
|
||||
WORKING_DIRECTORY "@work_dir@/@src_name@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
message(FATAL_ERROR "Failed to checkout tag: '@git_tag@'")
|
||||
@@ -56,6 +68,7 @@ if(init_submodules)
|
||||
submodule update @git_submodules_recurse@ --init @git_submodules@
|
||||
WORKING_DIRECTORY "@work_dir@/@src_name@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
endif()
|
||||
if(error_code)
|
||||
@@ -67,6 +80,7 @@ endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "@gitclone_infofile@" "@gitclone_stampfile@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
message(FATAL_ERROR "Failed to copy script-last-run stamp file: '@gitclone_stampfile@'")
|
||||
|
||||
@@ -3,12 +3,22 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# Even at VERBOSE level, we don't want to see the commands executed, but
|
||||
# enabling them to be shown for DEBUG may be useful to help diagnose problems.
|
||||
cmake_language(GET_MESSAGE_LOG_LEVEL active_log_level)
|
||||
if(active_log_level MATCHES "DEBUG|TRACE")
|
||||
set(maybe_show_command "COMMAND_ECHO STDOUT")
|
||||
else()
|
||||
set(maybe_show_command "")
|
||||
endif()
|
||||
|
||||
function(do_fetch)
|
||||
message(VERBOSE "Fetching latest from the remote @git_remote_name@")
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git fetch --tags --force "@git_remote_name@"
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
COMMAND_ERROR_IS_FATAL LAST
|
||||
${maybe_show_command}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
@@ -34,6 +44,9 @@ if(head_sha STREQUAL "")
|
||||
message(FATAL_ERROR "Failed to get the hash for HEAD:\n${error_msg}")
|
||||
endif()
|
||||
|
||||
if("${can_fetch}" STREQUAL "")
|
||||
set(can_fetch "@can_fetch_default@")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git show-ref "@git_tag@"
|
||||
@@ -97,7 +110,7 @@ else()
|
||||
# because it can be confusing for users to see a failed git command.
|
||||
# That failure is being handled here, so it isn't an error.
|
||||
if(NOT error_msg STREQUAL "")
|
||||
message(VERBOSE "${error_msg}")
|
||||
message(DEBUG "${error_msg}")
|
||||
endif()
|
||||
do_fetch()
|
||||
set(checkout_name "@git_tag@")
|
||||
@@ -181,6 +194,7 @@ if(need_stash)
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git stash save @git_stash_save_options@
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
${maybe_show_command}
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -189,6 +203,7 @@ if(git_update_strategy STREQUAL "CHECKOUT")
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git checkout "${checkout_name}"
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
${maybe_show_command}
|
||||
)
|
||||
else()
|
||||
execute_process(
|
||||
@@ -203,6 +218,7 @@ else()
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git rebase --abort
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
${maybe_show_command}
|
||||
)
|
||||
|
||||
if(NOT git_update_strategy STREQUAL "REBASE_CHECKOUT")
|
||||
@@ -211,6 +227,7 @@ else()
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
${maybe_show_command}
|
||||
)
|
||||
endif()
|
||||
message(FATAL_ERROR "\nFailed to rebase in: '@work_dir@'."
|
||||
@@ -236,12 +253,14 @@ else()
|
||||
${tag_name}
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
${maybe_show_command}
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git checkout "${checkout_name}"
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
${maybe_show_command}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
@@ -252,27 +271,32 @@ if(need_stash)
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
# Stash pop --index failed: Try again dropping the index
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git reset --hard --quiet
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
${maybe_show_command}
|
||||
)
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --quiet
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
# Stash pop failed: Restore previous state.
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git reset --hard --quiet ${head_sha}
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
${maybe_show_command}
|
||||
)
|
||||
execute_process(
|
||||
COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
${maybe_show_command}
|
||||
)
|
||||
message(FATAL_ERROR "\nFailed to unstash changes in: '@work_dir@'."
|
||||
"\nYou will have to resolve the conflicts manually")
|
||||
@@ -288,5 +312,6 @@ if(init_submodules)
|
||||
submodule update @git_submodules_recurse@ --init @git_submodules@
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
${maybe_show_command}
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -5,16 +5,26 @@ cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
if(EXISTS "@hgclone_stampfile@" AND EXISTS "@hgclone_infofile@" AND
|
||||
"@hgclone_stampfile@" IS_NEWER_THAN "@hgclone_infofile@")
|
||||
message(STATUS
|
||||
message(VERBOSE
|
||||
"Avoiding repeated hg clone, stamp file is up to date: "
|
||||
"'@hgclone_stampfile@'"
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Even at VERBOSE level, we don't want to see the commands executed, but
|
||||
# enabling them to be shown for DEBUG may be useful to help diagnose problems.
|
||||
cmake_language(GET_MESSAGE_LOG_LEVEL active_log_level)
|
||||
if(active_log_level MATCHES "DEBUG|TRACE")
|
||||
set(maybe_show_command "COMMAND_ECHO STDOUT")
|
||||
else()
|
||||
set(maybe_show_command "")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf "@source_dir@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
message(FATAL_ERROR "Failed to remove directory: '@source_dir@'")
|
||||
@@ -24,6 +34,7 @@ execute_process(
|
||||
COMMAND "@hg_EXECUTABLE@" clone -U "@hg_repository@" "@src_name@"
|
||||
WORKING_DIRECTORY "@work_dir@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
message(FATAL_ERROR "Failed to clone repository: '@hg_repository@'")
|
||||
@@ -33,6 +44,7 @@ execute_process(
|
||||
COMMAND "@hg_EXECUTABLE@" update @hg_tag@
|
||||
WORKING_DIRECTORY "@work_dir@/@src_name@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
message(FATAL_ERROR "Failed to checkout tag: '@hg_tag@'")
|
||||
@@ -43,6 +55,7 @@ endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "@hgclone_infofile@" "@hgclone_stampfile@"
|
||||
RESULT_VARIABLE error_code
|
||||
${maybe_show_command}
|
||||
)
|
||||
if(error_code)
|
||||
message(FATAL_ERROR "Failed to copy script-last-run stamp file: '@hgclone_stampfile@'")
|
||||
|
||||
@@ -764,7 +764,62 @@ function(_ep_get_git_submodules_recurse git_submodules_recurse)
|
||||
endfunction()
|
||||
|
||||
|
||||
function(_ep_add_script_commands script_var work_dir cmd)
|
||||
# We only support a subset of what ep_replace_location_tags() handles
|
||||
set(location_tags
|
||||
SOURCE_DIR
|
||||
SOURCE_SUBDIR
|
||||
BINARY_DIR
|
||||
TMP_DIR
|
||||
DOWNLOAD_DIR
|
||||
DOWNLOADED_FILE
|
||||
)
|
||||
|
||||
# There can be multiple COMMANDs, but we have to split those up to
|
||||
# one command per call to execute_process()
|
||||
set(execute_process_cmd
|
||||
"execute_process(\n"
|
||||
" WORKING_DIRECTORY \"${work_dir}\"\n"
|
||||
" COMMAND_ERROR_IS_FATAL LAST\n"
|
||||
)
|
||||
cmake_language(GET_MESSAGE_LOG_LEVEL active_log_level)
|
||||
if(active_log_level MATCHES "VERBOSE|DEBUG|TRACE")
|
||||
string(APPEND execute_process_cmd " COMMAND_ECHO STDOUT\n")
|
||||
endif()
|
||||
string(APPEND execute_process_cmd " COMMAND ")
|
||||
|
||||
string(APPEND ${script_var} "${execute_process_cmd}")
|
||||
|
||||
foreach(cmd_arg IN LISTS cmd)
|
||||
if(cmd_arg STREQUAL "COMMAND")
|
||||
string(APPEND ${script_var} "\n)\n${execute_process_cmd}")
|
||||
else()
|
||||
if(_EP_LIST_SEPARATOR)
|
||||
string(REPLACE "${_EP_LIST_SEPARATOR}" "\\;" cmd_arg "${cmd_arg}")
|
||||
endif()
|
||||
foreach(dir IN LISTS location_tags)
|
||||
string(REPLACE "<${dir}>" "${_EP_${dir}}" cmd_arg "${cmd_arg}")
|
||||
endforeach()
|
||||
string(APPEND ${script_var} " [====[${cmd_arg}]====]")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
string(APPEND ${script_var} "\n)")
|
||||
set(${script_var} "${${script_var}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
function(_ep_add_download_command name)
|
||||
set(noValueOptions )
|
||||
set(singleValueOptions
|
||||
SCRIPT_FILE # These should only be used by FetchContent
|
||||
DEPENDS_VARIABLE #
|
||||
)
|
||||
set(multiValueOptions )
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg
|
||||
"${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
|
||||
)
|
||||
|
||||
# The various _EP_... variables mentioned here and throughout this function
|
||||
# are expected to already have been set by the caller via a call to
|
||||
# _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables
|
||||
@@ -787,6 +842,7 @@ function(_ep_add_download_command name)
|
||||
# TODO: Perhaps file:// should be copied to download dir before extraction.
|
||||
string(REGEX REPLACE "file://" "" url "${url}")
|
||||
|
||||
set(step_script_contents)
|
||||
set(depends)
|
||||
set(comment)
|
||||
set(work_dir)
|
||||
@@ -795,6 +851,14 @@ function(_ep_add_download_command name)
|
||||
if(DEFINED _EP_DOWNLOAD_COMMAND)
|
||||
set(work_dir ${download_dir})
|
||||
set(method custom)
|
||||
if(NOT "x${cmd}" STREQUAL "x" AND arg_SCRIPT_FILE)
|
||||
_ep_add_script_commands(
|
||||
step_script_contents
|
||||
"${work_dir}"
|
||||
"${cmd}" # Must be a single quoted argument
|
||||
)
|
||||
endif()
|
||||
|
||||
elseif(cvs_repository)
|
||||
set(method cvs)
|
||||
find_package(CVS QUIET)
|
||||
@@ -819,6 +883,13 @@ function(_ep_add_download_command name)
|
||||
-d ${src_name}
|
||||
${cvs_module}
|
||||
)
|
||||
if(arg_SCRIPT_FILE)
|
||||
_ep_add_script_commands(
|
||||
step_script_contents
|
||||
"${work_dir}"
|
||||
"${cmd}" # Must be a single quoted argument
|
||||
)
|
||||
endif()
|
||||
|
||||
elseif(svn_repository)
|
||||
set(method svn)
|
||||
@@ -862,6 +933,13 @@ function(_ep_add_download_command name)
|
||||
${svn_user_pw_args}
|
||||
${src_name}
|
||||
)
|
||||
if(arg_SCRIPT_FILE)
|
||||
_ep_add_script_commands(
|
||||
step_script_contents
|
||||
"${work_dir}"
|
||||
"${cmd}" # Must be a single quoted argument
|
||||
)
|
||||
endif()
|
||||
|
||||
elseif(git_repository)
|
||||
set(method git)
|
||||
@@ -928,8 +1006,9 @@ CMP0097=${_EP_CMP0097}
|
||||
# create a cmake script to invoke as download command.
|
||||
# The script will delete the source directory and then call git clone.
|
||||
#
|
||||
set(clone_script ${tmp_dir}/${name}-gitclone.cmake)
|
||||
_ep_write_gitclone_script(
|
||||
${tmp_dir}/${name}-gitclone.cmake
|
||||
${clone_script}
|
||||
${source_dir}
|
||||
${GIT_EXECUTABLE}
|
||||
${git_repository}
|
||||
@@ -949,7 +1028,15 @@ CMP0097=${_EP_CMP0097}
|
||||
"${tls_verify}"
|
||||
)
|
||||
set(comment "Performing download step (git clone) for '${name}'")
|
||||
set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitclone.cmake)
|
||||
set(cmd ${CMAKE_COMMAND}
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
|
||||
-P ${clone_script}
|
||||
)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
set(step_script_contents "include(\"${clone_script}\")")
|
||||
list(APPEND depends ${clone_script})
|
||||
endif()
|
||||
|
||||
elseif(hg_repository)
|
||||
set(method hg)
|
||||
@@ -978,8 +1065,9 @@ CMP0097=${_EP_CMP0097}
|
||||
# create a cmake script to invoke as download command.
|
||||
# The script will delete the source directory and then call hg clone.
|
||||
#
|
||||
set(clone_script ${tmp_dir}/${name}-hgclone.cmake)
|
||||
_ep_write_hgclone_script(
|
||||
${tmp_dir}/${name}-hgclone.cmake
|
||||
${clone_script}
|
||||
${source_dir}
|
||||
${HG_EXECUTABLE}
|
||||
${hg_repository}
|
||||
@@ -990,7 +1078,15 @@ CMP0097=${_EP_CMP0097}
|
||||
${stamp_dir}/${name}-hgclone-lastrun.txt
|
||||
)
|
||||
set(comment "Performing download step (hg clone) for '${name}'")
|
||||
set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-hgclone.cmake)
|
||||
set(cmd ${CMAKE_COMMAND}
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
|
||||
-P ${clone_script}
|
||||
)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
set(step_script_contents "include(\"${clone_script}\")")
|
||||
list(APPEND depends ${clone_script})
|
||||
endif()
|
||||
|
||||
elseif(url)
|
||||
set(method url)
|
||||
@@ -1045,9 +1141,21 @@ hash=${hash}
|
||||
${CMAKE_COMMAND} -E rm -rf ${source_dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir}
|
||||
)
|
||||
if(arg_SCRIPT_FILE)
|
||||
# While it may be tempting to implement the two operations directly
|
||||
# with file(), the behavior is different. file(COPY) preserves input
|
||||
# file timestamps, which we don't want. Therefore, still use the same
|
||||
# external commands so that we get the same behavior.
|
||||
_ep_add_script_commands(
|
||||
step_script_contents
|
||||
"${work_dir}"
|
||||
"${cmd}" # Must be a single quoted argument
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
set(no_extract "${_EP_DOWNLOAD_NO_EXTRACT}")
|
||||
string(APPEND extra_repo_info "no_extract=${no_extract}\n")
|
||||
set(verify_script "${stamp_dir}/verify-${name}.cmake")
|
||||
if("${url}" MATCHES "^[a-z]+://")
|
||||
# TODO: Should download and extraction be different steps?
|
||||
if("x${fname}" STREQUAL "x")
|
||||
@@ -1097,9 +1205,15 @@ hash=${hash}
|
||||
"${netrc_file}"
|
||||
)
|
||||
set(cmd
|
||||
${CMAKE_COMMAND} -P "${download_script}"
|
||||
${CMAKE_COMMAND}
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
|
||||
-P "${download_script}"
|
||||
COMMAND
|
||||
)
|
||||
if(arg_SCRIPT_FILE)
|
||||
set(step_script_contents "include(\"${download_script}\")\n")
|
||||
endif()
|
||||
|
||||
if (no_extract)
|
||||
set(steps "download and verify")
|
||||
else ()
|
||||
@@ -1107,7 +1221,7 @@ hash=${hash}
|
||||
endif ()
|
||||
set(comment "Performing download step (${steps}) for '${name}'")
|
||||
# already verified by 'download_script'
|
||||
file(WRITE "${stamp_dir}/verify-${name}.cmake" "")
|
||||
file(WRITE "${verify_script}" "")
|
||||
|
||||
# Rather than adding everything to the RepositoryInfo.txt file, it is
|
||||
# more robust to just depend on the download script. That way, we will
|
||||
@@ -1122,12 +1236,19 @@ hash=${hash}
|
||||
endif ()
|
||||
set(comment "Performing download step (${steps}) for '${name}'")
|
||||
_ep_write_verifyfile_script(
|
||||
"${stamp_dir}/verify-${name}.cmake"
|
||||
"${verify_script}"
|
||||
"${file}"
|
||||
"${hash}"
|
||||
)
|
||||
endif()
|
||||
list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake)
|
||||
list(APPEND cmd ${CMAKE_COMMAND}
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
|
||||
-P ${verify_script}
|
||||
)
|
||||
if(arg_SCRIPT_FILE)
|
||||
string(APPEND step_script_contents "include(\"${verify_script}\")\n")
|
||||
list(APPEND depends ${verify_script})
|
||||
endif()
|
||||
set(extract_timestamp "${_EP_DOWNLOAD_EXTRACT_TIMESTAMP}")
|
||||
if(no_extract)
|
||||
if(DEFINED _EP_DOWNLOAD_EXTRACT_TIMESTAMP)
|
||||
@@ -1136,7 +1257,24 @@ hash=${hash}
|
||||
"DOWNLOAD_NO_EXTRACT TRUE"
|
||||
)
|
||||
endif()
|
||||
set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
|
||||
if(arg_SCRIPT_FILE)
|
||||
# There's no target to record the location of the downloaded file.
|
||||
# Instead, we copy it to the source directory within the script,
|
||||
# which is what FetchContent always does in this situation.
|
||||
cmake_path(SET safe_file NORMALIZE "${file}")
|
||||
cmake_path(GET safe_file FILENAME filename)
|
||||
string(APPEND step_script_contents
|
||||
"file(COPY_FILE\n"
|
||||
" \"${file}\"\n"
|
||||
" \"${source_dir}/${filename}\"\n"
|
||||
" ONLY_IF_DIFFERENT\n"
|
||||
" INPUT_MAY_BE_RECENT\n"
|
||||
")"
|
||||
)
|
||||
list(APPEND depends ${source_dir}/${filename})
|
||||
else()
|
||||
set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
|
||||
endif()
|
||||
else()
|
||||
if(NOT DEFINED _EP_DOWNLOAD_EXTRACT_TIMESTAMP)
|
||||
# Default depends on policy CMP0135
|
||||
@@ -1165,16 +1303,23 @@ hash=${hash}
|
||||
else()
|
||||
set(options "--touch")
|
||||
endif()
|
||||
set(extract_script "${stamp_dir}/extract-${name}.cmake")
|
||||
_ep_write_extractfile_script(
|
||||
"${stamp_dir}/extract-${name}.cmake"
|
||||
"${extract_script}"
|
||||
"${name}"
|
||||
"${file}"
|
||||
"${source_dir}"
|
||||
"${options}"
|
||||
)
|
||||
list(APPEND cmd
|
||||
COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
|
||||
-P ${extract_script}
|
||||
)
|
||||
if(arg_SCRIPT_FILE)
|
||||
string(APPEND step_script_contents "include(\"${extract_script}\")\n")
|
||||
list(APPEND depends ${extract_script})
|
||||
endif()
|
||||
endif ()
|
||||
endif()
|
||||
else()
|
||||
@@ -1194,6 +1339,9 @@ hash=${hash}
|
||||
" * CVS_REPOSITORY and CVS_MODULE"
|
||||
)
|
||||
endif()
|
||||
if(arg_SCRIPT_FILE)
|
||||
set(step_script_contents "message(VERBOSE [[Using SOURCE_DIR as is]])")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We use configure_file() to write the repo_info_file so that the file's
|
||||
@@ -1207,6 +1355,20 @@ hash=${hash}
|
||||
@ONLY
|
||||
)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
set(step_name download)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
|
||||
"${arg_SCRIPT_FILE}"
|
||||
@ONLY
|
||||
)
|
||||
set(${arg_DEPENDS_VARIABLE} "${depends}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Nothing below this point is applicable when we've been asked to put the
|
||||
# download step in a script file (which is the FetchContent case).
|
||||
|
||||
if(_EP_LOG_DOWNLOAD)
|
||||
set(log LOG 1)
|
||||
else()
|
||||
@@ -1253,6 +1415,16 @@ function(_ep_get_update_disconnected var name)
|
||||
endfunction()
|
||||
|
||||
function(_ep_add_update_command name)
|
||||
set(noValueOptions )
|
||||
set(singleValueOptions
|
||||
SCRIPT_FILE # These should only be used by FetchContent
|
||||
DEPEND_VARIABLE #
|
||||
)
|
||||
set(multiValueOptions )
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg
|
||||
"${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
|
||||
)
|
||||
|
||||
# The various _EP_... variables mentioned here and throughout this function
|
||||
# are expected to already have been set by the caller via a call to
|
||||
# _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables
|
||||
@@ -1280,7 +1452,13 @@ function(_ep_add_update_command name)
|
||||
set(work_dir ${source_dir})
|
||||
if(NOT "x${cmd}" STREQUAL "x")
|
||||
set(always 1)
|
||||
_ep_add_script_commands(
|
||||
step_script_contents
|
||||
"${work_dir}"
|
||||
"${cmd}" # Must be a single quoted argument
|
||||
)
|
||||
endif()
|
||||
|
||||
elseif(cvs_repository)
|
||||
if(NOT CVS_EXECUTABLE)
|
||||
message(FATAL_ERROR "error: could not find cvs for update of ${name}")
|
||||
@@ -1290,6 +1468,15 @@ function(_ep_add_update_command name)
|
||||
set(cvs_tag "${_EP_CVS_TAG}")
|
||||
set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q up -dP ${cvs_tag})
|
||||
set(always 1)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
_ep_add_script_commands(
|
||||
step_script_contents
|
||||
"${work_dir}"
|
||||
"${cmd}" # Must be a single quoted argument
|
||||
)
|
||||
endif()
|
||||
|
||||
elseif(svn_repository)
|
||||
if(NOT Subversion_SVN_EXECUTABLE)
|
||||
message(FATAL_ERROR "error: could not find svn for update of ${name}")
|
||||
@@ -1326,6 +1513,15 @@ function(_ep_add_update_command name)
|
||||
${svn_user_pw_args}
|
||||
)
|
||||
set(always 1)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
_ep_add_script_commands(
|
||||
step_script_contents
|
||||
"${work_dir}"
|
||||
"${cmd}" # Must be a single quoted argument
|
||||
)
|
||||
endif()
|
||||
|
||||
elseif(git_repository)
|
||||
# FetchContent gives us these directly, so don't try to recompute them
|
||||
if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
|
||||
@@ -1393,9 +1589,27 @@ function(_ep_add_update_command name)
|
||||
"${tls_version}"
|
||||
"${tls_verify}"
|
||||
)
|
||||
set(cmd ${CMAKE_COMMAND} -Dcan_fetch=YES -P ${update_script})
|
||||
set(cmd_disconnected ${CMAKE_COMMAND} -Dcan_fetch=NO -P ${update_script})
|
||||
set(cmd ${CMAKE_COMMAND}
|
||||
-Dcan_fetch=YES
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
|
||||
-P ${update_script}
|
||||
)
|
||||
set(cmd_disconnected ${CMAKE_COMMAND}
|
||||
-Dcan_fetch=NO
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
|
||||
-P ${update_script}
|
||||
)
|
||||
set(always 1)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
if(update_disconnected)
|
||||
set(can_fetch_default NO)
|
||||
else()
|
||||
set(can_fetch_default YES)
|
||||
endif()
|
||||
set(step_script_contents "include(\"${update_script}\")")
|
||||
endif()
|
||||
|
||||
elseif(hg_repository)
|
||||
if(NOT HG_EXECUTABLE)
|
||||
message(FATAL_ERROR "error: could not find hg for pull of ${name}")
|
||||
@@ -1427,6 +1641,28 @@ Update to Mercurial >= 2.1.1.
|
||||
)
|
||||
set(cmd_disconnected ${HG_EXECUTABLE} update ${hg_tag})
|
||||
set(always 1)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
# These commands are simple, and we know whether updates need to be
|
||||
# disconnected or not for this case, so write them directly instead of
|
||||
# forming them from "cmd" and "cmd_disconnected".
|
||||
if(NOT update_disconnected)
|
||||
string(APPEND step_script_contents
|
||||
"execute_process(\n"
|
||||
" WORKING_DIRECTORY \"${work_dir}\"\n"
|
||||
" COMMAND_ERROR_IS_FATAL LAST\n"
|
||||
" COMMAND \"${HG_EXECUTABLE}\" pull\n"
|
||||
")"
|
||||
)
|
||||
endif()
|
||||
string(APPEND step_script_contents
|
||||
"execute_process(\n"
|
||||
" WORKING_DIRECTORY \"${work_dir}\"\n"
|
||||
" COMMAND_ERROR_IS_FATAL LAST\n"
|
||||
" COMMAND \"${HG_EXECUTABLE}\" update \"${hg_tag}\"\n"
|
||||
")"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We use configure_file() to write the update_info_file so that the file's
|
||||
@@ -1442,6 +1678,20 @@ Update to Mercurial >= 2.1.1.
|
||||
@ONLY
|
||||
)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
set(step_name update)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
|
||||
"${arg_SCRIPT_FILE}"
|
||||
@ONLY
|
||||
)
|
||||
set(${arg_DEPENDS_VARIABLE} "${file_deps}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Nothing below this point is applicable when we've been asked to put the
|
||||
# update step in a script file (which is the FetchContent case).
|
||||
|
||||
if(_EP_LOG_UPDATE)
|
||||
set(log LOG 1)
|
||||
else()
|
||||
@@ -1499,6 +1749,15 @@ endfunction()
|
||||
|
||||
|
||||
function(_ep_add_patch_command name)
|
||||
set(noValueOptions )
|
||||
set(singleValueOptions
|
||||
SCRIPT_FILE # These should only be used by FetchContent
|
||||
)
|
||||
set(multiValueOptions )
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg
|
||||
"${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
|
||||
)
|
||||
|
||||
# The various _EP_... variables mentioned here and throughout this function
|
||||
# are expected to already have been set by the caller via a call to
|
||||
# _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables
|
||||
@@ -1509,10 +1768,18 @@ function(_ep_add_patch_command name)
|
||||
set(stamp_dir "${_EP_STAMP_DIR}")
|
||||
|
||||
set(cmd "${_EP_PATCH_COMMAND}")
|
||||
set(step_script_contents "")
|
||||
|
||||
set(work_dir)
|
||||
if(DEFINED _EP_PATCH_COMMAND)
|
||||
set(work_dir ${source_dir})
|
||||
if(arg_SCRIPT_FILE)
|
||||
_ep_add_script_commands(
|
||||
step_script_contents
|
||||
"${work_dir}"
|
||||
"${cmd}" # Must be a single quoted argument
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We use configure_file() to write the patch_info_file so that the file's
|
||||
@@ -1524,6 +1791,19 @@ function(_ep_add_patch_command name)
|
||||
@ONLY
|
||||
)
|
||||
|
||||
if(arg_SCRIPT_FILE)
|
||||
set(step_name patch)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
|
||||
"${arg_SCRIPT_FILE}"
|
||||
@ONLY
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Nothing below this point is applicable when we've been asked to put the
|
||||
# patch step in a script file (which is the FetchContent case).
|
||||
|
||||
if(_EP_LOG_PATCH)
|
||||
set(log LOG 1)
|
||||
else()
|
||||
|
||||
9
Modules/ExternalProject/stepscript.cmake.in
Normal file
9
Modules/ExternalProject/stepscript.cmake.in
Normal file
@@ -0,0 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.29)
|
||||
|
||||
message(VERBOSE "Executing @step_name@ step for @name@")
|
||||
|
||||
block(SCOPE_FOR VARIABLES)
|
||||
|
||||
@step_script_contents@
|
||||
|
||||
endblock()
|
||||
@@ -12,7 +12,7 @@ if(NOT EXISTS "@LOCAL@")
|
||||
endif()
|
||||
|
||||
if("@ALGO@" STREQUAL "")
|
||||
message(WARNING "File will not be verified since no URL_HASH specified")
|
||||
message(WARNING "File cannot be verified since no URL_HASH specified")
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -20,7 +20,7 @@ if("@EXPECT_VALUE@" STREQUAL "")
|
||||
message(FATAL_ERROR "EXPECT_VALUE can't be empty")
|
||||
endif()
|
||||
|
||||
message(STATUS "verifying file...
|
||||
message(VERBOSE "verifying file...
|
||||
file='@LOCAL@'")
|
||||
|
||||
file("@ALGO@" "@LOCAL@" actual_value)
|
||||
@@ -34,4 +34,4 @@ does not match expected value
|
||||
")
|
||||
endif()
|
||||
|
||||
message(STATUS "verifying file... done")
|
||||
message(VERBOSE "verifying file... done")
|
||||
|
||||
@@ -141,6 +141,11 @@ Commands
|
||||
exception, see :command:`FetchContent_MakeAvailable` for details on how that
|
||||
affects behavior.
|
||||
|
||||
.. versionchanged:: 3.30
|
||||
When policy :policy:`CMP0168` is set to ``NEW``, some output-related and
|
||||
directory-related options are ignored. See the policy documentation for
|
||||
details.
|
||||
|
||||
In most cases, ``<contentOptions>`` will just be a couple of options defining
|
||||
the download method and method-specific details like a commit tag or archive
|
||||
hash. For example:
|
||||
@@ -437,12 +442,13 @@ Commands
|
||||
like variable or directory scope. Therefore, it doesn't matter where in the
|
||||
project the details were previously declared, as long as they have been
|
||||
declared before the call to ``FetchContent_Populate()``. Those saved details
|
||||
are then used to construct a call to :command:`ExternalProject_Add` in a
|
||||
private sub-build to perform the content population immediately. The
|
||||
implementation of ``ExternalProject_Add()`` ensures that if the content has
|
||||
already been populated in a previous CMake run, that content will be reused
|
||||
rather than repopulating them again. For the common case where population
|
||||
involves downloading content, the cost of the download is only paid once.
|
||||
are then used to populate the content using a method based on
|
||||
:command:`ExternalProject_Add` (see policy :policy:`CMP0168` for important
|
||||
behavioral aspects of how that is done). The implementation ensures that if
|
||||
the content has already been populated in a previous CMake run, that content
|
||||
will be reused rather than repopulating them again. For the common case
|
||||
where population involves downloading content, the cost of the download is
|
||||
only paid once.
|
||||
|
||||
An internal global property records when a particular content population
|
||||
request has been processed. If ``FetchContent_Populate()`` is called more
|
||||
@@ -529,6 +535,13 @@ Commands
|
||||
cache variable has no effect on ``FetchContent_Populate()`` calls where the
|
||||
content details are provided directly.
|
||||
|
||||
.. versionchanged:: 3.30
|
||||
The ``QUIET`` option and global ``FETCHCONTENT_QUIET`` variable have no
|
||||
effect when policy :policy:`CMP0168` is set to ``NEW``. The output is
|
||||
still quiet by default in that case, but verbosity is controlled by the
|
||||
message logging level (see :variable:`CMAKE_MESSAGE_LOG_LEVEL` and
|
||||
:option:`--log-level <cmake --log-level>`).
|
||||
|
||||
``SUBBUILD_DIR``
|
||||
The ``SUBBUILD_DIR`` argument can be provided to change the location of the
|
||||
sub-build created to perform the population. The default value is
|
||||
@@ -538,6 +551,10 @@ Commands
|
||||
This option should not be confused with the ``SOURCE_SUBDIR`` option which
|
||||
only affects the :command:`FetchContent_MakeAvailable` command.
|
||||
|
||||
.. versionchanged:: 3.30
|
||||
``SUBBUILD_DIR`` is ignored when policy :policy:`CMP0168` is set to
|
||||
``NEW``, since there is no sub-build in that case.
|
||||
|
||||
``SOURCE_DIR``, ``BINARY_DIR``
|
||||
The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by
|
||||
:command:`ExternalProject_Add`, but different default values are used by
|
||||
@@ -548,7 +565,7 @@ Commands
|
||||
:variable:`CMAKE_CURRENT_BINARY_DIR`.
|
||||
|
||||
In addition to the above explicit options, any other unrecognized options are
|
||||
passed through unmodified to :command:`ExternalProject_Add` to perform the
|
||||
passed through unmodified to :command:`ExternalProject_Add` to set up the
|
||||
download, patch and update steps. The following options are explicitly
|
||||
prohibited (they are disabled by the ``FetchContent_Populate()`` command):
|
||||
|
||||
@@ -564,6 +581,11 @@ Commands
|
||||
:variable:`CMAKE_MAKE_PROGRAM` variables will need to be set appropriately
|
||||
on the command line invoking the script.
|
||||
|
||||
.. versionchanged:: 3.30
|
||||
If policy :policy:`CMP0168` is set to ``NEW``, no sub-build is used.
|
||||
Within CMake's script mode, that allows ``FetchContent_Populate()`` to be
|
||||
called without any build tool or CMake generator.
|
||||
|
||||
.. versionadded:: 3.18
|
||||
Added support for the ``DOWNLOAD_NO_EXTRACT`` option.
|
||||
|
||||
@@ -675,6 +697,13 @@ A number of cache variables can influence the behavior where details from a
|
||||
problems with hung downloads, temporarily switching this option off may
|
||||
help diagnose which content population is causing the issue.
|
||||
|
||||
.. versionchanged:: 3.30
|
||||
``FETCHCONTENT_QUIET`` is ignored if policy :policy:`CMP0168` is set to
|
||||
``NEW``. The output is still quiet by default in that case, but verbosity
|
||||
is controlled by the message logging level (see
|
||||
:variable:`CMAKE_MESSAGE_LOG_LEVEL` and
|
||||
:option:`--log-level <cmake --log-level>`).
|
||||
|
||||
.. variable:: FETCHCONTENT_FULLY_DISCONNECTED
|
||||
|
||||
When this option is enabled, no attempt is made to download or update
|
||||
@@ -682,7 +711,7 @@ A number of cache variables can influence the behavior where details from a
|
||||
a previous run or the source directories have been pointed at existing
|
||||
contents the developer has provided manually (using options described
|
||||
further below). When the developer knows that no changes have been made to
|
||||
any content details, turning this option ``ON`` can significantly speed up
|
||||
any content details, turning this option ``ON`` can speed up
|
||||
the configure stage. It is ``OFF`` by default.
|
||||
|
||||
.. note::
|
||||
@@ -1167,7 +1196,13 @@ function(__FetchContent_declareDetails contentName)
|
||||
set(__findPackageArgs)
|
||||
set(__sawQuietKeyword NO)
|
||||
set(__sawGlobalKeyword NO)
|
||||
set(__direct_population NO)
|
||||
foreach(__item IN LISTS ARGN)
|
||||
if(__item STREQUAL "__DIRECT_POPULATION")
|
||||
set(__direct_population YES)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
if(DEFINED __findPackageArgs)
|
||||
# All remaining args are for find_package()
|
||||
string(APPEND __findPackageArgs " [==[${__item}]==]")
|
||||
@@ -1206,6 +1241,10 @@ function(__FetchContent_declareDetails contentName)
|
||||
string(APPEND __cmdArgs " [==[${__item}]==]")
|
||||
endforeach()
|
||||
|
||||
set_property(GLOBAL PROPERTY
|
||||
"_FetchContent_${contentNameLower}_direct_population" ${__direct_population}
|
||||
)
|
||||
|
||||
define_property(GLOBAL PROPERTY ${savedDetailsPropertyName})
|
||||
cmake_language(EVAL CODE
|
||||
"set_property(GLOBAL PROPERTY ${savedDetailsPropertyName} ${__cmdArgs})"
|
||||
@@ -1372,16 +1411,24 @@ function(FetchContent_Declare contentName)
|
||||
endif()
|
||||
|
||||
# Add back in the keyword args we pulled out and potentially tweaked/added
|
||||
set(forward_args "${ARG_UNPARSED_ARGUMENTS}")
|
||||
set(sep EXTERNALPROJECT_INTERNAL_ARGUMENT_SEPARATOR)
|
||||
foreach(key IN LISTS oneValueArgs)
|
||||
if(DEFINED ARG_${key})
|
||||
list(PREPEND ARG_UNPARSED_ARGUMENTS ${key} "${ARG_${key}}" ${sep})
|
||||
list(PREPEND forward_args ${key} "${ARG_${key}}" ${sep})
|
||||
set(sep "")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
cmake_policy(GET CMP0168 cmp0168
|
||||
PARENT_SCOPE # undocumented, do not use outside of CMake
|
||||
)
|
||||
if(cmp0168 STREQUAL "NEW")
|
||||
list(PREPEND forward_args __DIRECT_POPULATION ${sep})
|
||||
endif()
|
||||
|
||||
set(__argsQuoted)
|
||||
foreach(__item IN LISTS ARG_UNPARSED_ARGUMENTS)
|
||||
foreach(__item IN LISTS forward_args)
|
||||
string(APPEND __argsQuoted " [==[${__item}]==]")
|
||||
endforeach()
|
||||
cmake_language(EVAL CODE
|
||||
@@ -1498,7 +1545,7 @@ endfunction()
|
||||
# The value of contentName will always have been lowercased by the caller.
|
||||
# All other arguments are assumed to be options that are understood by
|
||||
# ExternalProject_Add(), except for QUIET and SUBBUILD_DIR.
|
||||
function(__FetchContent_directPopulate contentName)
|
||||
function(__FetchContent_doPopulation contentName)
|
||||
|
||||
set(options
|
||||
QUIET
|
||||
@@ -1533,8 +1580,14 @@ function(__FetchContent_directPopulate contentName)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 ARG
|
||||
"${options}" "${oneValueArgs}" "${multiValueArgs}")
|
||||
|
||||
get_property(direct_population GLOBAL PROPERTY
|
||||
"_FetchContent_${contentNameLower}_direct_population"
|
||||
)
|
||||
|
||||
if(NOT ARG_SUBBUILD_DIR)
|
||||
message(FATAL_ERROR "Internal error: SUBBUILD_DIR not set")
|
||||
if(NOT direct_population)
|
||||
message(FATAL_ERROR "Internal error: SUBBUILD_DIR not set")
|
||||
endif()
|
||||
elseif(NOT IS_ABSOLUTE "${ARG_SUBBUILD_DIR}")
|
||||
set(ARG_SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBBUILD_DIR}")
|
||||
endif()
|
||||
@@ -1558,6 +1611,148 @@ function(__FetchContent_directPopulate contentName)
|
||||
set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE)
|
||||
set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE)
|
||||
|
||||
if(direct_population)
|
||||
__FetchContent_populateDirect()
|
||||
else()
|
||||
__FetchContent_populateSubbuild()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
function(__FetchContent_populateDirect)
|
||||
# Policies CMP0097, CMP0135 and CMP0150 are handled in FetchContent_Declare()
|
||||
# and the stored arguments already account for them.
|
||||
# For CMP0097, the arguments will always assume NEW behavior by the time
|
||||
# we get to here, so ensure ExternalProject sees that.
|
||||
set(_EP_CMP0097 NEW)
|
||||
|
||||
set(args_to_parse
|
||||
"${ARG_UNPARSED_ARGUMENTS}"
|
||||
SOURCE_DIR "${ARG_SOURCE_DIR}"
|
||||
BINARY_DIR "${ARG_BINARY_DIR}"
|
||||
)
|
||||
if(ARG_DOWNLOAD_NO_EXTRACT)
|
||||
list(APPEND args_to_parse DOWNLOAD_NO_EXTRACT YES)
|
||||
endif()
|
||||
|
||||
get_property(cmake_role GLOBAL PROPERTY CMAKE_ROLE)
|
||||
if(cmake_role STREQUAL "PROJECT")
|
||||
# We don't support direct population where a project makes a direct call
|
||||
# to FetchContent_Populate(). That always goes through ExternalProject and
|
||||
# will soon be deprecated anyway.
|
||||
set(function_for_args FetchContent_Declare)
|
||||
elseif(cmake_role STREQUAL "SCRIPT")
|
||||
set(function_for_args FetchContent_Populate)
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported context for direct population")
|
||||
endif()
|
||||
|
||||
_ep_get_add_keywords(keywords)
|
||||
_ep_parse_arguments_to_vars(
|
||||
${function_for_args}
|
||||
"${keywords}"
|
||||
${contentName}
|
||||
_EP_
|
||||
"${args_to_parse}"
|
||||
)
|
||||
|
||||
# We use a simplified set of directories here. We do not need the full set
|
||||
# of directories that ExternalProject supports, and we don't need the
|
||||
# extensive customization options it supports either. Note that
|
||||
# _EP_SOURCE_DIR and _EP_BINARY_DIR are always included in the saved args,
|
||||
# so we must not set them here.
|
||||
set(_EP_STAMP_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-stamp")
|
||||
set(_EP_TMP_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-tmp")
|
||||
set(_EP_DOWNLOAD_DIR "${_EP_TMP_DIR}")
|
||||
|
||||
file(MAKE_DIRECTORY
|
||||
"${_EP_SOURCE_DIR}"
|
||||
"${_EP_BINARY_DIR}"
|
||||
"${_EP_STAMP_DIR}"
|
||||
"${_EP_TMP_DIR}"
|
||||
)
|
||||
|
||||
# We take over the stamp files and use our own for detecting whether each
|
||||
# step is up-to-date. The method used by ExternalProject is specific to
|
||||
# using a sub-build and is not appropriate for us here.
|
||||
|
||||
set(download_script ${_EP_TMP_DIR}/download.cmake)
|
||||
set(update_script ${_EP_TMP_DIR}/upload.cmake)
|
||||
set(patch_script ${_EP_TMP_DIR}/patch.cmake)
|
||||
_ep_add_download_command(${contentName}
|
||||
SCRIPT_FILE ${download_script}
|
||||
DEPENDS_VARIABLE download_depends
|
||||
)
|
||||
_ep_add_update_command(${contentName}
|
||||
SCRIPT_FILE ${update_script}
|
||||
DEPENDS_VARIABLE update_depends
|
||||
)
|
||||
_ep_add_patch_command(${contentName}
|
||||
SCRIPT_FILE ${patch_script}
|
||||
# No additional dependencies for the patch step
|
||||
)
|
||||
|
||||
set(download_stamp ${_EP_STAMP_DIR}/download.stamp)
|
||||
set(update_stamp ${_EP_STAMP_DIR}/upload.stamp)
|
||||
set(patch_stamp ${_EP_STAMP_DIR}/patch.stamp)
|
||||
__FetchContent_doStepDirect(
|
||||
SCRIPT_FILE ${download_script}
|
||||
STAMP_FILE ${download_stamp}
|
||||
DEPENDS ${download_depends}
|
||||
)
|
||||
__FetchContent_doStepDirect(
|
||||
SCRIPT_FILE ${update_script}
|
||||
STAMP_FILE ${update_stamp}
|
||||
DEPENDS ${update_depends} ${download_stamp}
|
||||
)
|
||||
__FetchContent_doStepDirect(
|
||||
SCRIPT_FILE ${patch_script}
|
||||
STAMP_FILE ${patch_stamp}
|
||||
DEPENDS ${update_stamp}
|
||||
)
|
||||
|
||||
endfunction()
|
||||
|
||||
|
||||
function(__FetchContent_doStepDirect)
|
||||
set(noValueOptions )
|
||||
set(singleValueOptions
|
||||
SCRIPT_FILE
|
||||
STAMP_FILE
|
||||
)
|
||||
set(multiValueOptions
|
||||
DEPENDS
|
||||
)
|
||||
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||
"${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
|
||||
)
|
||||
|
||||
if(NOT EXISTS ${arg_STAMP_FILE})
|
||||
set(do_step YES)
|
||||
else()
|
||||
set(do_step NO)
|
||||
foreach(dep_file IN LISTS arg_DEPENDS arg_SCRIPT_FILE)
|
||||
if(NOT EXISTS "${arg_STAMP_FILE}" OR
|
||||
NOT EXISTS "${dep_file}" OR
|
||||
NOT "${arg_STAMP_FILE}" IS_NEWER_THAN "${dep_file}")
|
||||
set(do_step YES)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(do_step)
|
||||
include(${arg_SCRIPT_FILE})
|
||||
file(TOUCH "${arg_STAMP_FILE}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
function(__FetchContent_populateSubbuild)
|
||||
# All argument parsing is done in __FetchContent_doPopulate(), since it is
|
||||
# common to both the subbuild and direct population strategies.
|
||||
# Parsed arguments are in ARG_... variables.
|
||||
|
||||
# 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.
|
||||
@@ -1736,7 +1931,7 @@ function(FetchContent_Populate contentName)
|
||||
if(ARGN)
|
||||
# This is the direct population form with details fully specified
|
||||
# as part of the call, so we already have everything we need
|
||||
__FetchContent_directPopulate(
|
||||
__FetchContent_doPopulation(
|
||||
${contentNameLower}
|
||||
SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-subbuild"
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-src"
|
||||
@@ -1853,7 +2048,7 @@ function(FetchContent_Populate contentName)
|
||||
endif()
|
||||
endforeach()
|
||||
cmake_language(EVAL CODE "
|
||||
__FetchContent_directPopulate(
|
||||
__FetchContent_doPopulation(
|
||||
${contentNameLower}
|
||||
${quietFlag}
|
||||
UPDATE_DISCONNECTED ${disconnectUpdates}
|
||||
|
||||
@@ -514,7 +514,11 @@ class cmMakefile;
|
||||
"private dependencies of static libraries.", \
|
||||
3, 30, 0, cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0167, "The FindBoost module is removed.", 3, 30, 0, \
|
||||
cmPolicies::WARN)
|
||||
cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0168, \
|
||||
"FetchContent implements steps directly instead of through a " \
|
||||
"sub-build.", \
|
||||
3, 30, 0, cmPolicies::WARN)
|
||||
|
||||
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
|
||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||
|
||||
@@ -4,4 +4,10 @@ project(${RunCMake_TEST} NONE)
|
||||
# Tests assume no previous downloads in the output directory
|
||||
file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/_deps)
|
||||
|
||||
if(CMP0168 STREQUAL "NEW")
|
||||
cmake_policy(SET CMP0168 NEW)
|
||||
string(REGEX REPLACE "-direct$" "" RunCMake_TEST "${RunCMake_TEST}")
|
||||
else()
|
||||
cmake_policy(SET CMP0168 OLD)
|
||||
endif()
|
||||
include(${RunCMake_TEST}.cmake)
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
include(FetchContent)
|
||||
|
||||
# The file hash depends on the line endings used by git
|
||||
file(MD5 ${CMAKE_CURRENT_LIST_DIR}/dummyFile.txt md5_hash)
|
||||
|
||||
FetchContent_Declare(
|
||||
t1
|
||||
URL ${CMAKE_CURRENT_LIST_DIR}/dummyFile.txt
|
||||
URL_HASH MD5=${md5_hash}
|
||||
DOWNLOAD_NO_EXTRACT YES
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
CMake Error at .*/Modules/FetchContent\.cmake:[0-9]+ \(message\):
|
||||
Content t1 already populated in
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
CMake Error at .*/Modules/FetchContent\.cmake:[0-9]+ \(message\):
|
||||
No content details recorded for NoDetails
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
*Manually specified source directory is missing:
|
||||
+ *FETCHCONTENT_SOURCE_DIR_WITHPROJECT --> .*/ADirThatDoesNotExist
|
||||
@@ -1,3 +1,4 @@
|
||||
message(STATUS "FETCHCONTENT_SOURCE_DIR_WITHPROJECT = ${FETCHCONTENT_SOURCE_DIR_WITHPROJECT}")
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
*Relative source directory specified. This is not safe, as it depends on
|
||||
*the calling directory scope.
|
||||
+ *FETCHCONTENT_SOURCE_DIR_WITHPROJECT --> WithProject
|
||||
@@ -2,81 +2,107 @@ include(RunCMake)
|
||||
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
|
||||
run_cmake(MissingDetails)
|
||||
run_cmake(DirectIgnoresDetails)
|
||||
run_cmake(FirstDetailsWin)
|
||||
run_cmake(DownloadTwice)
|
||||
run_cmake(DownloadFile)
|
||||
run_cmake(IgnoreToolchainFile)
|
||||
run_cmake(SameGenerator)
|
||||
run_cmake(System)
|
||||
run_cmake(VarDefinitions)
|
||||
run_cmake(VarPassthroughs)
|
||||
run_cmake(GetProperties)
|
||||
run_cmake(UsesTerminalOverride)
|
||||
run_cmake(MakeAvailable)
|
||||
run_cmake(MakeAvailableTwice)
|
||||
run_cmake(MakeAvailableUndeclared)
|
||||
run_cmake(VerifyHeaderSet)
|
||||
function(run_cmake_with_cmp0168 name)
|
||||
run_cmake_with_options("${name}" -D CMP0168=OLD ${ARGN})
|
||||
run_cmake_with_options("${name}-direct" -D CMP0168=NEW ${ARGN})
|
||||
endfunction()
|
||||
|
||||
run_cmake_with_options(FindDependencyExport
|
||||
# Won't get to the part where CMP0168 matters
|
||||
run_cmake_with_options(MissingDetails -D CMP0168=NEW)
|
||||
|
||||
# These are testing specific aspects of the sub-build
|
||||
run_cmake_with_options(SameGenerator -D CMP0168=OLD)
|
||||
run_cmake_with_options(VarPassthroughs -D CMP0168=OLD)
|
||||
|
||||
run_cmake_with_cmp0168(DirectIgnoresDetails)
|
||||
run_cmake_with_cmp0168(FirstDetailsWin)
|
||||
run_cmake_with_cmp0168(DownloadTwice)
|
||||
run_cmake_with_cmp0168(DownloadFile)
|
||||
run_cmake_with_cmp0168(IgnoreToolchainFile)
|
||||
run_cmake_with_cmp0168(System)
|
||||
run_cmake_with_cmp0168(VarDefinitions)
|
||||
run_cmake_with_cmp0168(GetProperties)
|
||||
run_cmake_with_cmp0168(UsesTerminalOverride)
|
||||
run_cmake_with_cmp0168(MakeAvailable)
|
||||
run_cmake_with_cmp0168(MakeAvailableTwice)
|
||||
run_cmake_with_cmp0168(MakeAvailableUndeclared)
|
||||
run_cmake_with_cmp0168(VerifyHeaderSet)
|
||||
|
||||
run_cmake_with_cmp0168(FindDependencyExport
|
||||
-D "CMAKE_PROJECT_TOP_LEVEL_INCLUDES=${CMAKE_CURRENT_LIST_DIR}/FindDependencyExportDP.cmake"
|
||||
)
|
||||
|
||||
run_cmake_with_options(ManualSourceDirectory
|
||||
run_cmake_with_cmp0168(ManualSourceDirectory
|
||||
-D "FETCHCONTENT_SOURCE_DIR_WITHPROJECT=${CMAKE_CURRENT_LIST_DIR}/WithProject"
|
||||
)
|
||||
run_cmake_with_options(ManualSourceDirectoryMissing
|
||||
run_cmake_with_cmp0168(ManualSourceDirectoryMissing
|
||||
-D "FETCHCONTENT_SOURCE_DIR_WITHPROJECT=${CMAKE_CURRENT_LIST_DIR}/ADirThatDoesNotExist"
|
||||
)
|
||||
# Need to use :STRING to prevent CMake from automatically converting it to an
|
||||
# absolute path
|
||||
run_cmake_with_options(ManualSourceDirectoryRelative
|
||||
run_cmake_with_cmp0168(ManualSourceDirectoryRelative
|
||||
-D "FETCHCONTENT_SOURCE_DIR_WITHPROJECT:STRING=WithProject"
|
||||
)
|
||||
|
||||
function(run_FetchContent_DirOverrides)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/DirOverrides-build)
|
||||
function(run_FetchContent_DirOverrides cmp0168)
|
||||
if(cmp0168 STREQUAL "NEW")
|
||||
set(suffix "-direct")
|
||||
else()
|
||||
set(suffix "")
|
||||
endif()
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/DirOverrides${suffix}-build)
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
run_cmake(DirOverrides)
|
||||
run_cmake_with_options(DirOverrides${suffix} -D CMP0168=${cmp0168})
|
||||
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_with_options(DirOverridesDisconnected
|
||||
run_cmake_with_options(DirOverridesDisconnected${suffix}
|
||||
-D CMP0168=${cmp0168}
|
||||
-D FETCHCONTENT_FULLY_DISCONNECTED=YES
|
||||
)
|
||||
endfunction()
|
||||
run_FetchContent_DirOverrides()
|
||||
run_FetchContent_DirOverrides(OLD)
|
||||
run_FetchContent_DirOverrides(NEW)
|
||||
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
run_cmake(PreserveEmptyArgs)
|
||||
run_cmake_with_cmp0168(PreserveEmptyArgs)
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 0)
|
||||
|
||||
# We need to pass through CMAKE_GENERATOR and CMAKE_MAKE_PROGRAM
|
||||
# to ensure the test can run on machines where the build tool
|
||||
# isn't on the PATH. Some build slaves explicitly test with such
|
||||
# an arrangement (e.g. to test with spaces in the path). We also
|
||||
# pass through the platform and toolset for completeness, even
|
||||
# though we don't build anything, just in case this somehow affects
|
||||
# the way the build tool is invoked.
|
||||
run_cmake_command(ScriptMode
|
||||
${CMAKE_COMMAND}
|
||||
-DCMAKE_GENERATOR=${RunCMake_GENERATOR}
|
||||
-DCMAKE_GENERATOR_PLATFORM=${RunCMake_GENERATOR_PLATFORM}
|
||||
-DCMAKE_GENERATOR_TOOLSET=${RunCMake_GENERATOR_TOOLSET}
|
||||
-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}
|
||||
-P ${CMAKE_CURRENT_LIST_DIR}/ScriptMode.cmake
|
||||
)
|
||||
|
||||
function(run_FetchContent_ExcludeFromAll)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExcludeFromAll-build)
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
run_cmake(ExcludeFromAll)
|
||||
# We're testing FetchContent_MakeAvailable()'s add_subdirectory() behavior,
|
||||
# so it doesn't matter if we use OLD or NEW for CMP0168, but NEW is faster.
|
||||
run_cmake(ExcludeFromAll -D CMP0168=NEW)
|
||||
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build .)
|
||||
endfunction()
|
||||
run_FetchContent_ExcludeFromAll()
|
||||
|
||||
# Script mode testing requires more care for CMP0168 set to OLD.
|
||||
# We need to pass through CMAKE_GENERATOR and CMAKE_MAKE_PROGRAM
|
||||
# to ensure the test can run on machines where the build tool
|
||||
# isn't on the PATH. Some build machines explicitly test with such
|
||||
# an arrangement (e.g. to test with spaces in the path). We also
|
||||
# pass through the platform and toolset for completeness, even
|
||||
# though we don't build anything, just in case this somehow affects
|
||||
# the way the build tool is invoked.
|
||||
run_cmake_command(ScriptMode
|
||||
${CMAKE_COMMAND}
|
||||
-DCMP0168=OLD
|
||||
-DCMAKE_GENERATOR=${RunCMake_GENERATOR}
|
||||
-DCMAKE_GENERATOR_PLATFORM=${RunCMake_GENERATOR_PLATFORM}
|
||||
-DCMAKE_GENERATOR_TOOLSET=${RunCMake_GENERATOR_TOOLSET}
|
||||
-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}
|
||||
-P ${CMAKE_CURRENT_LIST_DIR}/ScriptMode.cmake
|
||||
)
|
||||
# CMP0168 NEW doesn't need a build tool or generator, so don't set them.
|
||||
run_cmake_command(ScriptMode-direct
|
||||
${CMAKE_COMMAND}
|
||||
-DCMP0168=NEW
|
||||
-P ${CMAKE_CURRENT_LIST_DIR}/ScriptMode.cmake
|
||||
)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
cmake_policy(SET CMP0168 ${CMP0168})
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
file(WRITE tmpFile.txt "Generated contents, not important")
|
||||
|
||||
Reference in New Issue
Block a user