if command: Add PATH_EQUAL operator

This commit is contained in:
Marc Chevrier
2022-06-03 12:42:41 +02:00
parent 0aa0b8e146
commit be4b9e10af
17 changed files with 156 additions and 2 deletions

View File

@@ -47,7 +47,7 @@ Compound conditions are evaluated in the following order of precedence:
`GREATER_EQUAL`_, `STREQUAL`_, `STRLESS`_, `STRLESS_EQUAL`_,
`STRGREATER`_, `STRGREATER_EQUAL`_, `VERSION_EQUAL`_, `VERSION_LESS`_,
`VERSION_LESS_EQUAL`_, `VERSION_GREATER`_, `VERSION_GREATER_EQUAL`_,
and `MATCHES`_.
`PATH_EQUAL`_, and `MATCHES`_.
4. Unary logical operator `NOT`_.
@@ -314,6 +314,34 @@ Version Comparisons
Any non-integer version component or non-integer trailing part of a version
component effectively truncates the string at that point.
Path Comparisons
""""""""""""""""
.. _PATH_EQUAL:
``if(<variable|string> PATH_EQUAL <variable|string>)``
.. versionadded:: 3.24
Compares the lexical representations of two paths provided as string
literals or variables. No normalization is performed on either path.
Lexical comparison has the advantage over string comparison to have a
knowledge of the structure of the path. So, the following comparison is
``TRUE`` using ``PATH_EQUAL`` operator, but ``FALSE`` with ``STREQUAL``:
.. code-block:: cmake
# comparison is TRUE
if ("/a//b/c" PATH_EQUAL "/a/b/c")
...
endif()
# comparison is FALSE
if ("/a//b/c" STREQUAL "/a/b/c")
...
endif()
See :ref:`cmake_path(COMPARE) <Path COMPARE>` for more details.
Variable Expansion
^^^^^^^^^^^^^^^^^^

View File

@@ -58,6 +58,7 @@ Policies Introduced by CMake 3.24
.. toctree::
:maxdepth: 1
CMP0139: The if() command supports path comparisons using PATH_EQUAL operator. </policy/CMP0139>
CMP0138: MSVC compilers use -ZI instead of /Zi for x86 and x64 by default. </policy/CMP0138>
CMP0137: try_compile() passes platform variables in project mode. </policy/CMP0137>
CMP0136: Watcom runtime library flags are selected by an abstraction. </policy/CMP0136>

17
Help/policy/CMP0139.rst Normal file
View File

@@ -0,0 +1,17 @@
CMP0139
-------
.. versionadded:: 3.24
The :command:`if` command supports path comparisons using ``PATH_EQUAL``
operator.
The ``OLD`` behavior for this policy is to ignore the ``PATH_EQUAL`` operator.
The ``NEW`` behavior is to interpret the ``PATH_EQUAL`` operator.
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

View File

@@ -0,0 +1,5 @@
if-PATH_EQUAL
-------------
* The :command:`if` command gains the capability to compare paths by using the
``PATH_EQUAL`` operator. See policy :policy:`CMP0139`.

View File

@@ -16,6 +16,7 @@
#include "cmsys/RegularExpression.hxx"
#include "cmCMakePath.h"
#include "cmExpandedCommandArgument.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -58,6 +59,7 @@ auto const keyVERSION_GREATER = "VERSION_GREATER"_s;
auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s;
auto const keyVERSION_LESS = "VERSION_LESS"_s;
auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s;
auto const keyPATH_EQUAL = "PATH_EQUAL"_s;
cmSystemTools::CompareOp const MATCH2CMPOP[5] = {
cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL,
@@ -217,6 +219,7 @@ cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile,
, Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054))
, Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057))
, Policy64Status(makefile.GetPolicyStatus(cmPolicies::CMP0064))
, Policy139Status(makefile.GetPolicyStatus(cmPolicies::CMP0139))
{
}
@@ -775,6 +778,29 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
}
else if (this->IsKeyword(keyPATH_EQUAL, *args.next)) {
if (this->Policy139Status != cmPolicies::OLD &&
this->Policy139Status != cmPolicies::WARN) {
cmValue lhs = this->GetVariableOrString(*args.current);
cmValue rhs = this->GetVariableOrString(*args.nextnext);
const auto result = cmCMakePath{ *lhs } == cmCMakePath{ *rhs };
newArgs.ReduceTwoArgs(result, args);
}
else if (this->Policy139Status == cmPolicies::WARN) {
std::ostringstream e;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0139)
<< "\n"
"PATH_EQUAL will be interpreted as an operator "
"when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
}
}
return true;
}

View File

@@ -79,4 +79,5 @@ private:
cmPolicies::PolicyStatus Policy54Status;
cmPolicies::PolicyStatus Policy57Status;
cmPolicies::PolicyStatus Policy64Status;
cmPolicies::PolicyStatus Policy139Status;
};

View File

@@ -417,7 +417,11 @@ class cmMakefile;
cmPolicies::WARN) \
SELECT(POLICY, CMP0138, \
"MSVC compilers use -ZI instead of /Zi for x86 and x64 by default.", \
3, 24, 0, cmPolicies::WARN)
3, 24, 0, cmPolicies::WARN) \
SELECT( \
POLICY, CMP0139, \
"The if() command supports path comparisons using PATH_EQUAL operator.", \
3, 24, 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,25 @@
cmake_policy(SET CMP0139 NEW)
set(path "a///b/c")
if (NOT path PATH_EQUAL "a/b/c")
message(SEND_ERROR "if(PATH_EQUAL): '${path}' not equal to 'a/b/c'")
endif()
set(path2 "a/b/c")
if (NOT path PATH_EQUAL path2)
message(SEND_ERROR "if(PATH_EQUAL): '${path}' not equal to '${path2}'")
endif()
set (path "a/b/d/../c")
if (path PATH_EQUAL "a/b/c")
message(SEND_ERROR "if(PATH_EQUAL): '${path}' equal to 'a/b/c'")
endif()
set(path2 "a/b/c")
if ("a/b/d/../c" PATH_EQUAL path2)
message(SEND_ERROR "if(PATH_EQUAL): 'a/b/d/../c' equal to '${path2}'")
endif()
cmake_path(NORMAL_PATH path)
if (NOT path PATH_EQUAL "a/b/c")
message(SEND_ERROR "if(PATH_EQUAL): '${path}' not equal to 'a/b/c'")
endif()

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,8 @@
CMake Error at CMP0139-OLD.cmake:[0-9]+ \(if\):
if given arguments:
"/path1" "PATH_EQUAL" "/path2"
Unknown arguments specified
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1,5 @@
cmake_policy(SET CMP0139 OLD)
if("/path1" PATH_EQUAL "/path2")
message("PATH_EQUAL recognized")
endif()

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,19 @@
CMake Warning \(dev\) at CMP0139-WARN.cmake:[0-9]+ \(if\):
Policy CMP0139 is not set: The if\(\) command supports path comparisons using
PATH_EQUAL operator. Run "cmake --help-policy CMP0139" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
PATH_EQUAL will be interpreted as an operator when the policy is set to
NEW. Since the policy is not set the OLD behavior will be used.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Error at CMP0139-WARN.cmake:[0-9]+ \(if\):
if given arguments:
"/path1" "PATH_EQUAL" "/path2"
Unknown arguments specified
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1,4 @@
if("/path1" PATH_EQUAL "/path2")
message("PATH_EQUAL recognized")
endif()

View File

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

View File

@@ -0,0 +1,5 @@
include(RunCMake)
run_cmake(CMP0139-OLD)
run_cmake(CMP0139-WARN)
run_cmake(CMP0139-NEW)

View File

@@ -150,6 +150,7 @@ endif()
add_RunCMake_test(CMP0132)
add_RunCMake_test(CMP0135)
add_RunCMake_test(CMP0139)
# The test for Policy 65 requires the use of the
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode