瀏覽代碼

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
Craig Scott 3 年之前
父節點
當前提交
fd95769ccf
共有 1 個文件被更改,包括 42 次插入29 次删除
  1. 42 29
      Modules/FetchContent.cmake

+ 42 - 29
Modules/FetchContent.cmake

@@ -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()