summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-policies.7.rst1
-rw-r--r--Help/policy/CMP0135.rst29
-rw-r--r--Help/release/dev/ExternalProject-no-extract-timestamp.rst8
-rw-r--r--Modules/ExternalProject.cmake60
-rw-r--r--Modules/ExternalProject/extractfile.cmake.in2
-rw-r--r--Source/cmPolicies.h4
-rw-r--r--Tests/RunCMake/CMP0135/CMP0135-Common.cmake18
-rw-r--r--Tests/RunCMake/CMP0135/CMP0135-NEW-stdout.txt1
-rw-r--r--Tests/RunCMake/CMP0135/CMP0135-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0135/CMP0135-OLD-stdout.txt1
-rw-r--r--Tests/RunCMake/CMP0135/CMP0135-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0135/CMP0135-WARN-stderr.txt10
-rw-r--r--Tests/RunCMake/CMP0135/CMP0135-WARN-stdout.txt1
-rw-r--r--Tests/RunCMake/CMP0135/CMP0135-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0135/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0135/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake1
-rw-r--r--Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake1
-rw-r--r--Tests/RunCMake/ExternalProject/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake1
21 files changed, 149 insertions, 5 deletions
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index d1fafb5..b3091fa 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -58,6 +58,7 @@ Policies Introduced by CMake 3.24
.. toctree::
:maxdepth: 1
+ CMP0135: ExternalProject ignores timestamps in archives by default for the URL download method. </policy/CMP0135>
CMP0134: Fallback to \"HOST\" Windows registry view when \"TARGET\" view is not usable. </policy/CMP0134>
CMP0133: The CPack module disables SLA by default in the CPack DragNDrop Generator. </policy/CMP0133>
CMP0132: Do not set compiler environment variables on first run. </policy/CMP0132>
diff --git a/Help/policy/CMP0135.rst b/Help/policy/CMP0135.rst
new file mode 100644
index 0000000..1c0c134
--- /dev/null
+++ b/Help/policy/CMP0135.rst
@@ -0,0 +1,29 @@
+CMP0135
+-------
+
+.. versionadded:: 3.24
+
+When using the ``URL`` download method with the :command:`ExternalProject_Add`
+command, CMake 3.23 and below sets the timestamps of the extracted contents
+to the same as the timestamps in the archive. When the ``URL`` changes, the
+new archive is downloaded and extracted, but the timestamps of the extracted
+contents might not be newer than the previous contents. Anything that depends
+on the extracted contents might not be rebuilt, even though the contents may
+change.
+
+CMake 3.24 and above prefers to set the timestamps of all extracted contents
+to the time of the extraction. This ensures that anything that depends on the
+extracted contents will be rebuilt whenever the ``URL`` changes.
+
+The ``DOWNLOAD_EXTRACT_TIMESTAMP`` option to the
+:command:`ExternalProject_Add` command can be used to explicitly specify how
+timestamps should be handled. When ``DOWNLOAD_EXTRACT_TIMESTAMP`` is not
+given, this policy controls the default behavior. The ``OLD`` behavior for
+this policy is to restore the timestamps from the archive. The ``NEW``
+behavior sets the timestamps of extracted contents to the time of extraction.
+
+This policy was introduced in CMake version 3.24. CMake version |release|
+warns when the policy is not set and uses ``OLD`` behavior. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/release/dev/ExternalProject-no-extract-timestamp.rst b/Help/release/dev/ExternalProject-no-extract-timestamp.rst
new file mode 100644
index 0000000..0e8c01e
--- /dev/null
+++ b/Help/release/dev/ExternalProject-no-extract-timestamp.rst
@@ -0,0 +1,8 @@
+ExternalProject-no-extract-timestamp
+------------------------------------
+
+* The :command:`ExternalProject_Add` command gained a new
+ ``DOWNLOAD_EXTRACT_TIMESTAMP`` option for controlling whether the timestamps
+ of extracted contents are set to match those in the archive when the ``URL``
+ download method is used. A new policy :policy:`CMP0135` was added to control
+ the default behavior when the new option is not used.
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 42cb7a0..5c37be2 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -170,6 +170,19 @@ External Project Definition
the default name is generally suitable and is not normally used outside
of code internal to the ``ExternalProject`` module.
+ ``DOWNLOAD_EXTRACT_TIMESTAMP <bool>``
+ .. versionadded:: 3.24
+
+ When specified with a true value, the timestamps of the extracted
+ files will match those in the archive. When false, the timestamps of
+ the extracted files will reflect the time at which the extraction
+ was performed. If the download URL changes, timestamps based off
+ those in the archive can result in dependent targets not being rebuilt
+ when they potentially should have been. Therefore, unless the file
+ timestamps are significant to the project in some way, use a false
+ value for this option. If ``DOWNLOAD_EXTRACT_TIMESTAMP`` is not given,
+ the default is false. See policy :policy:`CMP0135`.
+
``DOWNLOAD_NO_EXTRACT <bool>``
.. versionadded:: 3.6
@@ -1534,7 +1547,7 @@ function(_ep_write_verifyfile_script script_filename LOCAL hash)
endfunction()
-function(_ep_write_extractfile_script script_filename name filename directory)
+function(_ep_write_extractfile_script script_filename name filename directory options)
set(args "")
if(filename MATCHES "(\\.|=)(7z|tar\\.bz2|tar\\.gz|tar\\.xz|tbz2|tgz|txz|zip)$")
@@ -2761,16 +2774,51 @@ hash=${hash}
)
endif()
list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake)
- if (NOT no_extract)
+ get_target_property(extract_timestamp ${name} _EP_DOWNLOAD_EXTRACT_TIMESTAMP)
+ if(no_extract)
+ if(NOT extract_timestamp STREQUAL "extract_timestamp-NOTFOUND")
+ message(FATAL_ERROR
+ "Cannot specify DOWNLOAD_EXTRACT_TIMESTAMP when using "
+ "DOWNLOAD_NO_EXTRACT TRUE"
+ )
+ endif()
+ set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
+ else()
+ if(extract_timestamp STREQUAL "extract_timestamp-NOTFOUND")
+ # Default depends on policy CMP0135
+ if(_EP_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(extract_timestamp TRUE)
+ elseif(_EP_CMP0135 STREQUAL "NEW")
+ set(extract_timestamp FALSE)
+ else()
+ set(extract_timestamp TRUE)
+ endif()
+ endif()
+ if(extract_timestamp)
+ set(options "")
+ else()
+ set(options "--touch")
+ endif()
_ep_write_extractfile_script(
"${stamp_dir}/extract-${name}.cmake"
"${name}"
"${file}"
"${source_dir}"
+ "${options}"
)
list(APPEND cmd COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake)
- else ()
- set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
endif ()
endif()
else()
@@ -3438,6 +3486,9 @@ function(ExternalProject_Add name)
)
set(cmp0114 "NEW")
endif()
+ cmake_policy(GET CMP0135 _EP_CMP0135
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
_ep_get_configuration_subdir_suffix(cfgdir)
@@ -3483,6 +3534,7 @@ function(ExternalProject_Add name)
URL_HASH
URL_MD5
DOWNLOAD_NAME
+ DOWNLOAD_EXTRACT_TIMESTAMP
DOWNLOAD_NO_EXTRACT
DOWNLOAD_NO_PROGRESS
TIMEOUT
diff --git a/Modules/ExternalProject/extractfile.cmake.in b/Modules/ExternalProject/extractfile.cmake.in
index d7f5756..984565b 100644
--- a/Modules/ExternalProject/extractfile.cmake.in
+++ b/Modules/ExternalProject/extractfile.cmake.in
@@ -29,7 +29,7 @@ file(MAKE_DIRECTORY "${ut_dir}")
# Extract it:
#
message(STATUS "extracting... [tar @args@]")
-execute_process(COMMAND ${CMAKE_COMMAND} -E tar @args@ ${filename}
+execute_process(COMMAND ${CMAKE_COMMAND} -E tar @args@ ${filename} @options@
WORKING_DIRECTORY ${ut_dir}
RESULT_VARIABLE rv
)
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 8739c55..7d06607 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -404,6 +404,10 @@ class cmMakefile;
SELECT(POLICY, CMP0134, \
"Fallback to \"HOST\" Windows registry view when \"TARGET\" view " \
"is not usable.", \
+ 3, 24, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0135, \
+ "ExternalProject ignores timestamps in archives by default for the " \
+ "URL download method", \
3, 24, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
diff --git a/Tests/RunCMake/CMP0135/CMP0135-Common.cmake b/Tests/RunCMake/CMP0135/CMP0135-Common.cmake
new file mode 100644
index 0000000..4b7cce5
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMP0135-Common.cmake
@@ -0,0 +1,18 @@
+include(ExternalProject)
+
+set(stamp_dir "${CMAKE_CURRENT_BINARY_DIR}/stamps")
+
+ExternalProject_Add(fake_ext_proj
+ # We don't actually do a build, so we never try to download from this URL
+ URL https://example.com/something.zip
+ STAMP_DIR ${stamp_dir}
+)
+
+# Report whether the --touch option was added to the extraction script
+set(extraction_script "${stamp_dir}/extract-fake_ext_proj.cmake")
+file(STRINGS "${extraction_script}" results REGEX "--touch")
+if("${results}" STREQUAL "")
+ message(STATUS "Using timestamps from archive")
+else()
+ message(STATUS "Using extraction time for the timestamps")
+endif()
diff --git a/Tests/RunCMake/CMP0135/CMP0135-NEW-stdout.txt b/Tests/RunCMake/CMP0135/CMP0135-NEW-stdout.txt
new file mode 100644
index 0000000..bf53c0b
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMP0135-NEW-stdout.txt
@@ -0,0 +1 @@
+Using extraction time for the timestamps
diff --git a/Tests/RunCMake/CMP0135/CMP0135-NEW.cmake b/Tests/RunCMake/CMP0135/CMP0135-NEW.cmake
new file mode 100644
index 0000000..1fd6354
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMP0135-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0135 NEW)
+include(CMP0135-Common.cmake)
diff --git a/Tests/RunCMake/CMP0135/CMP0135-OLD-stdout.txt b/Tests/RunCMake/CMP0135/CMP0135-OLD-stdout.txt
new file mode 100644
index 0000000..ee57beb
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMP0135-OLD-stdout.txt
@@ -0,0 +1 @@
+Using timestamps from archive
diff --git a/Tests/RunCMake/CMP0135/CMP0135-OLD.cmake b/Tests/RunCMake/CMP0135/CMP0135-OLD.cmake
new file mode 100644
index 0000000..80d58a7
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMP0135-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0135 OLD)
+include(CMP0135-Common.cmake)
diff --git a/Tests/RunCMake/CMP0135/CMP0135-WARN-stderr.txt b/Tests/RunCMake/CMP0135/CMP0135-WARN-stderr.txt
new file mode 100644
index 0000000..8ba0027
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMP0135-WARN-stderr.txt
@@ -0,0 +1,10 @@
+CMake Warning \(dev\) at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ 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\.
diff --git a/Tests/RunCMake/CMP0135/CMP0135-WARN-stdout.txt b/Tests/RunCMake/CMP0135/CMP0135-WARN-stdout.txt
new file mode 100644
index 0000000..ee57beb
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMP0135-WARN-stdout.txt
@@ -0,0 +1 @@
+Using timestamps from archive
diff --git a/Tests/RunCMake/CMP0135/CMP0135-WARN.cmake b/Tests/RunCMake/CMP0135/CMP0135-WARN.cmake
new file mode 100644
index 0000000..ab71c40
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMP0135-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0135-Common.cmake)
diff --git a/Tests/RunCMake/CMP0135/CMakeLists.txt b/Tests/RunCMake/CMP0135/CMakeLists.txt
new file mode 100644
index 0000000..5ff8d3e
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.23)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0135/RunCMakeTest.cmake b/Tests/RunCMake/CMP0135/RunCMakeTest.cmake
new file mode 100644
index 0000000..da92391
--- /dev/null
+++ b/Tests/RunCMake/CMP0135/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0135-WARN)
+run_cmake(CMP0135-OLD)
+run_cmake(CMP0135-NEW)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index c2677a0..515c6d8 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -149,6 +149,7 @@ if("${CMAKE_C_COMPILER_ID}" STREQUAL "LCC" OR
endif()
add_RunCMake_test(CMP0132)
+add_RunCMake_test(CMP0135)
# The test for Policy 65 requires the use of the
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake b/Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake
index bfed4fa..364bf9e 100644
--- a/Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies.cmake
@@ -4,6 +4,7 @@ if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12)
else()
cmake_policy(SET CMP0114 OLD) # Test deprecated behavior.
endif()
+cmake_policy(SET CMP0135 NEW)
include(ExternalProject)
diff --git a/Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake b/Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake
index 039dec6..da823cd 100644
--- a/Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake
+++ b/Tests/RunCMake/ExternalProject/Add_StepDependencies_no_target.cmake
@@ -4,6 +4,7 @@ if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12)
else()
cmake_policy(SET CMP0114 OLD) # Test deprecated behavior.
endif()
+cmake_policy(SET CMP0135 NEW)
include(ExternalProject)
diff --git a/Tests/RunCMake/ExternalProject/CMakeLists.txt b/Tests/RunCMake/ExternalProject/CMakeLists.txt
index 933a57a..b94f825 100644
--- a/Tests/RunCMake/ExternalProject/CMakeLists.txt
+++ b/Tests/RunCMake/ExternalProject/CMakeLists.txt
@@ -3,4 +3,5 @@ project(${RunCMake_TEST} NONE)
if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12 AND NOT RunCMake_TEST STREQUAL "Xcode-CMP0114")
cmake_policy(SET CMP0114 NEW)
endif()
+cmake_policy(SET CMP0135 NEW)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake
index 7ec1a00..e257425 100644
--- a/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake
+++ b/Tests/RunCMake/ExternalProject/NO_DEPENDS-CMP0114-NEW-Direct.cmake
@@ -1,4 +1,5 @@
cmake_policy(SET CMP0114 NEW)
+cmake_policy(SET CMP0135 NEW)
include(ExternalProject)
ExternalProject_Add(BAR SOURCE_DIR . TEST_COMMAND echo test)
ExternalProject_Add_StepTargets(BAR NO_DEPENDS test)