FetchContent: Restore support for multiple URL values

In c2044fdf3f (FetchContent: Respect the CMP0135 policy setting,
2022-06-02), the URL keyword was wrongly assumed to only have
a single value. Multiple URL values are allowed if they are all
non-local. Rework the logic to remove that incorrect assumption
and handle both single and multi-value URL combinations.

Fixes: #23792
This commit is contained in:
Craig Scott
2022-07-29 20:58:08 +10:00
parent 5ead1d0a25
commit fd95769ccf

View File

@@ -1189,19 +1189,18 @@ function(FetchContent_Declare contentName)
)
endif()
set(options "")
# Because we are only looking for a subset of the supported keywords, we
# cannot check for multi-value arguments with this method. We will have to
# handle the URL keyword differently.
set(oneValueArgs
SVN_REPOSITORY
DOWNLOAD_NO_EXTRACT
DOWNLOAD_EXTRACT_TIMESTAMP
URL
BINARY_DIR
SOURCE_DIR
)
set(multiValueArgs "")
cmake_parse_arguments(PARSE_ARGV 1 ARG
"${options}" "${oneValueArgs}" "${multiValueArgs}")
cmake_parse_arguments(PARSE_ARGV 1 ARG "" "${oneValueArgs}" "")
string(TOLOWER ${contentName} contentNameLower)
@@ -1230,31 +1229,45 @@ function(FetchContent_Declare contentName)
# explicitly set the relevant option if not already provided. The condition
# here is essentially an abbreviated version of the logic in
# ExternalProject's _ep_add_download_command() function.
if(ARG_URL AND
NOT IS_DIRECTORY "${ARG_URL}" AND
NOT ARG_DOWNLOAD_NO_EXTRACT AND
if(NOT ARG_DOWNLOAD_NO_EXTRACT AND
NOT DEFINED ARG_DOWNLOAD_EXTRACT_TIMESTAMP)
cmake_policy(GET CMP0135 _FETCHCONTENT_CMP0135
PARENT_SCOPE # undocumented, do not use outside of CMake
)
if(_FETCHCONTENT_CMP0135 STREQUAL "")
message(AUTHOR_WARNING
"The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy "
"CMP0135 is not set. The policy's OLD behavior will be used. "
"When using a URL download, the timestamps of extracted files "
"should preferably be that of the time of extraction, otherwise "
"code that depends on the extracted contents might not be "
"rebuilt if the URL changes. The OLD behavior preserves the "
"timestamps from the archive instead, but this is usually not "
"what you want. Update your project to the NEW behavior or "
"specify the DOWNLOAD_EXTRACT_TIMESTAMP option with a value of "
"true to avoid this robustness issue."
)
set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
elseif(_FETCHCONTENT_CMP0135 STREQUAL "NEW")
set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP FALSE)
else()
set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
list(FIND ARGN URL urlIndex)
if(urlIndex GREATER_EQUAL 0)
math(EXPR urlIndex "${urlIndex} + 1")
list(LENGTH ARGN numArgs)
if(urlIndex GREATER_EQUAL numArgs)
message(FATAL_ERROR
"URL keyword needs to be followed by at least one URL"
)
endif()
# If we have multiple URLs, none of them are allowed to be local paths.
# Therefore, we can test just the first URL, and if it is non-local, so
# will be the others if there are more.
list(GET ARGN ${urlIndex} firstUrl)
if(NOT IS_DIRECTORY "${firstUrl}")
cmake_policy(GET CMP0135 _FETCHCONTENT_CMP0135
PARENT_SCOPE # undocumented, do not use outside of CMake
)
if(_FETCHCONTENT_CMP0135 STREQUAL "")
message(AUTHOR_WARNING
"The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy "
"CMP0135 is not set. The policy's OLD behavior will be used. "
"When using a URL download, the timestamps of extracted files "
"should preferably be that of the time of extraction, otherwise "
"code that depends on the extracted contents might not be "
"rebuilt if the URL changes. The OLD behavior preserves the "
"timestamps from the archive instead, but this is usually not "
"what you want. Update your project to the NEW behavior or "
"specify the DOWNLOAD_EXTRACT_TIMESTAMP option with a value of "
"true to avoid this robustness issue."
)
set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
elseif(_FETCHCONTENT_CMP0135 STREQUAL "NEW")
set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP FALSE)
else()
set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
endif()
endif()
endif()
endif()