Merge topic 'generator-expression-conditions'
9d9f616
Add $<CONFIG:...> boolean query generator expressionebf05ab
Add boolean generator expressions
This commit is contained in:
commit
3574bb4842
|
@ -16,6 +16,9 @@
|
||||||
"Generator expressions are evaluted during build system generation " \
|
"Generator expressions are evaluted during build system generation " \
|
||||||
"to produce information specific to each build configuration. " \
|
"to produce information specific to each build configuration. " \
|
||||||
"Valid expressions are:\n" \
|
"Valid expressions are:\n" \
|
||||||
|
" $<0:...> = empty string (ignores \"...\")\n" \
|
||||||
|
" $<1:...> = content of \"...\"\n" \
|
||||||
|
" $<CONFIG:cfg> = '1' if config is \"cfg\", else '0'\n" \
|
||||||
" $<CONFIGURATION> = configuration name\n" \
|
" $<CONFIGURATION> = configuration name\n" \
|
||||||
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
|
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
|
||||||
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
|
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
|
||||||
|
@ -25,6 +28,12 @@
|
||||||
"versions can produce the directory and file name components:\n" \
|
"versions can produce the directory and file name components:\n" \
|
||||||
" $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n" \
|
" $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n" \
|
||||||
" $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_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
|
#endif
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
#include "cmTarget.h"
|
#include "cmTarget.h"
|
||||||
|
|
||||||
|
#include <cmsys/String.h>
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
cmGeneratorExpression::cmGeneratorExpression(
|
cmGeneratorExpression::cmGeneratorExpression(
|
||||||
cmMakefile* mf, const char* config,
|
cmMakefile* mf, const char* config,
|
||||||
|
@ -25,6 +27,7 @@ cmGeneratorExpression::cmGeneratorExpression(
|
||||||
"_FILE(|_NAME|_DIR):" // Filename component.
|
"_FILE(|_NAME|_DIR):" // Filename component.
|
||||||
"([A-Za-z0-9_.-]+)" // Target name.
|
"([A-Za-z0-9_.-]+)" // Target name.
|
||||||
">$");
|
">$");
|
||||||
|
this->TestConfig.compile("^\\$<CONFIG:([A-Za-z0-9_]*)>$");
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -102,6 +105,26 @@ bool cmGeneratorExpression::Evaluate()
|
||||||
return true;
|
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)
|
bool cmGeneratorExpression::Evaluate(const char* expr, std::string& result)
|
||||||
{
|
{
|
||||||
|
@ -116,6 +139,38 @@ bool cmGeneratorExpression::Evaluate(const char* expr, std::string& result)
|
||||||
{
|
{
|
||||||
result = this->Config? this->Config : "";
|
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 if(this->TestConfig.find(expr))
|
||||||
|
{
|
||||||
|
result = cmsysString_strcasecmp(this->TestConfig.match(1).c_str(),
|
||||||
|
this->Config? this->Config:"") == 0
|
||||||
|
? "1":"0";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = "Expression syntax not recognized.";
|
result = "Expression syntax not recognized.";
|
||||||
|
|
|
@ -51,6 +51,7 @@ private:
|
||||||
std::vector<char> Data;
|
std::vector<char> Data;
|
||||||
std::stack<size_t> Barriers;
|
std::stack<size_t> Barriers;
|
||||||
cmsys::RegularExpression TargetInfo;
|
cmsys::RegularExpression TargetInfo;
|
||||||
|
cmsys::RegularExpression TestConfig;
|
||||||
std::set<cmTarget*> Targets;
|
std::set<cmTarget*> Targets;
|
||||||
bool Evaluate();
|
bool Evaluate();
|
||||||
bool Evaluate(const char* expr, std::string& result);
|
bool Evaluate(const char* expr, std::string& result);
|
||||||
|
|
|
@ -551,6 +551,16 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
|
||||||
FAIL_REGULAR_EXPRESSION "Unexpected: ")
|
FAIL_REGULAR_EXPRESSION "Unexpected: ")
|
||||||
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ArgumentExpansion")
|
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}
|
add_test(CustomCommand ${CMAKE_CTEST_COMMAND}
|
||||||
--build-and-test
|
--build-and-test
|
||||||
"${CMake_SOURCE_DIR}/Tests/CustomCommand"
|
"${CMake_SOURCE_DIR}/Tests/CustomCommand"
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
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_config_0=$<CONFIG:$<CONFIGURATION>x>
|
||||||
|
-Dtest_config_1=$<CONFIG:$<CONFIGURATION>>
|
||||||
|
-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,25 @@
|
||||||
|
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_config_0 "0")
|
||||||
|
check(test_config_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()
|
endmacro()
|
||||||
|
|
||||||
|
add_RunCMake_test(GeneratorExpression)
|
||||||
add_RunCMake_test(Languages)
|
add_RunCMake_test(Languages)
|
||||||
add_RunCMake_test(ObjectLibrary)
|
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,8 @@
|
||||||
|
CMake Error at BadCONFIG.cmake:1 \(add_custom_target\):
|
||||||
|
Error evaluating generator expression:
|
||||||
|
|
||||||
|
\$<CONFIG:.>
|
||||||
|
|
||||||
|
Expression syntax not recognized.
|
||||||
|
Call Stack \(most recent call first\):
|
||||||
|
CMakeLists.txt:3 \(include\)$
|
|
@ -0,0 +1,3 @@
|
||||||
|
add_custom_target(check ALL COMMAND check
|
||||||
|
$<CONFIG:.>
|
||||||
|
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,6 @@
|
||||||
|
include(RunCMake)
|
||||||
|
|
||||||
|
run_cmake(BadCONFIG)
|
||||||
|
run_cmake(BadOR)
|
||||||
|
run_cmake(BadAND)
|
||||||
|
run_cmake(BadNOT)
|
Loading…
Reference in New Issue