Add a generator expression for target properties.

There are two overloads, so that it can use the operational
target when a target property is being evaluated, and a target
can alternatively be specified by name.

At this point, the generators don't chain. That comes later.
This commit is contained in:
Stephen Kelly 2012-09-12 04:23:31 +02:00 committed by Brad King
parent e028381bf1
commit 239ac84153
6 changed files with 66 additions and 5 deletions

View File

@ -81,7 +81,7 @@ public:
"\n" "\n"
"Arguments after COMMAND may use \"generator expressions\" with the " "Arguments after COMMAND may use \"generator expressions\" with the "
"syntax \"$<...>\". " "syntax \"$<...>\". "
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS
"Example usage:\n" "Example usage:\n"
" add_test(NAME mytest\n" " add_test(NAME mytest\n"
" COMMAND testDriver --config $<CONFIGURATION>\n" " COMMAND testDriver --config $<CONFIGURATION>\n"

View File

@ -12,7 +12,7 @@
#ifndef cmDocumentGeneratorExpressions_h #ifndef cmDocumentGeneratorExpressions_h
#define cmDocumentGeneratorExpressions_h #define cmDocumentGeneratorExpressions_h
#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \ #define CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
"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" \
@ -35,11 +35,20 @@
" $<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" \
" $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \
"the target tgt. Note that tgt is not added as a dependency of the " \
"target this expression is evaluated on.\n" \
"Boolean expressions:\n" \ "Boolean expressions:\n" \
" $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \ " $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
" $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \ " $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \
" $<NOT:?> = '0' if '?' is '1', else '1'\n" \ " $<NOT:?> = '0' if '?' is '1', else '1'\n" \
"where '?' is always either '0' or '1'.\n" \ "where '?' is always either '0' or '1'.\n" \
#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
"Expressions with an implicit 'this' target:" \
" $<TARGET_PROPERTY:prop> = The value of the property prop on\n" \
"the target on which the generator expression is evaluated.\n" \
"" ""
#endif #endif

View File

@ -65,7 +65,8 @@ cmGeneratorExpression::~cmGeneratorExpression()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char *cmCompiledGeneratorExpression::Evaluate( const char *cmCompiledGeneratorExpression::Evaluate(
cmMakefile* mf, const char* config, bool quiet) const cmMakefile* mf, const char* config, bool quiet,
cmGeneratorTarget *target) const
{ {
if (!this->NeedsParsing) if (!this->NeedsParsing)
{ {
@ -84,6 +85,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
context.Config = config; context.Config = config;
context.Quiet = quiet; context.Quiet = quiet;
context.HadError = false; context.HadError = false;
context.Target = target;
context.Backtrace = this->Backtrace; context.Backtrace = this->Backtrace;
for ( ; it != end; ++it) for ( ; it != end; ++it)

View File

@ -20,6 +20,7 @@
#include <cmsys/RegularExpression.hxx> #include <cmsys/RegularExpression.hxx>
class cmTarget; class cmTarget;
class cmGeneratorTarget;
class cmMakefile; class cmMakefile;
class cmListFileBacktrace; class cmListFileBacktrace;
@ -58,7 +59,8 @@ class cmCompiledGeneratorExpression
{ {
public: public:
const char* Evaluate(cmMakefile* mf, const char* config, const char* Evaluate(cmMakefile* mf, const char* config,
bool quiet = false) const; bool quiet = false,
cmGeneratorTarget *target = 0) const;
/** Get set of targets found during evaluations. */ /** Get set of targets found during evaluations. */
std::set<cmTarget*> const& GetTargets() const std::set<cmTarget*> const& GetTargets() const

View File

@ -239,6 +239,46 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
} }
} configurationTestNode; } configurationTestNode;
//----------------------------------------------------------------------------
static const struct TargetPropertyNode: public cmGeneratorExpressionNode
{
TargetPropertyNode() {}
// This node handles errors on parameter count itself.
virtual int NumExpectedParameters() const { return -1; }
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content) const
{
if (parameters.size() != 1 && parameters.size() != 2)
{
reportError(context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:...> expression requires one or two parameters");
return std::string();
}
cmGeneratorTarget* target = context->Target;
std::string propertyName = *parameters.begin();
if (parameters.size() == 2)
{
target = context->Makefile->FindGeneratorTargetToUse(
parameters.begin()->c_str());
if (!target)
{
cmOStringStream e;
e << "Target \""
<< target
<< "\" not found.";
reportError(context, content->GetOriginalExpression(), e.str());
}
propertyName = parameters.at(1);
}
const char *prop = target->GetProperty(propertyName.c_str());
return prop ? prop : "";
}
} targetPropertyNode;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template<bool linker, bool soname> template<bool linker, bool soname>
struct TargetFilesystemArtifactResultCreator struct TargetFilesystemArtifactResultCreator
@ -460,7 +500,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &angle_rNode; return &angle_rNode;
else if (identifier == "COMMA") else if (identifier == "COMMA")
return &commaNode; return &commaNode;
else if (identifier == "TARGET_PROPERTY")
return &targetPropertyNode;
return 0; return 0;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -15,6 +15,11 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include "cmListFileCache.h"
class cmTarget;
class cmGeneratorTarget;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
struct cmGeneratorExpressionContext struct cmGeneratorExpressionContext
{ {
@ -22,7 +27,7 @@ struct cmGeneratorExpressionContext
std::set<cmTarget*> Targets; std::set<cmTarget*> Targets;
cmMakefile *Makefile; cmMakefile *Makefile;
const char *Config; const char *Config;
cmTarget *Target; cmGeneratorTarget *Target;
bool Quiet; bool Quiet;
bool HadError; bool HadError;
}; };