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"
"Arguments after COMMAND may use \"generator expressions\" with the "
"syntax \"$<...>\". "
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS
"Example usage:\n"
" add_test(NAME mytest\n"
" COMMAND testDriver --config $<CONFIGURATION>\n"

View File

@ -12,7 +12,7 @@
#ifndef 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 " \
"to produce information specific to each build configuration. " \
"Valid expressions are:\n" \
@ -35,11 +35,20 @@
" $<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_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" \
" $<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" \
#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

View File

@ -65,7 +65,8 @@ cmGeneratorExpression::~cmGeneratorExpression()
//----------------------------------------------------------------------------
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)
{
@ -84,6 +85,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
context.Config = config;
context.Quiet = quiet;
context.HadError = false;
context.Target = target;
context.Backtrace = this->Backtrace;
for ( ; it != end; ++it)

View File

@ -20,6 +20,7 @@
#include <cmsys/RegularExpression.hxx>
class cmTarget;
class cmGeneratorTarget;
class cmMakefile;
class cmListFileBacktrace;
@ -58,7 +59,8 @@ class cmCompiledGeneratorExpression
{
public:
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. */
std::set<cmTarget*> const& GetTargets() const

View File

@ -239,6 +239,46 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
}
} 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>
struct TargetFilesystemArtifactResultCreator
@ -460,7 +500,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &angle_rNode;
else if (identifier == "COMMA")
return &commaNode;
else if (identifier == "TARGET_PROPERTY")
return &targetPropertyNode;
return 0;
}
//----------------------------------------------------------------------------

View File

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