mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-09 23:59:53 -05:00
GenEx: add new expressions for string comparisons
This commit is contained in:
@@ -284,20 +284,8 @@ This section covers the primary and most widely used comparison types.
|
||||
Other more specific comparison types are documented in their own separate
|
||||
sections further below.
|
||||
|
||||
String Comparisons
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. genex:: $<STREQUAL:string1,string2>
|
||||
|
||||
``1`` if ``string1`` and ``string2`` are equal, else ``0``.
|
||||
The comparison is case-sensitive. For a case-insensitive comparison,
|
||||
combine with a :ref:`string transforming generator expression
|
||||
<String Transforming Generator Expressions>`. For example, the following
|
||||
evaluates to ``1`` if ``${foo}`` is any of ``BAR``, ``Bar``, ``bar``, etc.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
$<STREQUAL:$<UPPER_CASE:${foo}>,BAR>
|
||||
Numeric Comparisons
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. genex:: $<EQUAL:value1,value2>
|
||||
|
||||
@@ -330,10 +318,57 @@ Version Comparisons
|
||||
|
||||
``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``.
|
||||
|
||||
.. _`String Transforming Generator Expressions`:
|
||||
String Expressions
|
||||
------------------
|
||||
|
||||
.. _`String Comparisons Generator Expressions`:
|
||||
|
||||
String Comparisons
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The comparisons are case-sensitive. For a case-insensitive comparison,
|
||||
combine with a :ref:`string transforming generator expression
|
||||
<String Transforming Generator Expressions>`. For example, the following
|
||||
evaluates to ``1`` if ``${foo}`` is any of ``BAR``, ``Bar``, ``bar``, etc.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
$<STREQUAL:$<UPPER_CASE:${foo}>,BAR>
|
||||
|
||||
.. genex:: $<STREQUAL:string1,string2>
|
||||
|
||||
``1`` if ``string1`` and ``string2`` are lexicographically equal, else ``0``.
|
||||
|
||||
.. genex:: $<STRLESS:string1,string2>
|
||||
|
||||
.. versionadded:: 4.3
|
||||
|
||||
``1`` if ``string1`` is lexicographically less than ``string2``, else ``0``.
|
||||
|
||||
.. genex:: $<STRGREATER:string1,string2>
|
||||
|
||||
.. versionadded:: 4.3
|
||||
|
||||
``1`` if ``string1`` is lexicographically greater than ``string2``, else
|
||||
``0``.
|
||||
|
||||
.. genex:: $<STRLESS_EQUAL:string1,string2>
|
||||
|
||||
.. versionadded:: 4.3
|
||||
|
||||
``1`` if ``string1`` is lexicographically less than or equal to ``string2``,
|
||||
else ``0``.
|
||||
|
||||
.. genex:: $<STRGREATER_EQUAL:string1,string2>
|
||||
|
||||
.. versionadded:: 4.3
|
||||
|
||||
``1`` if ``string1`` is lexicographically greater than or equal to
|
||||
``string2``, else ``0``.
|
||||
|
||||
|
||||
String Transformations
|
||||
----------------------
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. genex:: $<LOWER_CASE:string>
|
||||
|
||||
@@ -343,7 +378,7 @@ String Transformations
|
||||
|
||||
Content of ``string`` converted to upper case.
|
||||
|
||||
.. genex:: $<MAKE_C_IDENTIFIER:...>
|
||||
.. genex:: $<MAKE_C_IDENTIFIER:string>
|
||||
|
||||
Content of ``...`` converted to a C identifier. The conversion follows the
|
||||
same behavior as :command:`string(MAKE_C_IDENTIFIER)`.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
GenEx-string-comparisons
|
||||
------------------------
|
||||
|
||||
* CMake gains new :ref:`generator expressions
|
||||
<String Comparisons Generator Expressions>` for string comparisons.
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "cmsys/String.h"
|
||||
|
||||
#include "cmCMakePath.h"
|
||||
#include "cmCMakeString.hxx"
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmGenExContext.h"
|
||||
#include "cmGenExEvaluation.h"
|
||||
@@ -265,9 +266,84 @@ static const struct StrEqualNode : public cmGeneratorExpressionNode
|
||||
GeneratorExpressionContent const* /*content*/,
|
||||
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
|
||||
{
|
||||
return parameters.front() == parameters[1] ? "1" : "0";
|
||||
return cm::CMakeString{ parameters.front() }.Compare(
|
||||
cm::CMakeString::CompOperator::EQUAL, parameters[1])
|
||||
? "1"
|
||||
: "0";
|
||||
}
|
||||
} strEqualNode;
|
||||
static const struct StrLessNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
StrLessNode() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
int NumExpectedParameters() const override { return 2; }
|
||||
|
||||
std::string Evaluate(
|
||||
std::vector<std::string> const& parameters,
|
||||
cm::GenEx::Evaluation* /*eval*/,
|
||||
GeneratorExpressionContent const* /*content*/,
|
||||
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
|
||||
{
|
||||
return cm::CMakeString{ parameters.front() }.Compare(
|
||||
cm::CMakeString::CompOperator::LESS, parameters[1])
|
||||
? "1"
|
||||
: "0";
|
||||
}
|
||||
} strLessNode;
|
||||
static const struct StrLessEqualNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
StrLessEqualNode() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
int NumExpectedParameters() const override { return 2; }
|
||||
|
||||
std::string Evaluate(
|
||||
std::vector<std::string> const& parameters,
|
||||
cm::GenEx::Evaluation* /*eval*/,
|
||||
GeneratorExpressionContent const* /*content*/,
|
||||
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
|
||||
{
|
||||
return cm::CMakeString{ parameters.front() }.Compare(
|
||||
cm::CMakeString::CompOperator::LESS_EQUAL, parameters[1])
|
||||
? "1"
|
||||
: "0";
|
||||
}
|
||||
} strLessEqualNode;
|
||||
static const struct StrGreaterNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
StrGreaterNode() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
int NumExpectedParameters() const override { return 2; }
|
||||
|
||||
std::string Evaluate(
|
||||
std::vector<std::string> const& parameters,
|
||||
cm::GenEx::Evaluation* /*eval*/,
|
||||
GeneratorExpressionContent const* /*content*/,
|
||||
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
|
||||
{
|
||||
return cm::CMakeString{ parameters.front() }.Compare(
|
||||
cm::CMakeString::CompOperator::GREATER, parameters[1])
|
||||
? "1"
|
||||
: "0";
|
||||
}
|
||||
} strGreaterNode;
|
||||
static const struct StrGreaterEqualNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
StrGreaterEqualNode() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
int NumExpectedParameters() const override { return 2; }
|
||||
|
||||
std::string Evaluate(
|
||||
std::vector<std::string> const& parameters,
|
||||
cm::GenEx::Evaluation* /*eval*/,
|
||||
GeneratorExpressionContent const* /*content*/,
|
||||
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
|
||||
{
|
||||
return cm::CMakeString{ parameters.front() }.Compare(
|
||||
cm::CMakeString::CompOperator::GREATER_EQUAL, parameters[1])
|
||||
? "1"
|
||||
: "0";
|
||||
}
|
||||
} strGreaterEqualNode;
|
||||
|
||||
static const struct EqualNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
@@ -4872,6 +4948,10 @@ cmGeneratorExpressionNode const* cmGeneratorExpressionNode::GetNode(
|
||||
{ "TARGET_BUNDLE_DIR_NAME", &targetBundleDirNameNode },
|
||||
{ "TARGET_BUNDLE_CONTENT_DIR", &targetBundleContentDirNode },
|
||||
{ "STREQUAL", &strEqualNode },
|
||||
{ "STRLESS", &strLessNode },
|
||||
{ "STRLESS_EQUAL", &strLessEqualNode },
|
||||
{ "STRGREATER", &strGreaterNode },
|
||||
{ "STRGREATER_EQUAL", &strGreaterEqualNode },
|
||||
{ "EQUAL", &equalNode },
|
||||
{ "IN_LIST", &inListNode },
|
||||
{ "FILTER", &filterNode },
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,40 @@
|
||||
CMake Error at BadStrGreater.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRGREATER>
|
||||
|
||||
\$<STRGREATER> expression requires 2 comma separated parameters, but got 0
|
||||
instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+CMake Error at BadStrGreater.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRGREATER:>
|
||||
|
||||
\$<STRGREATER> expression requires 2 comma separated parameters, but got 1
|
||||
instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+
|
||||
CMake Error at BadStrGreater.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRGREATER:,,>
|
||||
|
||||
\$<STRGREATER> expression requires 2 comma separated parameters, but got 3
|
||||
instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+
|
||||
CMake Error at BadStrGreater.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRGREATER:something,,>
|
||||
|
||||
\$<STRGREATER> expression requires 2 comma separated parameters, but got 3
|
||||
instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+
|
||||
CMake Generate step failed\. Build files cannot be regenerated correctly\.$
|
||||
@@ -0,0 +1,6 @@
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<STRGREATER>
|
||||
$<STRGREATER:>
|
||||
$<STRGREATER:,,>
|
||||
$<STRGREATER:something,,>
|
||||
VERBATIM)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,40 @@
|
||||
CMake Error at BadStrGreaterEqual.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRGREATER_EQUAL>
|
||||
|
||||
\$<STRGREATER_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 BadStrGreaterEqual.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRGREATER_EQUAL:>
|
||||
|
||||
\$<STRGREATER_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 BadStrGreaterEqual.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRGREATER_EQUAL:,,>
|
||||
|
||||
\$<STRGREATER_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 BadStrGreaterEqual.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRGREATER_EQUAL:something,,>
|
||||
|
||||
\$<STRGREATER_EQUAL> expression requires 2 comma separated parameters, but
|
||||
got 3 instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+
|
||||
CMake Generate step failed\. Build files cannot be regenerated correctly\.$
|
||||
@@ -0,0 +1,6 @@
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<STRGREATER_EQUAL>
|
||||
$<STRGREATER_EQUAL:>
|
||||
$<STRGREATER_EQUAL:,,>
|
||||
$<STRGREATER_EQUAL:something,,>
|
||||
VERBATIM)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,40 @@
|
||||
CMake Error at BadStrLess.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRLESS>
|
||||
|
||||
\$<STRLESS> expression requires 2 comma separated parameters, but got 0
|
||||
instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+CMake Error at BadStrLess.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRLESS:>
|
||||
|
||||
\$<STRLESS> expression requires 2 comma separated parameters, but got 1
|
||||
instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+
|
||||
CMake Error at BadStrLess.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRLESS:,,>
|
||||
|
||||
\$<STRLESS> expression requires 2 comma separated parameters, but got 3
|
||||
instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+
|
||||
CMake Error at BadStrLess.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRLESS:something,,>
|
||||
|
||||
\$<STRLESS> expression requires 2 comma separated parameters, but got 3
|
||||
instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+
|
||||
CMake Generate step failed\. Build files cannot be regenerated correctly\.$
|
||||
@@ -0,0 +1,6 @@
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<STRLESS>
|
||||
$<STRLESS:>
|
||||
$<STRLESS:,,>
|
||||
$<STRLESS:something,,>
|
||||
VERBATIM)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,40 @@
|
||||
CMake Error at BadStrLessEqual.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRLESS_EQUAL>
|
||||
|
||||
\$<STRLESS_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 BadStrLessEqual.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRLESS_EQUAL:>
|
||||
|
||||
\$<STRLESS_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 BadStrLessEqual.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRLESS_EQUAL:,,>
|
||||
|
||||
\$<STRLESS_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 BadStrLessEqual.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<STRLESS_EQUAL:something,,>
|
||||
|
||||
\$<STRLESS_EQUAL> expression requires 2 comma separated parameters, but got
|
||||
3 instead.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
+
|
||||
CMake Generate step failed\. Build files cannot be regenerated correctly\.$
|
||||
@@ -0,0 +1,6 @@
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<STRLESS_EQUAL>
|
||||
$<STRLESS_EQUAL:>
|
||||
$<STRLESS_EQUAL:,,>
|
||||
$<STRLESS_EQUAL:something,,>
|
||||
VERBATIM)
|
||||
@@ -7,6 +7,15 @@ run_cmake(BadOR)
|
||||
run_cmake(BadAND)
|
||||
run_cmake(BadNOT)
|
||||
run_cmake(BadStrEqual)
|
||||
run_cmake(BadStrLess)
|
||||
run_cmake(BadStrLessEqual)
|
||||
run_cmake(BadStrGreater)
|
||||
run_cmake(BadStrGreaterEqual)
|
||||
run_cmake(STREQUAL)
|
||||
run_cmake(STRLESS)
|
||||
run_cmake(STRLESS_EQUAL)
|
||||
run_cmake(STRGREATER)
|
||||
run_cmake(STRGREATER_EQUAL)
|
||||
run_cmake(BadZero)
|
||||
run_cmake(BadTargetName)
|
||||
run_cmake(BadTargetTypeInterface)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/STREQUAL-generated.txt" content)
|
||||
|
||||
set(expected "1:0")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "$<STREQUAL>: actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
||||
@@ -0,0 +1,3 @@
|
||||
cmake_policy(VERSION 4.2)
|
||||
|
||||
file(GENERATE OUTPUT "STREQUAL-generated.txt" CONTENT "$<STREQUAL:AA,AA>:$<STREQUAL:AA,BB>")
|
||||
@@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/STRGREATER-generated.txt" content)
|
||||
|
||||
set(expected "0:0:0:1")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "$<STRGREATER>: actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
||||
@@ -0,0 +1,3 @@
|
||||
cmake_policy(VERSION 4.2)
|
||||
|
||||
file(GENERATE OUTPUT "STRGREATER-generated.txt" CONTENT "$<STRGREATER:A,AA>:$<STRGREATER:AA,BB>:$<STRGREATER:AA,AA>:$<STRGREATER:BB,AA>")
|
||||
@@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/STRGREATER_EQUAL-generated.txt" content)
|
||||
|
||||
set(expected "0:0:1:1")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "$<STRGREATER_EQUAL>: actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
||||
@@ -0,0 +1,4 @@
|
||||
cmake_policy(VERSION 4.2)
|
||||
|
||||
file(GENERATE OUTPUT "STRGREATER_EQUAL-generated.txt"
|
||||
CONTENT "$<STRGREATER_EQUAL:A,AA>:$<STRGREATER_EQUAL:AA,BB>:$<STRGREATER_EQUAL:AA,AA>:$<STRGREATER_EQUAL:BB,AA>")
|
||||
@@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/STRLESS-generated.txt" content)
|
||||
|
||||
set(expected "1:1:0:0")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "$<STRLESS>: actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
||||
@@ -0,0 +1,3 @@
|
||||
cmake_policy(VERSION 4.2)
|
||||
|
||||
file(GENERATE OUTPUT "STRLESS-generated.txt" CONTENT "$<STRLESS:A,AA>:$<STRLESS:AA,BB>:$<STRLESS:AA,AA>:$<STRLESS:BB,AA>")
|
||||
@@ -0,0 +1,6 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/STRLESS_EQUAL-generated.txt" content)
|
||||
|
||||
set(expected "1:1:1:0")
|
||||
if(NOT content STREQUAL expected)
|
||||
set(RunCMake_TEST_FAILED "$<STRLESS_EQUAL>: actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
|
||||
endif()
|
||||
@@ -0,0 +1,4 @@
|
||||
cmake_policy(VERSION 4.2)
|
||||
|
||||
file(GENERATE OUTPUT "STRLESS_EQUAL-generated.txt"
|
||||
CONTENT "$<STRLESS_EQUAL:A,AA>:$<STRLESS_EQUAL:AA,BB>:$<STRLESS_EQUAL:AA,AA>:$<STRLESS_EQUAL:BB,AA>")
|
||||
Reference in New Issue
Block a user