summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmDocumentGeneratorExpressions.h2
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx154
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h8
-rw-r--r--Tests/CompileDefinitions/compiletest.cpp20
-rw-r--r--Tests/CompileDefinitions/target_prop/CMakeLists.txt6
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt5
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp1
7 files changed, 145 insertions, 51 deletions
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 7edc8ff..ae9ca50 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -28,6 +28,8 @@
"strings which contain a ',' for example.\n" \
" $<SEMICOLON> = A literal ';'. Used to prevent " \
"list expansion on an argument with ';'.\n" \
+ " $<JOIN:list,...> = joins the list with the content of " \
+ "\"...\"\n" \
" $<TARGET_NAME:...> = Marks ... as being the name of a " \
"target. This is required if exporting targets to multiple " \
"dependent export sets. The '...' must be a literal name of a " \
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 58fd251..9613673 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -51,7 +51,7 @@ struct cmGeneratorExpressionNode
virtual bool RequiresLiteralInput() const { return false; }
- virtual bool AcceptsSingleArbitraryContentParameter() const
+ virtual bool AcceptsArbitraryContentParameter() const
{ return false; }
virtual int NumExpectedParameters() const { return 1; }
@@ -70,7 +70,7 @@ static const struct ZeroNode : public cmGeneratorExpressionNode
virtual bool GeneratesContent() const { return false; }
- virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *,
@@ -87,7 +87,7 @@ static const struct OneNode : public cmGeneratorExpressionNode
{
OneNode() {}
- virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *,
@@ -307,6 +307,34 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
} configurationTestNode;
+static const struct JoinNode : public cmGeneratorExpressionNode
+{
+ JoinNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ std::string result;
+
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(parameters.front(), list);
+ std::string sep;
+ for(std::vector<std::string>::const_iterator li = list.begin();
+ li != list.end(); ++li)
+ {
+ result += sep + *li;
+ sep = parameters[1];
+ }
+ return result;
+ }
+} joinNode;
+
//----------------------------------------------------------------------------
static const char* targetPropertyTransitiveWhitelist[] = {
"INTERFACE_INCLUDE_DIRECTORIES"
@@ -600,7 +628,7 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
virtual bool GeneratesContent() const { return true; }
- virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
virtual bool RequiresLiteralInput() const { return true; }
std::string Evaluate(const std::vector<std::string> &parameters,
@@ -973,6 +1001,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &installInterfaceNode;
else if (identifier == "INSTALL_PREFIX")
return &installPrefixNode;
+ else if (identifier == "JOIN")
+ return &joinNode;
return 0;
}
@@ -993,6 +1023,57 @@ std::string GeneratorExpressionContent::GetOriginalExpression() const
}
//----------------------------------------------------------------------------
+std::string GeneratorExpressionContent::ProcessArbitraryContent(
+ const cmGeneratorExpressionNode *node,
+ const std::string &identifier,
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pit) const
+{
+ std::string result;
+
+ const
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pend = this->ParamChildren.end();
+ for ( ; pit != pend; ++pit)
+ {
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
+ = pit->begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
+ = pit->end();
+ for ( ; it != end; ++it)
+ {
+ if (node->RequiresLiteralInput())
+ {
+ if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
+ {
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier + "> expression requires literal input.");
+ return std::string();
+ }
+ }
+ result += (*it)->Evaluate(context, dagChecker);
+ if (context->HadError)
+ {
+ return std::string();
+ }
+ }
+ if ((pit + 1) != pend)
+ {
+ result += ",";
+ }
+ }
+ if (node->RequiresLiteralInput())
+ {
+ std::vector<std::string> parameters;
+ parameters.push_back(result);
+ return node->Evaluate(parameters, context, this, dagChecker);
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------
std::string GeneratorExpressionContent::Evaluate(
cmGeneratorExpressionContext *context,
cmGeneratorExpressionDAGChecker *dagChecker) const
@@ -1024,7 +1105,8 @@ std::string GeneratorExpressionContent::Evaluate(
if (!node->GeneratesContent())
{
- if (node->AcceptsSingleArbitraryContentParameter())
+ if (node->NumExpectedParameters() == 1
+ && node->AcceptsArbitraryContentParameter())
{
if (this->ParamChildren.empty())
{
@@ -1041,49 +1123,12 @@ std::string GeneratorExpressionContent::Evaluate(
return std::string();
}
- if (node->AcceptsSingleArbitraryContentParameter())
+ if (node->NumExpectedParameters() == 1
+ && node->AcceptsArbitraryContentParameter())
{
- std::string result;
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
- pit = this->ParamChildren.begin();
- const
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
- pend = this->ParamChildren.end();
- for ( ; pit != pend; ++pit)
- {
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
- = pit->begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
- = pit->end();
- for ( ; it != end; ++it)
- {
- if (node->RequiresLiteralInput())
- {
- if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
- {
- reportError(context, this->GetOriginalExpression(),
- "$<" + identifier + "> expression requires literal input.");
- return std::string();
- }
- }
- result += (*it)->Evaluate(context, dagChecker);
- if (context->HadError)
- {
- return std::string();
- }
- }
- if ((pit + 1) != pend)
- {
- result += ",";
- }
- }
- if (node->RequiresLiteralInput())
- {
- std::vector<std::string> parameters;
- parameters.push_back(result);
- return node->Evaluate(parameters, context, this, dagChecker);
- }
- return result;
+ return this->ProcessArbitraryContent(node, identifier, context,
+ dagChecker,
+ this->ParamChildren.begin());
}
std::vector<std::string> parameters;
@@ -1104,12 +1149,15 @@ std::string GeneratorExpressionContent::EvaluateParameters(
cmGeneratorExpressionDAGChecker *dagChecker,
std::vector<std::string> &parameters) const
{
+ const int numExpected = node->NumExpectedParameters();
{
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
pit = this->ParamChildren.begin();
const
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
pend = this->ParamChildren.end();
+ const bool acceptsArbitraryContent
+ = node->AcceptsArbitraryContentParameter();
for ( ; pit != pend; ++pit)
{
std::string parameter;
@@ -1126,10 +1174,20 @@ std::string GeneratorExpressionContent::EvaluateParameters(
}
}
parameters.push_back(parameter);
+ if (acceptsArbitraryContent
+ && parameters.size() == (unsigned int)numExpected - 1)
+ {
+ assert(pit != pend);
+ std::string lastParam = this->ProcessArbitraryContent(node, identifier,
+ context,
+ dagChecker,
+ pit + 1);
+ parameters.push_back(lastParam);
+ return std::string();
+ }
}
}
- int numExpected = node->NumExpectedParameters();
if ((numExpected != -1 && (unsigned int)numExpected != parameters.size()))
{
if (numExpected == 0)
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index ce7ad69..218abf1 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -129,6 +129,14 @@ private:
cmGeneratorExpressionDAGChecker *dagChecker,
std::vector<std::string> &parameters) const;
+ std::string ProcessArbitraryContent(
+ const cmGeneratorExpressionNode *node,
+ const std::string &identifier,
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pit) const;
+
private:
std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren;
std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren;
diff --git a/Tests/CompileDefinitions/compiletest.cpp b/Tests/CompileDefinitions/compiletest.cpp
index 14b8eab..7379380 100644
--- a/Tests/CompileDefinitions/compiletest.cpp
+++ b/Tests/CompileDefinitions/compiletest.cpp
@@ -20,10 +20,16 @@ static const char very_fun_string[] = CMAKE_IS_REALLY;
#endif
enum {
- StringLiteralTest1 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_) == sizeof("Fun")>)
+ StringLiteralTest1 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_) == sizeof("Fun")>),
#ifndef NO_SPACES_IN_DEFINE_VALUES
- ,
- StringLiteralTest2 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_REALLY) == sizeof("Very Fun")>)
+ StringLiteralTest2 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_REALLY) == sizeof("Very Fun")>),
+#endif
+#ifdef TEST_GENERATOR_EXPRESSIONS
+ StringLiteralTest3 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST1) == sizeof("A,B,C,D")>),
+ StringLiteralTest4 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST2) == sizeof("A,,B,,C,,D")>),
+ StringLiteralTest5 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST3) == sizeof("A,-B,-C,-D")>),
+ StringLiteralTest6 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST4) == sizeof("A-,-B-,-C-,-D")>),
+ StringLiteralTest7 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST5) == sizeof("A-,B-,C-,D")>)
#endif
};
@@ -42,6 +48,14 @@ enum {
#error Expected define expanded from list
#endif
+#ifndef PREFIX_DEF1
+#error Expect PREFIX_DEF1
+#endif
+
+#ifndef PREFIX_DEF2
+#error Expect PREFIX_DEF2
+#endif
+
// TEST_GENERATOR_EXPRESSIONS
#endif
diff --git a/Tests/CompileDefinitions/target_prop/CMakeLists.txt b/Tests/CompileDefinitions/target_prop/CMakeLists.txt
index 1ef2d6d..34be917 100644
--- a/Tests/CompileDefinitions/target_prop/CMakeLists.txt
+++ b/Tests/CompileDefinitions/target_prop/CMakeLists.txt
@@ -13,6 +13,12 @@ set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
"$<1:CMAKE_IS_DECLARATIVE>"
"$<0:GE_NOT_DEFINED>"
"$<1:ARGUMENT;LIST>"
+ PREFIX_$<JOIN:DEF1;DEF2,;PREFIX_>
+ LETTER_LIST1=\"$<JOIN:A;B;C;D,,>\"
+ LETTER_LIST2=\"$<JOIN:A;B;C;D,,,>\"
+ LETTER_LIST3=\"$<JOIN:A;B;C;D,,->\"
+ LETTER_LIST4=\"$<JOIN:A;B;C;D,-,->\"
+ LETTER_LIST5=\"$<JOIN:A;B;C;D,-,>\"
)
set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
index ad6671f..60d4c6a 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
@@ -123,3 +123,8 @@ target_link_libraries(lib5 libbad libgood)
target_include_directories(lib5
BEFORE PRIVATE $<TARGET_PROPERTY:libgood,INTERFACE_INCLUDE_DIRECTORIES>
)
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat/prefix_foo_bar_bat.h" "// prefix_foo_bar_bat.h\n")
+
+target_include_directories(TargetIncludeDirectories PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix_$<JOIN:foo;bar;bat,/prefix_>")
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
index 90909d3..5bb34aa 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
@@ -10,6 +10,7 @@
#include "arguments.h"
#include "list.h"
#include "target.h"
+#include "prefix_foo_bar_bat.h"
int main(int, char**)
{