From a73ddd2ddb9f769ef168e8e788737bab73ca012e Mon Sep 17 00:00:00 2001 From: Hanna Rusakovich Date: Wed, 15 Oct 2025 17:01:08 +0300 Subject: [PATCH] file(CREATE_LINK): Implement COPY_ON_ERROR for directories Add policy `CMP0205` for compatibility with projects not expecting this. Fixes: #27294 --- Help/command/file.rst | 7 +- Help/manual/cmake-policies.7.rst | 8 ++ Help/policy/CMP0205.rst | 23 ++++++ Source/cmFileCommand.cxx | 75 +++++++++++++++---- Source/cmPolicies.h | 5 +- .../CMP0205-HardLink-NEW.cmake | 3 + .../CMP0205-HardLink-OLD.cmake | 3 + .../CMP0205-HardLink-WARN-stderr.txt | 38 ++++++++++ .../CMP0205-HardLink-WARN.cmake | 3 + .../CMP0205-SymLink-NEW.cmake | 3 + .../CMP0205-SymLink-OLD.cmake | 3 + .../CMP0205-SymLink-WARN-stderr.txt | 19 +++++ .../CMP0205-SymLink-WARN.cmake | 3 + .../file-CREATE_LINK/CMP0205-common-NEW.cmake | 12 +++ .../file-CREATE_LINK/CMP0205-common-OLD.cmake | 6 ++ .../CMP0205-common-WARN.cmake | 6 ++ .../file-CREATE_LINK/CMP0205-common.cmake | 14 ++++ .../file-CREATE_LINK/CMP0205/test.txt | 0 ...e => CREATE_LINK-COPY_ON_ERROR-file.cmake} | 3 +- .../file-CREATE_LINK/RunCMakeTest.cmake | 33 +++++++- 20 files changed, 247 insertions(+), 20 deletions(-) create mode 100644 Help/policy/CMP0205.rst create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-NEW.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-OLD.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-WARN-stderr.txt create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-WARN.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-NEW.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-OLD.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-WARN-stderr.txt create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-WARN.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-common-NEW.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-common-OLD.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-common-WARN.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205-common.cmake create mode 100644 Tests/RunCMake/file-CREATE_LINK/CMP0205/test.txt rename Tests/RunCMake/file-CREATE_LINK/{CREATE_LINK-COPY_ON_ERROR.cmake => CREATE_LINK-COPY_ON_ERROR-file.cmake} (77%) diff --git a/Help/command/file.rst b/Help/command/file.rst index 81f2a0121a..ec21fae991 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -615,11 +615,12 @@ Filesystem emitted. Specifying ``COPY_ON_ERROR`` enables copying the file as a fallback if - creating the link fails. If the source is a directory, the destination - directory will be created if it does not exist, but no files will be copied - the from source one. It can be useful for handling situations such as + creating the link fails. It can be useful for handling situations such as ```` and ```` being on different drives or mount points, which would make them unable to support a hard link. + If the source is a directory, the destination directory will be created if + it does not exist. Contents of the source directory will be copied to the + destination directory unless policy :policy:`CMP0205` is not set to ``NEW``. .. signature:: file(CHMOD ... ... diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index fd010484d1..7a41e00b97 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -92,6 +92,14 @@ Supported Policies The following policies are supported. +Policies Introduced by CMake 4.3 +-------------------------------- + +.. toctree:: + :maxdepth: 1 + + CMP0205: file(CREATE_LINK) with COPY_ON_ERROR copies directory content. + Policies Introduced by CMake 4.2 -------------------------------- diff --git a/Help/policy/CMP0205.rst b/Help/policy/CMP0205.rst new file mode 100644 index 0000000000..b08ef4a16e --- /dev/null +++ b/Help/policy/CMP0205.rst @@ -0,0 +1,23 @@ +CMP0205 +------- + +.. versionadded:: 4.3 + +:command:`file(CREATE_LINK)` with ``COPY_ON_ERROR`` copies directory content. + +The :command:`file(CREATE_LINK)` command's ``COPY_ON_ERROR`` option copies +the source file to the destination as a fallback if linking it fails. +If the source is a directory, CMake 4.2 and below create the destination +directory but do not copy its contents. CMake 4.3 and above prefer to +copy the directory contents too. This policy provides compatibility with +projects that have not been updated to expect the contents to be copied. + +The ``OLD`` behavior for this policy is to create the destination directory +without copying contents. The ``NEW`` behavior for this policy to create +the destination directory and copy contents from the source directory. + +.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.3 +.. |WARNS_OR_DOES_NOT_WARN| replace:: warns +.. include:: include/STANDARD_ADVICE.rst + +.. include:: include/DEPRECATED.rst diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index b7a9be3b07..4666baa265 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3221,8 +3221,13 @@ bool HandleCreateLinkCommand(std::vector const& args, return false; } + cmPolicies::PolicyStatus const cmp0205 = + status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0205); + // Hard link requires original file to exist. - if (!arguments.Symbolic && !cmSystemTools::FileExists(fileName)) { + if (!arguments.Symbolic && + (!cmSystemTools::PathExists(fileName) || + (cmp0205 != cmPolicies::NEW && !cmSystemTools::FileExists(fileName)))) { result = "Cannot hard link \'" + fileName + "\' as it does not exist."; if (!arguments.Result.empty()) { status.GetMakefile().AddDefinition(arguments.Result, result); @@ -3234,11 +3239,17 @@ bool HandleCreateLinkCommand(std::vector const& args, // Check if the new file already exists and remove it. if (cmSystemTools::PathExists(newFileName)) { - cmsys::Status rmStatus = cmSystemTools::RemoveFile(newFileName); + cmsys::Status rmStatus; + if (cmp0205 == cmPolicies::NEW && + cmSystemTools::FileIsDirectory(newFileName)) { + rmStatus = cmSystemTools::RepeatedRemoveDirectory(newFileName); + } else { + rmStatus = cmSystemTools::RemoveFile(newFileName); + } if (!rmStatus) { - auto err = cmStrCat("Failed to create link '", newFileName, - "' because existing path cannot be removed: ", - rmStatus.GetString(), '\n'); + std::string err = cmStrCat("Failed to create link '", newFileName, + "' because existing path cannot be removed: ", + rmStatus.GetString(), '\n'); if (!arguments.Result.empty()) { status.GetMakefile().AddDefinition(arguments.Result, err); @@ -3249,6 +3260,8 @@ bool HandleCreateLinkCommand(std::vector const& args, } } + bool const sourceIsDirectory = cmSystemTools::FileIsDirectory(fileName); + // Whether the operation completed successfully. bool completed = false; @@ -3263,20 +3276,54 @@ bool HandleCreateLinkCommand(std::vector const& args, "': ", linked.GetString()); } } else { - cmsys::Status linked = - cmSystemTools::CreateLinkQuietly(fileName, newFileName); - if (linked) { - completed = true; - } else { - result = cmStrCat("failed to create link '", newFileName, - "': ", linked.GetString()); + bool needToTry = true; + if (sourceIsDirectory) { + if (cmp0205 == cmPolicies::NEW) { + needToTry = false; + } else if (cmp0205 == cmPolicies::WARN) { + status.GetMakefile().IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat("Path\n ", fileName, + "\nis directory. Hardlinks creation is not supported for " + "directories.\n", + cmPolicies::GetPolicyWarning(cmPolicies::CMP0205))); + } } + + if (needToTry) { + cmsys::Status linked = + cmSystemTools::CreateLinkQuietly(fileName, newFileName); + if (linked) { + completed = true; + } else { + result = cmStrCat("failed to create link '", newFileName, + "': ", linked.GetString()); + } + } else { + result = + cmStrCat("failed to create link '", newFileName, "': not supported"); + } + } + + if (arguments.CopyOnError && cmp0205 == cmPolicies::WARN && + sourceIsDirectory) { + status.GetMakefile().IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat("Path\n ", fileName, + "\nis directory. It will be copied recursively when NEW policy " + "behavior applies for CMP0205.\n", + cmPolicies::GetPolicyWarning(cmPolicies::CMP0205))); } // Check if copy-on-error is enabled in the arguments. if (!completed && arguments.CopyOnError) { - cmsys::Status copied = - cmsys::SystemTools::CopyFileAlways(fileName, newFileName); + cmsys::Status copied; + if (cmp0205 == cmPolicies::NEW && sourceIsDirectory) { + copied = cmsys::SystemTools::CopyADirectory(fileName, newFileName); + } else { + copied = cmsys::SystemTools::CopyFileAlways(fileName, newFileName); + } + if (copied) { completed = true; } else { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 2f22aaad7e..554d061df5 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -612,7 +612,10 @@ class cmMakefile; 4, 2, 0, WARN) \ SELECT(POLICY, CMP0204, \ "A character set is always defined when targeting the MSVC ABI.", 4, \ - 2, 0, WARN) + 2, 0, WARN) \ + SELECT(POLICY, CMP0205, \ + "file(CREATE_LINK) with COPY_ON_ERROR copies directory content.", 4, \ + 3, 0, WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-NEW.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-NEW.cmake new file mode 100644 index 0000000000..4cc82ae8ff --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-NEW.cmake @@ -0,0 +1,3 @@ +set(link_name HardLink) +set(maybe_SYMBOLIC) +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common-NEW.cmake") diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-OLD.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-OLD.cmake new file mode 100644 index 0000000000..e68cb7f3a2 --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-OLD.cmake @@ -0,0 +1,3 @@ +set(link_name HardLink) +set(maybe_SYMBOLIC) +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common-OLD.cmake") diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-WARN-stderr.txt b/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-WARN-stderr.txt new file mode 100644 index 0000000000..52873f3e5e --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-WARN-stderr.txt @@ -0,0 +1,38 @@ +^CMake Warning \(dev\) at [^ +]*/CMP0205-common\.cmake:[0-9]+ \(file\): + Path + + [^ +]*[\\|/]file-CREATE_LINK[\\|/]CMP0205 + + is directory. Hardlinks creation is not supported for directories. + + Policy CMP0205 is not set: file\(CREATE_LINK\) with COPY_ON_ERROR copies + directory content\. Run "cmake --help-policy CMP0205" for policy details\. + Use the cmake_policy command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + [^ +]*/CMP0205-common-WARN\.cmake:[0-9]+ \(include\) + [^ +]*/CMP0205-HardLink-WARN\.cmake:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Warning \(dev\) at [^ +]*/CMP0205-common\.cmake:[0-9]+ \(file\): + Path + + [^ +]*[\\|/]file-CREATE_LINK[\\|/]CMP0205 + + is directory. It will be copied recursively when NEW policy behavior + applies for CMP0205\. + + Policy CMP0205 is not set: file\(CREATE_LINK\) with COPY_ON_ERROR copies + directory content\. Run "cmake --help-policy CMP0205" for policy details\. + Use the cmake_policy command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + [^ +]*/CMP0205-common-WARN\.cmake:[0-9]+ \(include\) + [^ +]*/CMP0205-HardLink-WARN\.cmake:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-WARN.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-WARN.cmake new file mode 100644 index 0000000000..c8ebc710c4 --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-HardLink-WARN.cmake @@ -0,0 +1,3 @@ +set(link_name HardLink) +set(maybe_SYMBOLIC) +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common-WARN.cmake") diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-NEW.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-NEW.cmake new file mode 100644 index 0000000000..4831ab2b29 --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-NEW.cmake @@ -0,0 +1,3 @@ +set(link_name SymLink) +set(maybe_SYMBOLIC SYMBOLIC) +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common-NEW.cmake") diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-OLD.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-OLD.cmake new file mode 100644 index 0000000000..7fb1f6a5ca --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-OLD.cmake @@ -0,0 +1,3 @@ +set(link_name SymLink) +set(maybe_SYMBOLIC SYMBOLIC) +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common-OLD.cmake") diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-WARN-stderr.txt b/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-WARN-stderr.txt new file mode 100644 index 0000000000..0399f1fd8e --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-WARN-stderr.txt @@ -0,0 +1,19 @@ +^CMake Warning \(dev\) at [^ +]*/CMP0205-common\.cmake:[0-9]+ \(file\): + Path + + [^ +]*[\\|/]file-CREATE_LINK[\\|/]CMP0205 + + is directory. It will be copied recursively when NEW policy behavior + applies for CMP0205\. + + Policy CMP0205 is not set: file\(CREATE_LINK\) with COPY_ON_ERROR copies + directory content\. Run "cmake --help-policy CMP0205" for policy details\. + Use the cmake_policy command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + [^ +]*/CMP0205-common-WARN\.cmake:[0-9]+ \(include\) + [^ +]*/CMP0205-SymLink-WARN\.cmake:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-WARN.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-WARN.cmake new file mode 100644 index 0000000000..b14ec15df7 --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-SymLink-WARN.cmake @@ -0,0 +1,3 @@ +set(link_name SymLink) +set(maybe_SYMBOLIC SYMBOLIC) +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common-WARN.cmake") diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-NEW.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-NEW.cmake new file mode 100644 index 0000000000..15e6a361c6 --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-NEW.cmake @@ -0,0 +1,12 @@ +cmake_policy(SET CMP0205 NEW) +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common.cmake") + +if(NOT allFilesDst) + message(SEND_ERROR "Destination directory is empty: '${allFilesDst}'") +endif() + +if(NOT "${allFilesSrc}" STREQUAL "${allFilesDst}") + message(SEND_ERROR "Source and destination directories are not equal") + message(SEND_ERROR "Source files: '${allFilesSrc}'") + message(SEND_ERROR "Destination files: '${allFilesDst}'") +endif() diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-OLD.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-OLD.cmake new file mode 100644 index 0000000000..76add41239 --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-OLD.cmake @@ -0,0 +1,6 @@ +cmake_policy(SET CMP0205 OLD) +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common.cmake") + +if(allFilesDst) + message(SEND_ERROR "Directory is not empty: '${allFilesDst}'") +endif() diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-WARN.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-WARN.cmake new file mode 100644 index 0000000000..ee940466b7 --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-common-WARN.cmake @@ -0,0 +1,6 @@ +# CMP0205 is unset +include("${CMAKE_CURRENT_LIST_DIR}/CMP0205-common.cmake") + +if(allFilesDst) + message(SEND_ERROR "Directory is not empty: '${allFilesDst}'") +endif() diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205-common.cmake b/Tests/RunCMake/file-CREATE_LINK/CMP0205-common.cmake new file mode 100644 index 0000000000..deb313f9a5 --- /dev/null +++ b/Tests/RunCMake/file-CREATE_LINK/CMP0205-common.cmake @@ -0,0 +1,14 @@ +# Use COPY_ON_ERROR to handle the case where the source and destination +# directory are on different devices and empty. +file(CREATE_LINK + ${CMAKE_CURRENT_LIST_DIR}/CMP0205 ${CMAKE_CURRENT_BINARY_DIR}/CMP0205-${link_name} + ${maybe_SYMBOLIC} + RESULT result + COPY_ON_ERROR + ) +if(NOT result STREQUAL "0") + message(SEND_ERROR "COPY_ON_ERROR failed: '${result}'") +endif() + +file(GLOB_RECURSE allFilesSrc LIST_DIRECTORIES true RELATIVE "${CMAKE_CURRENT_LIST_DIR}/CMP0205" "${CMAKE_CURRENT_LIST_DIR}/CMP0205/*") +file(GLOB_RECURSE allFilesDst LIST_DIRECTORIES true RELATIVE "${CMAKE_CURRENT_BINARY_DIR}/CMP0205-${link_name}" "${CMAKE_CURRENT_BINARY_DIR}/CMP0205-${link_name}/*") diff --git a/Tests/RunCMake/file-CREATE_LINK/CMP0205/test.txt b/Tests/RunCMake/file-CREATE_LINK/CMP0205/test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Tests/RunCMake/file-CREATE_LINK/CREATE_LINK-COPY_ON_ERROR.cmake b/Tests/RunCMake/file-CREATE_LINK/CREATE_LINK-COPY_ON_ERROR-file.cmake similarity index 77% rename from Tests/RunCMake/file-CREATE_LINK/CREATE_LINK-COPY_ON_ERROR.cmake rename to Tests/RunCMake/file-CREATE_LINK/CREATE_LINK-COPY_ON_ERROR-file.cmake index 777ef4e6c4..e980ac00b3 100644 --- a/Tests/RunCMake/file-CREATE_LINK/CREATE_LINK-COPY_ON_ERROR.cmake +++ b/Tests/RunCMake/file-CREATE_LINK/CREATE_LINK-COPY_ON_ERROR-file.cmake @@ -1,6 +1,7 @@ # Use COPY_ON_ERROR to handle the case where the source and destination -# directory are on different devices. Cross-device links are not permitted +# file are on different devices. Cross-device links are not permitted # and the following command falls back to copying the file if link fails. +# Check only command result. file(CREATE_LINK ${CMAKE_CURRENT_LIST_FILE} TestCreateLink.cmake RESULT result diff --git a/Tests/RunCMake/file-CREATE_LINK/RunCMakeTest.cmake b/Tests/RunCMake/file-CREATE_LINK/RunCMakeTest.cmake index 9f79faec50..ed83312207 100644 --- a/Tests/RunCMake/file-CREATE_LINK/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-CREATE_LINK/RunCMakeTest.cmake @@ -1,7 +1,7 @@ include(RunCMake) run_cmake(CREATE_LINK) -run_cmake(CREATE_LINK-COPY_ON_ERROR) +run_cmake(CREATE_LINK-COPY_ON_ERROR-file) run_cmake(CREATE_LINK-noarg) run_cmake(CREATE_LINK-noexist) @@ -11,3 +11,34 @@ if(NOT WIN32 run_cmake(CREATE_LINK-SYMBOLIC) run_cmake(CREATE_LINK-SYMBOLIC-noexist) endif() + +file(MAKE_DIRECTORY ${RunCMake_BINARY_DIR}/CMP0205-Inspect/Dest) + +file(REMOVE_RECURSE ${RunCMake_BINARY_DIR}/CMP0205-Inspect-SymLink) +file(CREATE_LINK + ${RunCMake_BINARY_DIR}/CMP0205-Inspect/Dest ${RunCMake_BINARY_DIR}/CMP0205-Inspect-SymLink + SYMBOLIC + RESULT SymLink_RESULT +) +if(SymLink_RESULT STREQUAL "0") + message(STATUS "CMP0205-SymLink-* skipped: directory symbolic link creation works") + file(REMOVE ${RunCMake_BINARY_DIR}/CMP0205-Inspect-SymLink) +else() + run_cmake_script(CMP0205-SymLink-WARN) + run_cmake_script(CMP0205-SymLink-OLD) + run_cmake_script(CMP0205-SymLink-NEW) +endif() + +file(REMOVE_RECURSE ${RunCMake_BINARY_DIR}/CMP0205-Inspect-HardLink) +file(CREATE_LINK + ${RunCMake_BINARY_DIR}/CMP0205-Inspect/Dest ${RunCMake_BINARY_DIR}/CMP0205-Inspect-HardLink + RESULT HardLink_RESULT +) +if(HardLink_RESULT STREQUAL "0") + message(STATUS "CMP0205-HardLink-* skipped: directory hard link creation works") + file(REMOVE_RECURSE ${RunCMake_BINARY_DIR}/CMP0205-Inspect-HardLink) +else() + run_cmake_script(CMP0205-HardLink-WARN) + run_cmake_script(CMP0205-HardLink-OLD) + run_cmake_script(CMP0205-HardLink-NEW) +endif()