Merge topic 'join-genex'

a7ba452 Add the JOIN generator expression.
96ec314 Make it possible for any genex to have arbitrary content at the end.
bd638ee Rename the method determining if a genex accepts arbitrary content.
dc742fe Extract the ProcessArbitraryContent method.
This commit is contained in:
Brad King 2013-05-22 13:35:15 -04:00 committed by CMake Topic Stage
commit 3db29d2724
7 changed files with 145 additions and 51 deletions

View File

@ -28,6 +28,8 @@
"strings which contain a ',' for example.\n" \ "strings which contain a ',' for example.\n" \
" $<SEMICOLON> = A literal ';'. Used to prevent " \ " $<SEMICOLON> = A literal ';'. Used to prevent " \
"list expansion on an argument with ';'.\n" \ "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_NAME:...> = Marks ... as being the name of a " \
"target. This is required if exporting targets to multiple " \ "target. This is required if exporting targets to multiple " \
"dependent export sets. The '...' must be a literal name of a " \ "dependent export sets. The '...' must be a literal name of a " \

View File

@ -51,7 +51,7 @@ struct cmGeneratorExpressionNode
virtual bool RequiresLiteralInput() const { return false; } virtual bool RequiresLiteralInput() const { return false; }
virtual bool AcceptsSingleArbitraryContentParameter() const virtual bool AcceptsArbitraryContentParameter() const
{ return false; } { return false; }
virtual int NumExpectedParameters() const { return 1; } virtual int NumExpectedParameters() const { return 1; }
@ -70,7 +70,7 @@ static const struct ZeroNode : public cmGeneratorExpressionNode
virtual bool GeneratesContent() const { return false; } 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> &, std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *, cmGeneratorExpressionContext *,
@ -87,7 +87,7 @@ static const struct OneNode : public cmGeneratorExpressionNode
{ {
OneNode() {} OneNode() {}
virtual bool AcceptsSingleArbitraryContentParameter() const { return true; } virtual bool AcceptsArbitraryContentParameter() const { return true; }
std::string Evaluate(const std::vector<std::string> &, std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *, cmGeneratorExpressionContext *,
@ -307,6 +307,34 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
} configurationTestNode; } 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[] = { static const char* targetPropertyTransitiveWhitelist[] = {
"INTERFACE_INCLUDE_DIRECTORIES" "INTERFACE_INCLUDE_DIRECTORIES"
@ -600,7 +628,7 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
virtual bool GeneratesContent() const { return true; } virtual bool GeneratesContent() const { return true; }
virtual bool AcceptsSingleArbitraryContentParameter() const { return true; } virtual bool AcceptsArbitraryContentParameter() const { return true; }
virtual bool RequiresLiteralInput() const { return true; } virtual bool RequiresLiteralInput() const { return true; }
std::string Evaluate(const std::vector<std::string> &parameters, std::string Evaluate(const std::vector<std::string> &parameters,
@ -973,6 +1001,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &installInterfaceNode; return &installInterfaceNode;
else if (identifier == "INSTALL_PREFIX") else if (identifier == "INSTALL_PREFIX")
return &installPrefixNode; return &installPrefixNode;
else if (identifier == "JOIN")
return &joinNode;
return 0; return 0;
} }
@ -992,6 +1022,57 @@ std::string GeneratorExpressionContent::GetOriginalExpression() const
return std::string(this->StartContent, this->ContentLength); return std::string(this->StartContent, this->ContentLength);
} }
//----------------------------------------------------------------------------
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( std::string GeneratorExpressionContent::Evaluate(
cmGeneratorExpressionContext *context, cmGeneratorExpressionContext *context,
@ -1024,7 +1105,8 @@ std::string GeneratorExpressionContent::Evaluate(
if (!node->GeneratesContent()) if (!node->GeneratesContent())
{ {
if (node->AcceptsSingleArbitraryContentParameter()) if (node->NumExpectedParameters() == 1
&& node->AcceptsArbitraryContentParameter())
{ {
if (this->ParamChildren.empty()) if (this->ParamChildren.empty())
{ {
@ -1041,49 +1123,12 @@ std::string GeneratorExpressionContent::Evaluate(
return std::string(); return std::string();
} }
if (node->AcceptsSingleArbitraryContentParameter()) if (node->NumExpectedParameters() == 1
&& node->AcceptsArbitraryContentParameter())
{ {
std::string result; return this->ProcessArbitraryContent(node, identifier, context,
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator dagChecker,
pit = this->ParamChildren.begin(); 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;
} }
std::vector<std::string> parameters; std::vector<std::string> parameters;
@ -1104,12 +1149,15 @@ std::string GeneratorExpressionContent::EvaluateParameters(
cmGeneratorExpressionDAGChecker *dagChecker, cmGeneratorExpressionDAGChecker *dagChecker,
std::vector<std::string> &parameters) const std::vector<std::string> &parameters) const
{ {
const int numExpected = node->NumExpectedParameters();
{ {
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
pit = this->ParamChildren.begin(); pit = this->ParamChildren.begin();
const const
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
pend = this->ParamChildren.end(); pend = this->ParamChildren.end();
const bool acceptsArbitraryContent
= node->AcceptsArbitraryContentParameter();
for ( ; pit != pend; ++pit) for ( ; pit != pend; ++pit)
{ {
std::string parameter; std::string parameter;
@ -1126,10 +1174,20 @@ std::string GeneratorExpressionContent::EvaluateParameters(
} }
} }
parameters.push_back(parameter); 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 != -1 && (unsigned int)numExpected != parameters.size()))
{ {
if (numExpected == 0) if (numExpected == 0)

View File

@ -129,6 +129,14 @@ private:
cmGeneratorExpressionDAGChecker *dagChecker, cmGeneratorExpressionDAGChecker *dagChecker,
std::vector<std::string> &parameters) const; 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: private:
std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren; std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren;
std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren; std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren;

View File

@ -20,10 +20,16 @@ static const char very_fun_string[] = CMAKE_IS_REALLY;
#endif #endif
enum { enum {
StringLiteralTest1 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_) == sizeof("Fun")>) StringLiteralTest1 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_) == sizeof("Fun")>),
#ifndef NO_SPACES_IN_DEFINE_VALUES #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 #endif
}; };
@ -42,6 +48,14 @@ enum {
#error Expected define expanded from list #error Expected define expanded from list
#endif #endif
#ifndef PREFIX_DEF1
#error Expect PREFIX_DEF1
#endif
#ifndef PREFIX_DEF2
#error Expect PREFIX_DEF2
#endif
// TEST_GENERATOR_EXPRESSIONS // TEST_GENERATOR_EXPRESSIONS
#endif #endif

View File

@ -13,6 +13,12 @@ set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
"$<1:CMAKE_IS_DECLARATIVE>" "$<1:CMAKE_IS_DECLARATIVE>"
"$<0:GE_NOT_DEFINED>" "$<0:GE_NOT_DEFINED>"
"$<1:ARGUMENT;LIST>" "$<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 set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS

View File

@ -123,3 +123,8 @@ target_link_libraries(lib5 libbad libgood)
target_include_directories(lib5 target_include_directories(lib5
BEFORE PRIVATE $<TARGET_PROPERTY:libgood,INTERFACE_INCLUDE_DIRECTORIES> 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_>")

View File

@ -10,6 +10,7 @@
#include "arguments.h" #include "arguments.h"
#include "list.h" #include "list.h"
#include "target.h" #include "target.h"
#include "prefix_foo_bar_bat.h"
int main(int, char**) int main(int, char**)
{ {