mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
@@ -0,0 +1,7 @@
|
||||
ExternalData-link-mode
|
||||
----------------------
|
||||
|
||||
* The :module:`ExternalData` module gained an
|
||||
:variable:`ExternalData_LINK_MODE` variable to select an ordered list
|
||||
of file materialization modes for hard links, symbolic links, and
|
||||
copies.
|
||||
+118
-18
@@ -179,6 +179,36 @@ calling any of the functions provided by this module.
|
||||
data files under ``ExternalData_BINARY_ROOT``. By default, hash records
|
||||
continue to be placed next to the materialized data.
|
||||
|
||||
.. variable:: ExternalData_LINK_MODE
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
The ``ExternalData_LINK_MODE`` variable selects how real data files are
|
||||
exposed under ``ExternalData_BINARY_ROOT``.
|
||||
|
||||
The value may be one of:
|
||||
|
||||
``auto``
|
||||
Try each of the supported modes until one succeeds.
|
||||
The default order is ``hardlink -> symlink -> copy`` on Windows
|
||||
and ``symlink -> hardlink -> copy`` on other platforms.
|
||||
|
||||
``hardlink``
|
||||
Materialize paths as hard links to the real files.
|
||||
|
||||
``symlink``
|
||||
Materialize paths as symbolic links to the real files.
|
||||
|
||||
``copy``
|
||||
Materialize paths as copies of the real files.
|
||||
|
||||
Or, the value may be a :ref:`semicolon-separated list <CMake Language Lists>`
|
||||
of ``hardlink``, ``symlink``, and ``copy`` to try the modes in the order
|
||||
specified until one succeeds.
|
||||
|
||||
When ``ExternalData_NO_SYMLINKS`` is set, the ``symlink`` mode is removed
|
||||
from automatic selection and cannot be requested explicitly.
|
||||
|
||||
.. variable:: ExternalData_OBJECT_STORES
|
||||
|
||||
The ``ExternalData_OBJECT_STORES`` variable may be set to a list of local
|
||||
@@ -1010,33 +1040,103 @@ if(NOT ExternalData_URL_TEMPLATES AND NOT ExternalData_OBJECT_STORES)
|
||||
"Neither ExternalData_URL_TEMPLATES nor ExternalData_OBJECT_STORES is set!")
|
||||
endif()
|
||||
|
||||
function(_ExternalData_compute_link_target src dst var_tgt)
|
||||
get_filename_component(dst_dir "${dst}" PATH)
|
||||
set(tgt "${src}")
|
||||
if(relative_top)
|
||||
# Use relative path if files are close enough.
|
||||
file(RELATIVE_PATH relsrc "${relative_top}" "${src}")
|
||||
file(RELATIVE_PATH reldst "${relative_top}" "${dst}")
|
||||
if(NOT IS_ABSOLUTE "${relsrc}" AND NOT "${relsrc}" MATCHES "^\\.\\./" AND
|
||||
NOT IS_ABSOLUTE "${reldst}" AND NOT "${reldst}" MATCHES "^\\.\\./")
|
||||
file(RELATIVE_PATH tgt "${dst_dir}" "${src}")
|
||||
endif()
|
||||
endif()
|
||||
set(${var_tgt} "${tgt}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_ExternalData_try_link_mode mode src dst var_result)
|
||||
if(mode STREQUAL "copy")
|
||||
file(COPY_FILE "${src}" "${dst}" RESULT result INPUT_MAY_BE_RECENT)
|
||||
elseif(mode STREQUAL "hardlink")
|
||||
file(CREATE_LINK "${src}" "${dst}" RESULT result)
|
||||
elseif(mode STREQUAL "symlink")
|
||||
_ExternalData_compute_link_target("${src}" "${dst}" tgt)
|
||||
file(CREATE_LINK "${tgt}" "${dst}" RESULT result SYMBOLIC)
|
||||
else()
|
||||
set(result "Unsupported ExternalData_LINK_MODE `${mode}`")
|
||||
endif()
|
||||
set(${var_result} "${result}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_ExternalData_get_auto_link_modes var_modes)
|
||||
if(CMAKE_HOST_WIN32)
|
||||
set(modes hardlink)
|
||||
if(NOT ExternalData_NO_SYMLINKS)
|
||||
list(APPEND modes symlink)
|
||||
endif()
|
||||
list(APPEND modes copy)
|
||||
else()
|
||||
if(NOT ExternalData_NO_SYMLINKS)
|
||||
list(APPEND modes symlink)
|
||||
endif()
|
||||
list(APPEND modes hardlink copy)
|
||||
endif()
|
||||
set(${var_modes} "${modes}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_ExternalData_get_requested_link_modes var_modes)
|
||||
if(DEFINED ExternalData_LINK_MODE AND NOT "${ExternalData_LINK_MODE}" STREQUAL "")
|
||||
set(requested_modes "${ExternalData_LINK_MODE}")
|
||||
else()
|
||||
set(requested_modes auto)
|
||||
endif()
|
||||
string(TOLOWER "${requested_modes}" requested_modes_lower)
|
||||
|
||||
if(requested_modes_lower STREQUAL "auto")
|
||||
_ExternalData_get_auto_link_modes(modes)
|
||||
else()
|
||||
set(modes)
|
||||
foreach(mode IN LISTS requested_modes)
|
||||
string(TOLOWER "${mode}" mode_lower)
|
||||
if(mode_lower STREQUAL "copy" OR mode_lower STREQUAL "hardlink")
|
||||
list(APPEND modes "${mode_lower}")
|
||||
elseif(mode_lower STREQUAL "symlink")
|
||||
if(ExternalData_NO_SYMLINKS)
|
||||
message(FATAL_ERROR
|
||||
"ExternalData_LINK_MODE with `symlink` conflicts with NO_SYMLINKS")
|
||||
endif()
|
||||
list(APPEND modes symlink)
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"ExternalData_LINK_MODE must be `auto` or list: hardlink, symlink, copy")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(${var_modes} "${modes}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_ExternalData_link_or_copy src dst)
|
||||
# Create a temporary file first.
|
||||
get_filename_component(dst_dir "${dst}" PATH)
|
||||
file(MAKE_DIRECTORY "${dst_dir}")
|
||||
_ExternalData_random(random)
|
||||
set(tmp "${dst}.tmp${random}")
|
||||
if(UNIX AND NOT ExternalData_NO_SYMLINKS)
|
||||
# Create a symbolic link.
|
||||
set(tgt "${src}")
|
||||
if(relative_top)
|
||||
# Use relative path if files are close enough.
|
||||
file(RELATIVE_PATH relsrc "${relative_top}" "${src}")
|
||||
file(RELATIVE_PATH relfile "${relative_top}" "${dst}")
|
||||
if(NOT IS_ABSOLUTE "${relsrc}" AND NOT "${relsrc}" MATCHES "^\\.\\./" AND
|
||||
NOT IS_ABSOLUTE "${reldst}" AND NOT "${reldst}" MATCHES "^\\.\\./")
|
||||
file(RELATIVE_PATH tgt "${dst_dir}" "${src}")
|
||||
endif()
|
||||
_ExternalData_get_requested_link_modes(_ExternalData_link_modes)
|
||||
|
||||
unset(result)
|
||||
foreach(_ExternalData_mode IN LISTS _ExternalData_link_modes)
|
||||
_ExternalData_try_link_mode("${_ExternalData_mode}" "${src}" "${tmp}" result)
|
||||
if(NOT result)
|
||||
break()
|
||||
endif()
|
||||
# Create link (falling back to copying if there's a problem).
|
||||
file(CREATE_LINK "${tgt}" "${tmp}" RESULT result COPY_ON_ERROR SYMBOLIC)
|
||||
else()
|
||||
# Create a copy.
|
||||
file(COPY_FILE "${src}" "${tmp}" RESULT result INPUT_MAY_BE_RECENT)
|
||||
endif()
|
||||
file(REMOVE "${tmp}")
|
||||
endforeach()
|
||||
|
||||
if(result)
|
||||
file(REMOVE "${tmp}")
|
||||
message(FATAL_ERROR "Failed to create:\n \"${tmp}\"\nfrom:\n \"${obj}\"\nwith error:\n ${result}")
|
||||
message(FATAL_ERROR "Failed to create:\n \"${tmp}\"\nfrom:\n \"${src}\"\nwith error:\n ${result}")
|
||||
endif()
|
||||
|
||||
# Atomically create/replace the real destination.
|
||||
|
||||
@@ -4,4 +4,5 @@ set(ExternalData_TIMEOUT_INACTIVITY "@ExternalData_TIMEOUT_INACTIVITY@")
|
||||
set(ExternalData_TIMEOUT_ABSOLUTE "@ExternalData_TIMEOUT_ABSOLUTE@")
|
||||
set(ExternalData_NO_SYMLINKS "@ExternalData_NO_SYMLINKS@")
|
||||
set(ExternalData_STATE_ROOT "@ExternalData_STATE_ROOT@")
|
||||
set(ExternalData_LINK_MODE "@ExternalData_LINK_MODE@")
|
||||
@_ExternalData_CONFIG_CODE@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
CMake Error at .*/Modules/ExternalData\.cmake:[0-9]+ \(message\):
|
||||
ExternalData_LINK_MODE must be `auto` or list: hardlink, symlink, copy
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
CMake Error at .*/Modules/ExternalData\.cmake:[0-9]+ \(message\):
|
||||
ExternalData_LINK_MODE with `symlink` conflicts with NO_SYMLINKS
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -1,5 +1,25 @@
|
||||
include(RunCMake)
|
||||
|
||||
function(run_externaldata_local test)
|
||||
run_cmake_command(${test}
|
||||
${CMAKE_COMMAND}
|
||||
-DExternalData_ACTION=local
|
||||
-DExternalData_OBJECT_STORES=${RunCMake_BINARY_DIR}/${test}-store
|
||||
${ARGN}
|
||||
-Dfile=${RunCMake_BINARY_DIR}/${test}-output.txt
|
||||
-Dname=${RunCMake_SOURCE_DIR}/CMakeLists.txt
|
||||
-P ${RunCMake_SOURCE_DIR}/../../../Modules/ExternalData.cmake
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(run_externaldata_local_link_mode test link_mode)
|
||||
string(REPLACE ";" "\\\\;" link_mode_arg "${link_mode}")
|
||||
run_externaldata_local(${test}
|
||||
"-DExternalData_LINK_MODE=${link_mode_arg}"
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
run_cmake(BadAlgoMap1)
|
||||
run_cmake(BadAlgoMap2)
|
||||
run_cmake(BadArguments)
|
||||
@@ -8,6 +28,13 @@ run_cmake(BadCustom2)
|
||||
run_cmake(BadCustom3)
|
||||
run_cmake(BadCustom4)
|
||||
run_cmake(BadHashAlgo1)
|
||||
run_externaldata_local_link_mode(BadLinkMode "invalid;copy"
|
||||
)
|
||||
run_externaldata_local_link_mode(BadLinkModeNoSymlinks "symlink;copy"
|
||||
-DExternalData_NO_SYMLINKS=1
|
||||
)
|
||||
run_externaldata_local_link_mode(GoodLinkModeList "copy;hardlink"
|
||||
)
|
||||
run_cmake(BadOption1)
|
||||
run_cmake(BadOption2)
|
||||
run_cmake(BadRecurse1)
|
||||
|
||||
Reference in New Issue
Block a user