Browse Source

Genex-PATH_EQUAL: path comparison

To complete issue #23498
Marc Chevrier 3 years ago
parent
commit
4d1883df11

+ 1 - 0
Help/command/cmake_path.rst

@@ -473,6 +473,7 @@ are :ref:`normalized <Normalization>` before the check.
   set(path "/a/b")
   set(path "/a/b")
   cmake_path(IS_PREFIX path "/a/c/../b" NORMALIZE result)   # result = true
   cmake_path(IS_PREFIX path "/a/c/../b" NORMALIZE result)   # result = true
 
 
+.. _Path COMPARE:
 .. _COMPARE:
 .. _COMPARE:
 
 
 ::
 ::

+ 13 - 0
Help/manual/cmake-generator-expressions.7.rst

@@ -123,6 +123,19 @@ String Comparisons
 
 
   ``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``.
   ``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``.
 
 
+Path Comparisons
+----------------
+
+.. genex:: $<PATH_EQUAL:path1,path2>
+
+  .. versionadded:: 3.24
+
+  Compares the lexical representations of two paths. No normalization is
+  performed on either path. Returns ``1`` if the paths are equal, ``0``
+  otherwise.
+
+  See :ref:`cmake_path(COMPARE) <Path COMPARE>` for more details.
+
 .. _GenEx Path Queries:
 .. _GenEx Path Queries:
 
 
 Path Queries
 Path Queries

+ 5 - 0
Help/release/dev/Genex-PATH_EQUAL.rst

@@ -0,0 +1,5 @@
+Genex-PATH_EQUAL
+----------------
+
+* The :genex:`PATH_EQUAL` generator expression was added to manage path
+  comparisons.

+ 18 - 0
Source/cmGeneratorExpressionNode.cxx

@@ -1034,6 +1034,23 @@ static const struct PathNode : public cmGeneratorExpressionNode
   }
   }
 } pathNode;
 } pathNode;
 
 
+static const struct PathEqualNode : public cmGeneratorExpressionNode
+{
+  PathEqualNode() {} // NOLINT(modernize-use-equals-default)
+
+  int NumExpectedParameters() const override { return 2; }
+
+  std::string Evaluate(
+    const std::vector<std::string>& parameters,
+    cmGeneratorExpressionContext* /*context*/,
+    const GeneratorExpressionContent* /*content*/,
+    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+  {
+    return cmCMakePath{ parameters[0] } == cmCMakePath{ parameters[1] } ? "1"
+                                                                        : "0";
+  }
+} pathEqualNode;
+
 static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
 static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
 {
 {
   MakeCIdentifierNode() {} // NOLINT(modernize-use-equals-default)
   MakeCIdentifierNode() {} // NOLINT(modernize-use-equals-default)
@@ -3265,6 +3282,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
     { "LOWER_CASE", &lowerCaseNode },
     { "LOWER_CASE", &lowerCaseNode },
     { "UPPER_CASE", &upperCaseNode },
     { "UPPER_CASE", &upperCaseNode },
     { "PATH", &pathNode },
     { "PATH", &pathNode },
+    { "PATH_EQUAL", &pathEqualNode },
     { "MAKE_C_IDENTIFIER", &makeCIdentifierNode },
     { "MAKE_C_IDENTIFIER", &makeCIdentifierNode },
     { "BOOL", &boolNode },
     { "BOOL", &boolNode },
     { "IF", &ifNode },
     { "IF", &ifNode },

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -331,6 +331,7 @@ add_RunCMake_test(GenEx-TARGET_FILE -DLINKER_SUPPORTS_PDB=${LINKER_SUPPORTS_PDB}
 add_RunCMake_test(GenEx-GENEX_EVAL)
 add_RunCMake_test(GenEx-GENEX_EVAL)
 add_RunCMake_test(GenEx-TARGET_RUNTIME_DLLS)
 add_RunCMake_test(GenEx-TARGET_RUNTIME_DLLS)
 add_RunCMake_test(GenEx-PATH)
 add_RunCMake_test(GenEx-PATH)
+add_RunCMake_test(GenEx-PATH_EQUAL)
 add_RunCMake_test(GeneratorExpression)
 add_RunCMake_test(GeneratorExpression)
 add_RunCMake_test(GeneratorInstance)
 add_RunCMake_test(GeneratorInstance)
 add_RunCMake_test(GeneratorPlatform)
 add_RunCMake_test(GeneratorPlatform)

+ 5 - 0
Tests/RunCMake/GenEx-PATH_EQUAL/CMakeLists.txt

@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.18...3.24)
+
+project(${RunCMake_TEST} NONE)
+
+include(${RunCMake_TEST}.cmake)

+ 8 - 0
Tests/RunCMake/GenEx-PATH_EQUAL/PATH_EQUAL.cmake.in

@@ -0,0 +1,8 @@
+
+include ("${RunCMake_SOURCE_DIR}/check_errors.cmake")
+
+expect_true("$<PATH_EQUAL:a///b/c,a/b/c>" "a///b/c" "a/b/c")
+
+expect_false("$<PATH_EQUAL:a/b/d/../c,a/b/c>" "a/b/d/../c" "a/b/c")
+
+expect_true("$<PATH_EQUAL:$<PATH:NORMAL_PATH,a/b/d/../c>,a/b/c>" "a/b/d/../c" "a/b/c")

+ 14 - 0
Tests/RunCMake/GenEx-PATH_EQUAL/RunCMakeTest.cmake

@@ -0,0 +1,14 @@
+
+include(RunCMake)
+
+run_cmake(WrongArguments)
+
+function(check_path_execution name)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_VARIANT_DESCRIPTION " - ${name}")
+  run_cmake_with_options(generate -DPATH_TEST=${name})
+  run_cmake_command(check "${CMAKE_COMMAND}" "-DRunCMake_SOURCE_DIR=${RunCMake_SOURCE_DIR}" -P "${RunCMake_TEST_BINARY_DIR}/${name}.cmake")
+endfunction()
+
+check_path_execution (PATH_EQUAL)

+ 1 - 0
Tests/RunCMake/GenEx-PATH_EQUAL/WrongArguments-result.txt

@@ -0,0 +1 @@
+1

+ 42 - 0
Tests/RunCMake/GenEx-PATH_EQUAL/WrongArguments-stderr.txt

@@ -0,0 +1,42 @@
+CMake Error at WrongArguments.cmake:[0-9]+ \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<PATH_EQUAL>
+
+  \$<PATH_EQUAL> expression requires 2 comma separated parameters, but got 0
+  instead.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+CMake Error at WrongArguments.cmake:[0-9]+ \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<PATH_EQUAL:>
+
+  \$<PATH_EQUAL> expression requires 2 comma separated parameters, but got 1
+  instead.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+CMake Error at WrongArguments.cmake:2 \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<PATH_EQUAL:,,>
+
+  \$<PATH_EQUAL> expression requires 2 comma separated parameters, but got 3
+  instead.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+CMake Error at WrongArguments.cmake:[0-9]+ \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<PATH_EQUAL:something,,>
+
+  \$<PATH_EQUAL> expression requires 2 comma separated parameters, but got 3
+  instead.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 7 - 0
Tests/RunCMake/GenEx-PATH_EQUAL/WrongArguments.cmake

@@ -0,0 +1,7 @@
+
+add_custom_target(check ALL COMMAND check
+  $<PATH_EQUAL>
+  $<PATH_EQUAL:>
+  $<PATH_EQUAL:,,>
+  $<PATH_EQUAL:something,,>
+  VERBATIM)

+ 12 - 0
Tests/RunCMake/GenEx-PATH_EQUAL/check_errors.cmake

@@ -0,0 +1,12 @@
+
+function(EXPECT_TRUE output data reference)
+  if (NOT output)
+    message(SEND_ERROR "'${data}' not equal to '${reference}'")
+  endif()
+endfunction()
+
+function(EXPECT_FALSE output data reference)
+  if (output)
+    message(SEND_ERROR "'${data}' equal to '${reference}'")
+  endif()
+endfunction()

+ 2 - 0
Tests/RunCMake/GenEx-PATH_EQUAL/generate.cmake

@@ -0,0 +1,2 @@
+
+file(GENERATE OUTPUT "${PATH_TEST}.cmake" INPUT "${PATH_TEST}.cmake.in")