From be4b9e10afaae750ad184ce1b34d6cb2c3d7fd33 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Fri, 3 Jun 2022 12:42:41 +0200 Subject: if command: Add PATH_EQUAL operator --- Help/command/if.rst | 30 +++++++++++++++++++++++++- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0139.rst | 17 +++++++++++++++ Help/release/dev/if-PATH_EQUAL.rst | 5 +++++ Source/cmConditionEvaluator.cxx | 26 ++++++++++++++++++++++ Source/cmConditionEvaluator.h | 1 + Source/cmPolicies.h | 6 +++++- Tests/RunCMake/CMP0139/CMP0139-NEW.cmake | 25 +++++++++++++++++++++ Tests/RunCMake/CMP0139/CMP0139-OLD-result.txt | 1 + Tests/RunCMake/CMP0139/CMP0139-OLD-stderr.txt | 8 +++++++ Tests/RunCMake/CMP0139/CMP0139-OLD.cmake | 5 +++++ Tests/RunCMake/CMP0139/CMP0139-WARN-result.txt | 1 + Tests/RunCMake/CMP0139/CMP0139-WARN-stderr.txt | 19 ++++++++++++++++ Tests/RunCMake/CMP0139/CMP0139-WARN.cmake | 4 ++++ Tests/RunCMake/CMP0139/CMakeLists.txt | 3 +++ Tests/RunCMake/CMP0139/RunCMakeTest.cmake | 5 +++++ Tests/RunCMake/CMakeLists.txt | 1 + 17 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 Help/policy/CMP0139.rst create mode 100644 Help/release/dev/if-PATH_EQUAL.rst create mode 100644 Tests/RunCMake/CMP0139/CMP0139-NEW.cmake create mode 100644 Tests/RunCMake/CMP0139/CMP0139-OLD-result.txt create mode 100644 Tests/RunCMake/CMP0139/CMP0139-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0139/CMP0139-OLD.cmake create mode 100644 Tests/RunCMake/CMP0139/CMP0139-WARN-result.txt create mode 100644 Tests/RunCMake/CMP0139/CMP0139-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0139/CMP0139-WARN.cmake create mode 100644 Tests/RunCMake/CMP0139/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0139/RunCMakeTest.cmake 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( PATH_EQUAL )`` + .. 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) ` 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. CMP0138: MSVC compilers use -ZI instead of /Zi for x86 and x64 by default. CMP0137: try_compile() passes platform variables in project mode. CMP0136: Watcom runtime library flags are selected by an abstraction. 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 -- cgit v0.12