From 895f7f16a79428689a263ba5cd9a72647dc8e912 Mon Sep 17 00:00:00 2001 From: Colby Pike Date: Mon, 23 Jan 2017 20:14:03 -0700 Subject: Genex: Add `IF` generator expression This allows a single condition to be used to choose between two alternatives. Without this the condition must be duplicated with one surrounded by `NOT`. Closes: #15585 --- Help/manual/cmake-generator-expressions.7.rst | 2 ++ Help/release/dev/if-genex.rst | 7 +++++++ Source/cmGeneratorExpressionNode.cxx | 22 ++++++++++++++++++++++ Tests/GeneratorExpression/CMakeLists.txt | 4 ++++ Tests/GeneratorExpression/check-part4.cmake | 5 +++++ .../RunCMake/GeneratorExpression/BadIF-result.txt | 1 + .../RunCMake/GeneratorExpression/BadIF-stderr.txt | 15 +++++++++++++++ Tests/RunCMake/GeneratorExpression/BadIF.cmake | 5 +++++ .../GeneratorExpression/RunCMakeTest.cmake | 1 + 9 files changed, 62 insertions(+) create mode 100644 Help/release/dev/if-genex.rst create mode 100644 Tests/RunCMake/GeneratorExpression/BadIF-result.txt create mode 100644 Tests/RunCMake/GeneratorExpression/BadIF-stderr.txt create mode 100644 Tests/RunCMake/GeneratorExpression/BadIF.cmake diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 64d15a9..3a225ad 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -51,6 +51,8 @@ Available logical expressions are: ``0`` if all ``?`` are ``0``, else ``1`` ``$`` ``0`` if ``?`` is ``1``, else ``1`` +``$``` + ``true-value...`` if ``?`` is ``1``, ``false-value...`` if ``?`` is ``0`` ``$`` ``1`` if ``a`` is STREQUAL ``b``, else ``0`` ``$`` diff --git a/Help/release/dev/if-genex.rst b/Help/release/dev/if-genex.rst new file mode 100644 index 0000000..62be3a7 --- /dev/null +++ b/Help/release/dev/if-genex.rst @@ -0,0 +1,7 @@ +genex-if +-------- + +* A new logical generator expression for immediate-if was added: + ``$``. It takes three arguments: One + condition, a true-value, and a false-value. Resolves to the true-value if the + condition is ``1``, and resolves to the false-value if the condition is ``0``. diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 398f95b..66202df 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -162,6 +162,27 @@ static const struct BoolNode : public cmGeneratorExpressionNode } } boolNode; +static const struct IfNode : public cmGeneratorExpressionNode +{ + IfNode() {} + + int NumExpectedParameters() const CM_OVERRIDE { return 3; } + + std::string Evaluate(const std::vector& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker*) const CM_OVERRIDE + { + if (parameters[0] != "1" && parameters[0] != "0") { + reportError(context, content->GetOriginalExpression(), + "First parameter to $ must resolve to exactly one '0' " + "or '1' value."); + return std::string(); + } + return parameters[0] == "1" ? parameters[1] : parameters[2]; + } +} ifNode; + static const struct StrEqualNode : public cmGeneratorExpressionNode { StrEqualNode() {} @@ -1757,6 +1778,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["UPPER_CASE"] = &upperCaseNode; nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode; nodeMap["BOOL"] = &boolNode; + nodeMap["IF"] = &ifNode; nodeMap["ANGLE-R"] = &angle_rNode; nodeMap["COMMA"] = &commaNode; nodeMap["SEMICOLON"] = &semicolonNode; diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index f0d6abf..f920188 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -246,6 +246,10 @@ add_custom_target(check-part4 ALL # CMake as command-line argument -Dtest_shell_path=${path_prefix}$ -Dpath_prefix=${path_prefix} + -Dif_1=$ + -Dif_2=$ + -Dif_3=$,a,b> + -Dif_4=$,a,b> -DWIN32=${WIN32} -DCMAKE_GENERATOR=${CMAKE_GENERATOR} -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part4.cmake diff --git a/Tests/GeneratorExpression/check-part4.cmake b/Tests/GeneratorExpression/check-part4.cmake index 9e516d5..f5d14dd 100644 --- a/Tests/GeneratorExpression/check-part4.cmake +++ b/Tests/GeneratorExpression/check-part4.cmake @@ -13,3 +13,8 @@ if(WIN32) else() check(test_shell_path [[/shell/path]]) endif() + +check(if_1 "a") +check(if_2 "b") +check(if_3 "b") +check(if_4 "a") diff --git a/Tests/RunCMake/GeneratorExpression/BadIF-result.txt b/Tests/RunCMake/GeneratorExpression/BadIF-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadIF-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/BadIF-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadIF-stderr.txt new file mode 100644 index 0000000..7c7506c --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadIF-stderr.txt @@ -0,0 +1,15 @@ +CMake Error at BadIF.cmake:2 \(add_custom_target\): + Error evaluating generator expression: + + \$ + + First parameter to \$ must resolve to exactly one '0' or '1' value. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Error at BadIF.cmake:2 \(add_custom_target\): + Error evaluating generator expression: + + \$ + + \$ expression requires 3 comma separated parameters, but got 2 instead. diff --git a/Tests/RunCMake/GeneratorExpression/BadIF.cmake b/Tests/RunCMake/GeneratorExpression/BadIF.cmake new file mode 100644 index 0000000..583f68d --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadIF.cmake @@ -0,0 +1,5 @@ + +add_custom_target(check ALL COMMAND check + $ + $ + ) diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake index f5584d5..084b5c3 100644 --- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake @@ -1,5 +1,6 @@ include(RunCMake) +run_cmake(BadIF) run_cmake(BadCONFIG) run_cmake(BadOR) run_cmake(BadAND) -- cgit v0.12