Merge topic 'file-REAL_PATH-relative'

6b5f2dbbfe file(REAL_PATH): resolve symlinks before '..' components

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !8605
This commit is contained in:
Brad King 2023-07-24 12:43:15 +00:00 committed by Kitware Robot
commit 6194193a8a
17 changed files with 188 additions and 9 deletions

View File

@ -981,6 +981,11 @@ Path Conversion
if ``USERPROFILE`` is not defined. On all other platforms, only ``HOME``
is used.
.. versionchanged:: 3.28
All symlinks are resolved before collapsing ``../`` components.
See policy :policy:`CMP0152`.
.. signature::
file(RELATIVE_PATH <variable> <directory> <file>)

View File

@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
to determine whether to report an error on use of deprecated macros or
functions.
Policies Introduced by CMake 3.28
=================================
.. toctree::
:maxdepth: 1
CMP0152: file(REAL_PATH) resolves symlinks before collapsing ../ components. </policy/CMP0152>
Policies Introduced by CMake 3.27
=================================

20
Help/policy/CMP0152.rst Normal file
View File

@ -0,0 +1,20 @@
CMP0152
-------
.. versionadded:: 3.28
:command:`file(REAL_PATH)` resolves symlinks before collapsing ../ components.
In CMake 3.27 and below, :command:`file(REAL_PATH)` collapsed any ``../``
components in a path before resolving symlinks. This produced incorrect
results when the ``../`` collapsed away a symlink.
The ``OLD`` behavior for this policy is to collapse ``../`` components before
resolving symlinks.
The ``NEW`` behavior for this policy is to resolve all symlinks before
collapsing ``../`` components.
This policy was introduced in CMake version 3.28. Use the
:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
.. include:: DEPRECATED.txt

View File

@ -965,12 +965,15 @@ if(CUDAToolkit_FOUND)
# search paths without symlinks
if(CUDAToolkit_LIBRARY_DIR MATCHES ".*/cuda/${CUDAToolkit_VERSION_MAJOR}.${CUDAToolkit_VERSION_MINOR}/lib64$")
# Search location for math_libs/
file(REAL_PATH "${CUDAToolkit_LIBRARY_DIR}/../../../" _cmake_search_dir)
list(APPEND CUDAToolkit_LIBRARY_SEARCH_DIRS "${_cmake_search_dir}")
block(SCOPE_FOR POLICIES)
cmake_policy(SET CMP0152 NEW)
file(REAL_PATH "${CUDAToolkit_LIBRARY_DIR}/../../../../../" _cmake_search_dir)
list(APPEND CUDAToolkit_LIBRARY_SEARCH_DIRS "${_cmake_search_dir}")
# Search location for extras like cupti
file(REAL_PATH "${CUDAToolkit_LIBRARY_DIR}/../" _cmake_search_dir)
list(APPEND CUDAToolkit_LIBRARY_SEARCH_DIRS "${_cmake_search_dir}")
# Search location for extras like cupti
file(REAL_PATH "${CUDAToolkit_LIBRARY_DIR}/../../../" _cmake_search_dir)
list(APPEND CUDAToolkit_LIBRARY_SEARCH_DIRS "${_cmake_search_dir}")
endblock()
endif()
# If no `CUDAToolkit_LIBRARY_ROOT` exists set it based on CUDAToolkit_LIBRARY_DIR

View File

@ -30,6 +30,7 @@
#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmCMakePath.h"
#include "cmCryptoHash.h"
#include "cmELF.h"
#include "cmExecutionStatus.h"
@ -1278,9 +1279,58 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
}
}
auto realPath =
cmSystemTools::CollapseFullPath(input, *arguments.BaseDirectory);
realPath = cmSystemTools::GetRealPath(realPath);
bool warnAbout152 = false;
bool use152New = true;
cmPolicies::PolicyStatus policyStatus =
status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0152);
switch (policyStatus) {
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
break;
case cmPolicies::WARN:
use152New = false;
warnAbout152 = true;
break;
case cmPolicies::OLD:
use152New = false;
warnAbout152 = false;
break;
}
auto computeNewPath = [=](std::string const& in, std::string& result) {
auto path = cmCMakePath{ in };
if (path.IsRelative()) {
auto basePath = cmCMakePath{ *arguments.BaseDirectory };
path = basePath.Append(path);
}
result = cmSystemTools::GetActualCaseForPath(
cmSystemTools::GetRealPath(path.String()));
};
std::string realPath;
if (use152New) {
computeNewPath(input, realPath);
} else {
std::string oldPolicyPath =
cmSystemTools::CollapseFullPath(input, *arguments.BaseDirectory);
oldPolicyPath = cmSystemTools::GetRealPath(oldPolicyPath);
if (warnAbout152) {
computeNewPath(input, realPath);
if (oldPolicyPath != realPath) {
status.GetMakefile().IssueMessage(
MessageType::AUTHOR_WARNING,
cmStrCat(
cmPolicies::GetPolicyWarning(cmPolicies::CMP0152), '\n',
"From input path:\n ", input,
"\nthe policy OLD behavior produces path:\n ", oldPolicyPath,
"\nbut the policy NEW behavior produces path:\n ", realPath,
"\nSince the policy is not set, CMake is using the OLD "
"behavior for compatibility."));
}
}
realPath = oldPolicyPath;
}
status.GetMakefile().AddDefinition(args[2], realPath);

View File

@ -459,7 +459,11 @@ class cmMakefile;
SELECT(POLICY, CMP0151, \
"AUTOMOC include directory is a system include directory by " \
"default.", \
3, 27, 0, cmPolicies::WARN)
3, 27, 0, cmPolicies::WARN) \
SELECT( \
POLICY, CMP0152, \
"file(REAL_PATH) resolves symlinks before collapsing ../ components.", 3, \
28, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \

View File

@ -0,0 +1,5 @@
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dir/")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin/")
file(CREATE_LINK "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin" "${CMAKE_CURRENT_BINARY_DIR}/dir/bin" SYMBOLIC)
file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/dir/bin/../" real_path)

View File

@ -0,0 +1,2 @@
cmake_policy(SET CMP0152 NEW)
include(CMP0152-Common.cmake)

View File

@ -0,0 +1,2 @@
cmake_policy(SET CMP0152 OLD)
include(CMP0152-Common.cmake)

View File

@ -0,0 +1,27 @@
^CMake Warning \(dev\) at CMP0152-Common\.cmake:[0-9]+ \(file\):
Policy CMP0152 is not set: file\(REAL_PATH\) resolves symlinks before
collapsing \.\./ components\. Run "cmake --help-policy CMP0152" for policy
details\. Use the cmake_policy command to set the policy and suppress this
warning\.
From input path:
[^
]*/Tests/RunCMake/CMP0152/CMP0152-WARN-build/dir/bin/\.\./
the policy OLD behavior produces path:
[^
]*/Tests/RunCMake/CMP0152/CMP0152-WARN-build/dir
but the policy NEW behavior produces path:
[^
]*/Tests/RunCMake/CMP0152/CMP0152-WARN-build/dir/nested
Since the policy is not set, CMake is using the OLD behavior for
compatibility.
Call Stack \(most recent call first\):
CMP0152-WARN\.cmake:[0-9]+ \(include\)
CMakeLists.txt:[0-9]+ \(include\)
This warning is for project developers\. Use -Wno-dev to suppress it\.$

View File

@ -0,0 +1,2 @@
include(CMP0152-Common.cmake)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.23)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,7 @@
include(RunCMake)
if(NOT CMAKE_GENERATOR_NO_COMPILER_ENV)
run_cmake(CMP0152-WARN)
run_cmake(CMP0152-OLD)
run_cmake(CMP0152-NEW)
endif()

View File

@ -165,6 +165,10 @@ if(GIT_EXECUTABLE)
add_RunCMake_test(CMP0150)
endif()
if(NOT WIN32 OR CYGWIN)
add_RunCMake_test(CMP0152)
endif()
# The test for Policy 65 requires the use of the
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
# generators ignore. The policy will have no effect on those generators.

View File

@ -13,6 +13,43 @@ if (NOT WIN32 OR CYGWIN)
if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt")
message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"")
endif()
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dir/")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin/")
file(CREATE_LINK "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin" "${CMAKE_CURRENT_BINARY_DIR}/dir/bin" SYMBOLIC)
cmake_policy(SET CMP0152 NEW)
file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/dir/bin/../" real_path)
if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/dir/nested")
message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/dir/nested\"")
endif()
file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/dir/bin/../bin" real_path)
if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin")
message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin\"")
endif()
file(REAL_PATH "dir/bin/../bin" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin")
message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin\"")
endif()
file(REAL_PATH "../bin" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dir/bin/" )
if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin")
message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/dir/nested/bin\"")
endif()
cmake_policy(SET CMP0152 OLD)
file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/dir/bin/../" real_path)
if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/dir")
message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/dir/nested\"")
endif()
file(REAL_PATH "../" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dir/bin/")
if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/dir")
message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/dir\"")
endif()
endif()