Add boolean generator expressions
Add generator expressions that combine and use boolean test results: $<0:...> = empty string (ignores "...") $<1:...> = content of "..." $<AND:?[,?]...> = '1' if all '?' are '1', else '0' $<OR:?[,?]...> = '0' if all '?' are '0', else '1' $<NOT:?> = '0' if '?' is '1', else '1' These will be useful to evaluate (future) boolean query expressions and condition content on the results. Include tests and documentation.
This commit is contained in:
parent
cd3bd23266
commit
ebf05abda1
|
@ -16,6 +16,8 @@
|
|||
"Generator expressions are evaluted during build system generation " \
|
||||
"to produce information specific to each build configuration. " \
|
||||
"Valid expressions are:\n" \
|
||||
" $<0:...> = empty string (ignores \"...\")\n" \
|
||||
" $<1:...> = content of \"...\"\n" \
|
||||
" $<CONFIGURATION> = configuration name\n" \
|
||||
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
|
||||
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
|
||||
|
@ -25,6 +27,12 @@
|
|||
"versions can produce the directory and file name components:\n" \
|
||||
" $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n" \
|
||||
" $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \
|
||||
" $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n"
|
||||
" $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \
|
||||
"Boolean expressions:\n" \
|
||||
" $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
|
||||
" $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \
|
||||
" $<NOT:?> = '0' if '?' is '1', else '1'\n" \
|
||||
"where '?' is always either '0' or '1'.\n" \
|
||||
""
|
||||
|
||||
#endif
|
||||
|
|
|
@ -102,6 +102,26 @@ bool cmGeneratorExpression::Evaluate()
|
|||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool cmGeneratorExpressionBool(const char* c, std::string& result,
|
||||
const char* name,
|
||||
const char* a, const char* b)
|
||||
{
|
||||
result = a;
|
||||
while((c[0] == '0' || c[0] == '1') && (c[1] == ',' || c[1] == '>'))
|
||||
{
|
||||
if(c[0] == b[0]) { result = b; }
|
||||
c += 2;
|
||||
}
|
||||
if(c[0])
|
||||
{
|
||||
result = name;
|
||||
result += " requires one or more comma-separated '0' or '1' values.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmGeneratorExpression::Evaluate(const char* expr, std::string& result)
|
||||
{
|
||||
|
@ -116,6 +136,32 @@ bool cmGeneratorExpression::Evaluate(const char* expr, std::string& result)
|
|||
{
|
||||
result = this->Config? this->Config : "";
|
||||
}
|
||||
else if(strncmp(expr, "$<0:",4) == 0)
|
||||
{
|
||||
result = "";
|
||||
}
|
||||
else if(strncmp(expr, "$<1:",4) == 0)
|
||||
{
|
||||
result = std::string(expr+4, strlen(expr)-5);
|
||||
}
|
||||
else if(strncmp(expr, "$<NOT:",6) == 0)
|
||||
{
|
||||
const char* c = expr+6;
|
||||
if((c[0] != '0' && c[0] != '1') || c[1] != '>' || c[2])
|
||||
{
|
||||
result = "NOT requires exactly one '0' or '1' value.";
|
||||
return false;
|
||||
}
|
||||
result = c[0] == '1'? "0" : "1";
|
||||
}
|
||||
else if(strncmp(expr, "$<AND:",6) == 0)
|
||||
{
|
||||
return cmGeneratorExpressionBool(expr+6, result, "AND", "1", "0");
|
||||
}
|
||||
else if(strncmp(expr, "$<OR:",5) == 0)
|
||||
{
|
||||
return cmGeneratorExpressionBool(expr+5, result, "OR", "0", "1");
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "Expression syntax not recognized.";
|
||||
|
|
|
@ -551,6 +551,16 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
|
|||
FAIL_REGULAR_EXPRESSION "Unexpected: ")
|
||||
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ArgumentExpansion")
|
||||
|
||||
add_test(GeneratorExpression ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/GeneratorExpression"
|
||||
"${CMake_BINARY_DIR}/Tests/GeneratorExpression"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-project GeneratorExpression
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
)
|
||||
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/GeneratorExpression")
|
||||
|
||||
add_test(CustomCommand ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/CustomCommand"
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
cmake_minimum_required (VERSION 2.8.8)
|
||||
project(GeneratorExpression NONE)
|
||||
|
||||
add_custom_target(check ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-Dtest_0=$<0:nothing>
|
||||
-Dtest_1=$<1:content>
|
||||
-Dconfig=$<CONFIGURATION>
|
||||
-Dtest_and_0=$<AND:0>
|
||||
-Dtest_and_0_0=$<AND:0,0>
|
||||
-Dtest_and_0_1=$<AND:0,1>
|
||||
-Dtest_and_1=$<AND:1>
|
||||
-Dtest_and_1_0=$<AND:1,0>
|
||||
-Dtest_and_1_1=$<AND:1,1>
|
||||
-Dtest_not_0=$<NOT:0>
|
||||
-Dtest_not_1=$<NOT:1>
|
||||
-Dtest_or_0=$<OR:0>
|
||||
-Dtest_or_0_0=$<OR:0,0>
|
||||
-Dtest_or_0_1=$<OR:0,1>
|
||||
-Dtest_or_1=$<OR:1>
|
||||
-Dtest_or_1_0=$<OR:1,0>
|
||||
-Dtest_or_1_1=$<OR:1,1>
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "check done"
|
||||
VERBATIM
|
||||
)
|
|
@ -0,0 +1,23 @@
|
|||
macro(check var val)
|
||||
if(NOT "${${var}}" STREQUAL "${val}")
|
||||
message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
message(STATUS "config=[${config}]")
|
||||
check(test_0 "")
|
||||
check(test_1 "content")
|
||||
check(test_and_0 "0")
|
||||
check(test_and_0_0 "0")
|
||||
check(test_and_0_1 "0")
|
||||
check(test_and_1 "1")
|
||||
check(test_and_1_0 "0")
|
||||
check(test_and_1_1 "1")
|
||||
check(test_not_0 "1")
|
||||
check(test_not_1 "0")
|
||||
check(test_or_0 "0")
|
||||
check(test_or_0_0 "0")
|
||||
check(test_or_0_1 "1")
|
||||
check(test_or_1 "1")
|
||||
check(test_or_1_0 "1")
|
||||
check(test_or_1_1 "1")
|
|
@ -45,6 +45,7 @@ macro(add_RunCMake_test test)
|
|||
)
|
||||
endmacro()
|
||||
|
||||
add_RunCMake_test(GeneratorExpression)
|
||||
add_RunCMake_test(Languages)
|
||||
add_RunCMake_test(ObjectLibrary)
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,17 @@
|
|||
CMake Error at BadAND.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<AND:>
|
||||
|
||||
AND requires one or more comma-separated '0' or '1' values.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
+
|
||||
CMake Error at BadAND.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<AND:,>
|
||||
|
||||
AND requires one or more comma-separated '0' or '1' values.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)$
|
|
@ -0,0 +1,4 @@
|
|||
add_custom_target(check ALL COMMAND check
|
||||
$<AND:>
|
||||
$<AND:,>
|
||||
VERBATIM)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,26 @@
|
|||
CMake Error at BadNOT.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<NOT:>
|
||||
|
||||
NOT requires exactly one '0' or '1' value.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
+
|
||||
CMake Error at BadNOT.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<NOT:,>
|
||||
|
||||
NOT requires exactly one '0' or '1' value.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
+
|
||||
CMake Error at BadNOT.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<NOT:0,1>
|
||||
|
||||
NOT requires exactly one '0' or '1' value.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)$
|
|
@ -0,0 +1,5 @@
|
|||
add_custom_target(check ALL COMMAND check
|
||||
$<NOT:>
|
||||
$<NOT:,>
|
||||
$<NOT:0,1>
|
||||
VERBATIM)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,17 @@
|
|||
CMake Error at BadOR.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<OR:>
|
||||
|
||||
OR requires one or more comma-separated '0' or '1' values.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
+
|
||||
CMake Error at BadOR.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<OR:,>
|
||||
|
||||
OR requires one or more comma-separated '0' or '1' values.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)$
|
|
@ -0,0 +1,4 @@
|
|||
add_custom_target(check ALL COMMAND check
|
||||
$<OR:>
|
||||
$<OR:,>
|
||||
VERBATIM)
|
|
@ -0,0 +1,3 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1,5 @@
|
|||
include(RunCMake)
|
||||
|
||||
run_cmake(BadOR)
|
||||
run_cmake(BadAND)
|
||||
run_cmake(BadNOT)
|
Loading…
Reference in New Issue