diff options
author | Stephen Kelly <steveire@gmail.com> | 2013-01-30 22:38:04 (GMT) |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2013-01-31 16:34:20 (GMT) |
commit | 0b92602b816e2584db3781b120a1e5200da72ada (patch) | |
tree | ccf0d78b89d14d2bc317725b81ff3281d8b83ed1 /Source | |
parent | 0fa7f69c0e2cdcd8b7ece400651ee7821b2ede4b (diff) | |
download | CMake-0b92602b816e2584db3781b120a1e5200da72ada.zip CMake-0b92602b816e2584db3781b120a1e5200da72ada.tar.gz CMake-0b92602b816e2584db3781b120a1e5200da72ada.tar.bz2 |
Add the $<LINKED:...> generator expression.
This is both a short form of using a TARGET_DEFINED expression
together with a TARGET_PROPERTY definition, and a way to strip
non-target content from interface properties when exporting.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmDocumentGeneratorExpressions.h | 8 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 66 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.h | 4 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionEvaluator.cxx | 85 |
4 files changed, 155 insertions, 8 deletions
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index 8b80a8a..3993f7d 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -51,6 +51,14 @@ "on the target tgt.\n" \ "Note that tgt is not added as a dependency of the target this " \ "expression is evaluated on.\n" \ + " $<LINKED:item> = An empty string if item is not a " \ + "target. If item is a target then the " \ + "INTERFACE_INCLUDE_DIRECTORIES or INTERFACE_COMPILE_DEFINITIONS " \ + "content is read from the target. " \ + "This generator expression can only be used in evaluation of the " \ + "INCLUDE_DIRECTORIES or COMPILE_DEFINITIONS property. Note that " \ + "this expression is for internal use and may be changed or removed " \ + "in the future.\n" \ " $<TARGET_POLICY:pol> = '1' if the policy was NEW when " \ "the 'head' target was created, else '0'. If the policy was not " \ "set, the warning message for the policy will be emitted. This " \ diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 2ecac84..7e4c3df 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -25,6 +25,8 @@ #include <cmsys/auto_ptr.hxx> +#include "assert.h" + //---------------------------------------------------------------------------- cmExportFileGenerator::cmExportFileGenerator() { @@ -160,7 +162,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, preprocessRule); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, target, + this->ResolveTargetsInGeneratorExpressions(prepro, target, propName, missingTargets); properties[outputName] = prepro; } @@ -324,13 +326,14 @@ static bool isGeneratorExpression(const std::string &lib) void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( std::string &input, - cmTarget* target, + cmTarget* target, const char *propName, std::vector<std::string> &missingTargets, FreeTargetsReplace replace) { if (replace == NoReplaceFreeTargets) { - this->ResolveTargetsInGeneratorExpression(input, target, missingTargets); + this->ResolveTargetsInGeneratorExpression(input, target, propName, + missingTargets); return; } std::vector<std::string> parts; @@ -349,7 +352,7 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( { this->ResolveTargetsInGeneratorExpression( *li, - target, + target, propName, missingTargets); } input += sep + *li; @@ -361,7 +364,7 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string &input, - cmTarget* target, + cmTarget* target, const char *propName, std::vector<std::string> &missingTargets) { std::string::size_type pos = 0; @@ -398,6 +401,57 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string errorString; pos = 0; lastPos = pos; + while((pos = input.find("$<LINKED:", lastPos)) != input.npos) + { + std::string::size_type nameStartPos = pos + sizeof("$<LINKED:") - 1; + std::string::size_type endPos = input.find(">", nameStartPos); + if (endPos == input.npos) + { + errorString = "$<LINKED:...> expression incomplete"; + break; + } + std::string targetName = input.substr(nameStartPos, + endPos - nameStartPos); + if(targetName.find("$<") != input.npos) + { + errorString = "$<LINKED:...> requires its parameter to be a " + "literal."; + break; + } + if (this->AddTargetNamespace(targetName, target, missingTargets)) + { + assert(propName); // The link libraries strings will + // never contain $<LINKED> + std::string replacement = "$<TARGET_PROPERTY:" + + targetName + "," + propName; + input.replace(pos, endPos - pos, replacement); + lastPos = pos + replacement.size() + 1; + } + else + { + if (pos != 0) + { + if (input[pos - 1] == ';') + { + --pos; + } + } + else if (input[endPos + 1] == ';') + { + ++endPos; + } + input.replace(pos, endPos - pos + 1, ""); + lastPos = pos; + } + } + if (!errorString.empty()) + { + mf->IssueMessage(cmake::FATAL_ERROR, errorString); + return; + } + + pos = 0; + lastPos = pos; while((pos = input.find("$<TARGET_NAME:", lastPos)) != input.npos) { std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1; @@ -491,7 +545,7 @@ cmExportFileGenerator preprocessRule); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, target, + this->ResolveTargetsInGeneratorExpressions(prepro, target, 0, missingTargets, ReplaceFreeTargets); properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro; diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 776be61..5ad27bf 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -119,7 +119,7 @@ protected: }; void ResolveTargetsInGeneratorExpressions(std::string &input, - cmTarget* target, + cmTarget* target, const char *propName, std::vector<std::string> &missingTargets, FreeTargetsReplace replace = NoReplaceFreeTargets); @@ -150,7 +150,7 @@ private: std::vector<std::string> &missingTargets); void ResolveTargetsInGeneratorExpression(std::string &input, - cmTarget* target, + cmTarget* target, const char *propName, std::vector<std::string> &missingTargets); virtual void ReplaceInstallPrefix(std::string &input); diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index fff7dab..cbea1d9 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -638,6 +638,89 @@ static const struct InstallPrefixNode : public cmGeneratorExpressionNode } installPrefixNode; //---------------------------------------------------------------------------- +static const struct LinkedNode : public cmGeneratorExpressionNode +{ + LinkedNode() {} + + virtual bool GeneratesContent() const { return true; } + virtual int NumExpectedParameters() const { return 1; } + virtual bool RequiresLiteralInput() const { return true; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (dagChecker->EvaluatingIncludeDirectories()) + { + return this->GetInterfaceProperty(parameters.front(), + "INCLUDE_DIRECTORIES", + context, content, dagChecker); + } + if (dagChecker->EvaluatingCompileDefinitions()) + { + return this->GetInterfaceProperty(parameters.front(), + "COMPILE_DEFINITIONS", + context, content, dagChecker); + } + + reportError(context, content->GetOriginalExpression(), + "$<LINKED:...> may only be used in INCLUDE_DIRECTORIES and " + "COMPILE_DEFINITIONS properties."); + + return std::string(); + } + +private: + std::string GetInterfaceProperty(const std::string &item, + const std::string &prop, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagCheckerParent) const + { + cmTarget *target = context->CurrentTarget + ->GetMakefile()->FindTargetToUse(item.c_str()); + if (!target) + { + return std::string(); + } + std::string propertyName = "INTERFACE_" + prop; + const char *propContent = target->GetProperty(propertyName.c_str()); + if (!propContent) + { + return std::string(); + } + + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, + target->GetName(), + propertyName, + content, + dagCheckerParent); + + switch (dagChecker.check()) + { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + dagChecker.reportError(context, content->GetOriginalExpression()); + return std::string(); + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return std::string(); + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + cmGeneratorExpression ge(context->Backtrace); + return ge.Parse(propContent)->Evaluate(context->Makefile, + context->Config, + context->Quiet, + context->HeadTarget, + target, + &dagChecker); + } + +} linkedNode; + +//---------------------------------------------------------------------------- template<bool linker, bool soname> struct TargetFilesystemArtifactResultCreator { @@ -874,6 +957,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &targetDefinedNode; else if (identifier == "INSTALL_PREFIX") return &installPrefixNode; + else if (identifier == "LINKED") + return &linkedNode; return 0; } |