mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-17 15:32:10 +08:00
ExternalProject: Add DOWNLOAD_EXTRACT_TIMESTAMP option and policy
Add the option to keep the current filestamps when extracting an archive in ExternalProject_Add. Enabling this option makes the behavior consistent with how ExternalProject_Add is used when checking out code from revision control instead of an archive. Fixes: #22746
This commit is contained in:

committed by
Craig Scott

parent
e0dbca93aa
commit
a283e58b51
@@ -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>
|
||||
|
29
Help/policy/CMP0135.rst
Normal file
29
Help/policy/CMP0135.rst
Normal file
@@ -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
|
@@ -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.
|
@@ -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
|
||||
|
@@ -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
|
||||
)
|
||||
|
@@ -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)
|
||||
|
18
Tests/RunCMake/CMP0135/CMP0135-Common.cmake
Normal file
18
Tests/RunCMake/CMP0135/CMP0135-Common.cmake
Normal file
@@ -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()
|
1
Tests/RunCMake/CMP0135/CMP0135-NEW-stdout.txt
Normal file
1
Tests/RunCMake/CMP0135/CMP0135-NEW-stdout.txt
Normal file
@@ -0,0 +1 @@
|
||||
Using extraction time for the timestamps
|
2
Tests/RunCMake/CMP0135/CMP0135-NEW.cmake
Normal file
2
Tests/RunCMake/CMP0135/CMP0135-NEW.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
include(CMP0135-Common.cmake)
|
1
Tests/RunCMake/CMP0135/CMP0135-OLD-stdout.txt
Normal file
1
Tests/RunCMake/CMP0135/CMP0135-OLD-stdout.txt
Normal file
@@ -0,0 +1 @@
|
||||
Using timestamps from archive
|
2
Tests/RunCMake/CMP0135/CMP0135-OLD.cmake
Normal file
2
Tests/RunCMake/CMP0135/CMP0135-OLD.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0135 OLD)
|
||||
include(CMP0135-Common.cmake)
|
10
Tests/RunCMake/CMP0135/CMP0135-WARN-stderr.txt
Normal file
10
Tests/RunCMake/CMP0135/CMP0135-WARN-stderr.txt
Normal file
@@ -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\.
|
1
Tests/RunCMake/CMP0135/CMP0135-WARN-stdout.txt
Normal file
1
Tests/RunCMake/CMP0135/CMP0135-WARN-stdout.txt
Normal file
@@ -0,0 +1 @@
|
||||
Using timestamps from archive
|
2
Tests/RunCMake/CMP0135/CMP0135-WARN.cmake
Normal file
2
Tests/RunCMake/CMP0135/CMP0135-WARN.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
include(CMP0135-Common.cmake)
|
3
Tests/RunCMake/CMP0135/CMakeLists.txt
Normal file
3
Tests/RunCMake/CMP0135/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
5
Tests/RunCMake/CMP0135/RunCMakeTest.cmake
Normal file
5
Tests/RunCMake/CMP0135/RunCMakeTest.cmake
Normal file
@@ -0,0 +1,5 @@
|
||||
include(RunCMake)
|
||||
|
||||
run_cmake(CMP0135-WARN)
|
||||
run_cmake(CMP0135-OLD)
|
||||
run_cmake(CMP0135-NEW)
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user