summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmDocumentGeneratorExpressions.h11
-rw-r--r--Source/cmGeneratorExpression.cxx55
-rw-r--r--Source/cmGeneratorExpression.h1
-rw-r--r--Tests/CMakeLists.txt10
-rw-r--r--Tests/GeneratorExpression/CMakeLists.txt28
-rw-r--r--Tests/GeneratorExpression/check.cmake25
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadAND-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadAND-stderr.txt17
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadAND.cmake4
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadCONFIG-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadCONFIG-stderr.txt8
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadCONFIG.cmake3
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadNOT-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadNOT-stderr.txt26
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadNOT.cmake5
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadOR-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadOR-stderr.txt17
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadOR.cmake4
-rw-r--r--Tests/RunCMake/GeneratorExpression/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake6
21 files changed, 227 insertions, 1 deletions
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 5359013..74c673a 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -16,6 +16,9 @@
"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" \
+ " $<CONFIG:cfg> = '1' if config is \"cfg\", else '0'\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 +28,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
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index f88ab0b..92bbf1d 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -14,6 +14,8 @@
#include "cmMakefile.h"
#include "cmTarget.h"
+#include <cmsys/String.h>
+
//----------------------------------------------------------------------------
cmGeneratorExpression::cmGeneratorExpression(
cmMakefile* mf, const char* config,
@@ -25,6 +27,7 @@ cmGeneratorExpression::cmGeneratorExpression(
"_FILE(|_NAME|_DIR):" // Filename component.
"([A-Za-z0-9_.-]+)" // Target name.
">$");
+ this->TestConfig.compile("^\\$<CONFIG:([A-Za-z0-9_]*)>$");
}
//----------------------------------------------------------------------------
@@ -103,6 +106,26 @@ bool cmGeneratorExpression::Evaluate()
}
//----------------------------------------------------------------------------
+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)
{
if(this->TargetInfo.find(expr))
@@ -116,6 +139,38 @@ 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 if(this->TestConfig.find(expr))
+ {
+ result = cmsysString_strcasecmp(this->TestConfig.match(1).c_str(),
+ this->Config? this->Config:"") == 0
+ ? "1":"0";
+ }
else
{
result = "Expression syntax not recognized.";
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 1a9d4c6..a023eb0 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -51,6 +51,7 @@ private:
std::vector<char> Data;
std::stack<size_t> Barriers;
cmsys::RegularExpression TargetInfo;
+ cmsys::RegularExpression TestConfig;
std::set<cmTarget*> Targets;
bool Evaluate();
bool Evaluate(const char* expr, std::string& result);
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 9512ea6..ae51697 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -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"
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
new file mode 100644
index 0000000..2b135dc
--- /dev/null
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -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
+ )
diff --git a/Tests/GeneratorExpression/check.cmake b/Tests/GeneratorExpression/check.cmake
new file mode 100644
index 0000000..e243d85
--- /dev/null
+++ b/Tests/GeneratorExpression/check.cmake
@@ -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")
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index eca96f9..3ea54f1 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -45,6 +45,7 @@ macro(add_RunCMake_test test)
)
endmacro()
+add_RunCMake_test(GeneratorExpression)
add_RunCMake_test(Languages)
add_RunCMake_test(ObjectLibrary)
diff --git a/Tests/RunCMake/GeneratorExpression/BadAND-result.txt b/Tests/RunCMake/GeneratorExpression/BadAND-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadAND-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorExpression/BadAND-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadAND-stderr.txt
new file mode 100644
index 0000000..ced21d8
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadAND-stderr.txt
@@ -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\)$
diff --git a/Tests/RunCMake/GeneratorExpression/BadAND.cmake b/Tests/RunCMake/GeneratorExpression/BadAND.cmake
new file mode 100644
index 0000000..7926540
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadAND.cmake
@@ -0,0 +1,4 @@
+add_custom_target(check ALL COMMAND check
+ $<AND:>
+ $<AND:,>
+ VERBATIM)
diff --git a/Tests/RunCMake/GeneratorExpression/BadCONFIG-result.txt b/Tests/RunCMake/GeneratorExpression/BadCONFIG-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadCONFIG-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorExpression/BadCONFIG-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadCONFIG-stderr.txt
new file mode 100644
index 0000000..7c86b25
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadCONFIG-stderr.txt
@@ -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\)$
diff --git a/Tests/RunCMake/GeneratorExpression/BadCONFIG.cmake b/Tests/RunCMake/GeneratorExpression/BadCONFIG.cmake
new file mode 100644
index 0000000..0c13f89
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadCONFIG.cmake
@@ -0,0 +1,3 @@
+add_custom_target(check ALL COMMAND check
+ $<CONFIG:.>
+ VERBATIM)
diff --git a/Tests/RunCMake/GeneratorExpression/BadNOT-result.txt b/Tests/RunCMake/GeneratorExpression/BadNOT-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadNOT-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorExpression/BadNOT-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadNOT-stderr.txt
new file mode 100644
index 0000000..5721f5f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadNOT-stderr.txt
@@ -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\)$
diff --git a/Tests/RunCMake/GeneratorExpression/BadNOT.cmake b/Tests/RunCMake/GeneratorExpression/BadNOT.cmake
new file mode 100644
index 0000000..452293b
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadNOT.cmake
@@ -0,0 +1,5 @@
+add_custom_target(check ALL COMMAND check
+ $<NOT:>
+ $<NOT:,>
+ $<NOT:0,1>
+ VERBATIM)
diff --git a/Tests/RunCMake/GeneratorExpression/BadOR-result.txt b/Tests/RunCMake/GeneratorExpression/BadOR-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadOR-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorExpression/BadOR-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadOR-stderr.txt
new file mode 100644
index 0000000..72ef2dd
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadOR-stderr.txt
@@ -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\)$
diff --git a/Tests/RunCMake/GeneratorExpression/BadOR.cmake b/Tests/RunCMake/GeneratorExpression/BadOR.cmake
new file mode 100644
index 0000000..f16f56a
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadOR.cmake
@@ -0,0 +1,4 @@
+add_custom_target(check ALL COMMAND check
+ $<OR:>
+ $<OR:,>
+ VERBATIM)
diff --git a/Tests/RunCMake/GeneratorExpression/CMakeLists.txt b/Tests/RunCMake/GeneratorExpression/CMakeLists.txt
new file mode 100644
index 0000000..e8db6b0
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
new file mode 100644
index 0000000..ed18f25
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
@@ -0,0 +1,6 @@
+include(RunCMake)
+
+run_cmake(BadCONFIG)
+run_cmake(BadOR)
+run_cmake(BadAND)
+run_cmake(BadNOT)