summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2022-06-03 10:42:41 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2022-06-03 17:31:36 (GMT)
commitbe4b9e10afaae750ad184ce1b34d6cb2c3d7fd33 (patch)
tree1c88a4586bb77f93be8e9bf1ddd43cbcad1f4bbe
parent0aa0b8e146ea8d1dc50b4c045360abd57c3643e4 (diff)
downloadCMake-be4b9e10afaae750ad184ce1b34d6cb2c3d7fd33.zip
CMake-be4b9e10afaae750ad184ce1b34d6cb2c3d7fd33.tar.gz
CMake-be4b9e10afaae750ad184ce1b34d6cb2c3d7fd33.tar.bz2
if command: Add PATH_EQUAL operator
-rw-r--r--Help/command/if.rst30
-rw-r--r--Help/manual/cmake-policies.7.rst1
-rw-r--r--Help/policy/CMP0139.rst17
-rw-r--r--Help/release/dev/if-PATH_EQUAL.rst5
-rw-r--r--Source/cmConditionEvaluator.cxx26
-rw-r--r--Source/cmConditionEvaluator.h1
-rw-r--r--Source/cmPolicies.h6
-rw-r--r--Tests/RunCMake/CMP0139/CMP0139-NEW.cmake25
-rw-r--r--Tests/RunCMake/CMP0139/CMP0139-OLD-result.txt1
-rw-r--r--Tests/RunCMake/CMP0139/CMP0139-OLD-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0139/CMP0139-OLD.cmake5
-rw-r--r--Tests/RunCMake/CMP0139/CMP0139-WARN-result.txt1
-rw-r--r--Tests/RunCMake/CMP0139/CMP0139-WARN-stderr.txt19
-rw-r--r--Tests/RunCMake/CMP0139/CMP0139-WARN.cmake4
-rw-r--r--Tests/RunCMake/CMP0139/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0139/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
17 files changed, 156 insertions, 2 deletions
diff --git a/Help/command/if.rst b/Help/command/if.rst
index 64f1c35..c096725 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -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
^^^^^^^^^^^^^^^^^^
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index a7741f7..1447c17 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -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>
diff --git a/Help/policy/CMP0139.rst b/Help/policy/CMP0139.rst
new file mode 100644
index 0000000..5a0f4f7
--- /dev/null
+++ b/Help/policy/CMP0139.rst
@@ -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
diff --git a/Help/release/dev/if-PATH_EQUAL.rst b/Help/release/dev/if-PATH_EQUAL.rst
new file mode 100644
index 0000000..45f02e8
--- /dev/null
+++ b/Help/release/dev/if-PATH_EQUAL.rst
@@ -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`.
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 141c4eb..5de012a 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -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;
}
diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h
index 37b7825..9486b16 100644
--- a/Source/cmConditionEvaluator.h
+++ b/Source/cmConditionEvaluator.h
@@ -79,4 +79,5 @@ private:
cmPolicies::PolicyStatus Policy54Status;
cmPolicies::PolicyStatus Policy57Status;
cmPolicies::PolicyStatus Policy64Status;
+ cmPolicies::PolicyStatus Policy139Status;
};
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index f13432b..256d483 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -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) \
diff --git a/Tests/RunCMake/CMP0139/CMP0139-NEW.cmake b/Tests/RunCMake/CMP0139/CMP0139-NEW.cmake
new file mode 100644
index 0000000..8144696
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/CMP0139-NEW.cmake
@@ -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()
diff --git a/Tests/RunCMake/CMP0139/CMP0139-OLD-result.txt b/Tests/RunCMake/CMP0139/CMP0139-OLD-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/CMP0139-OLD-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0139/CMP0139-OLD-stderr.txt b/Tests/RunCMake/CMP0139/CMP0139-OLD-stderr.txt
new file mode 100644
index 0000000..1cfb319
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/CMP0139-OLD-stderr.txt
@@ -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\)
diff --git a/Tests/RunCMake/CMP0139/CMP0139-OLD.cmake b/Tests/RunCMake/CMP0139/CMP0139-OLD.cmake
new file mode 100644
index 0000000..e813a47
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/CMP0139-OLD.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0139 OLD)
+
+if("/path1" PATH_EQUAL "/path2")
+ message("PATH_EQUAL recognized")
+endif()
diff --git a/Tests/RunCMake/CMP0139/CMP0139-WARN-result.txt b/Tests/RunCMake/CMP0139/CMP0139-WARN-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/CMP0139-WARN-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0139/CMP0139-WARN-stderr.txt b/Tests/RunCMake/CMP0139/CMP0139-WARN-stderr.txt
new file mode 100644
index 0000000..6a873ca
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/CMP0139-WARN-stderr.txt
@@ -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\)
diff --git a/Tests/RunCMake/CMP0139/CMP0139-WARN.cmake b/Tests/RunCMake/CMP0139/CMP0139-WARN.cmake
new file mode 100644
index 0000000..d74753e
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/CMP0139-WARN.cmake
@@ -0,0 +1,4 @@
+
+if("/path1" PATH_EQUAL "/path2")
+ message("PATH_EQUAL recognized")
+endif()
diff --git a/Tests/RunCMake/CMP0139/CMakeLists.txt b/Tests/RunCMake/CMP0139/CMakeLists.txt
new file mode 100644
index 0000000..18dfd26
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.2)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0139/RunCMakeTest.cmake b/Tests/RunCMake/CMP0139/RunCMakeTest.cmake
new file mode 100644
index 0000000..2dbea3c
--- /dev/null
+++ b/Tests/RunCMake/CMP0139/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0139-OLD)
+run_cmake(CMP0139-WARN)
+run_cmake(CMP0139-NEW)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 3ca01ec..7e17450 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -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