From e04f737c7a3e66c49e2d50813af1fa40a415eff8 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 10 Dec 2012 23:07:09 +0100 Subject: [PATCH] Add API to extract target names from a genex string. The TARGET_NAME expression, which requires a literal, provides target names. $ also provides target names in the cases where tgt is a literal, so that TARGET_NAME is not needed then in addition. --- Source/cmExportFileGenerator.cxx | 136 +++++++++++++++++++++++++++++++ Source/cmExportFileGenerator.h | 4 + 2 files changed, 140 insertions(+) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 3f738ccde..2507b72ab 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -124,6 +124,142 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, this->GenerateImportTargetsConfig(os, config, suffix); } +//---------------------------------------------------------------------------- +void +cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( + std::string &input, + cmTarget* target, + std::vector &missingTargets) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + + cmMakefile *mf = target->GetMakefile(); + std::string errorString; + + while((pos = input.find("$", nameStartPos); + std::string::size_type commaPos = input.find(",", nameStartPos); + std::string::size_type nextOpenPos = input.find("$<", nameStartPos); + if (commaPos == input.npos // Implied 'this' target + || closePos == input.npos // Imcomplete expression. + || closePos < commaPos // Implied 'this' target + || nextOpenPos < commaPos) // Non-literal + { + lastPos = nameStartPos; + continue; + } + + const std::string targetName = input.substr(nameStartPos, + commaPos - nameStartPos); + + pos = nameStartPos; // We're not going to replace the entire expression, + // but only the target parameter. + if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) + { + if(tgt->IsImported()) + { + pos += targetName.size(); + } + else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) + { + input.replace(pos, targetName.size(), + this->Namespace + targetName); + pos += this->Namespace.size() + targetName.size(); + } + else + { + std::string namespacedTarget; + this->HandleMissingTarget(namespacedTarget, missingTargets, + mf, target, tgt); + if (!namespacedTarget.empty()) + { + input.replace(pos, targetName.size(), namespacedTarget); + pos += namespacedTarget.size(); + } + } + } + else + { + errorString = "$ requires " + "its first parameter to be a reachable target."; + } + lastPos = pos; + if (!errorString.empty()) + { + break; + } + } + if (!errorString.empty()) + { + mf->IssueMessage(cmake::FATAL_ERROR, errorString); + return; + } + + pos = 0; + lastPos = pos; + while((pos = input.find("$", nameStartPos); + if (endPos == input.npos) + { + errorString = "$ expression incomplete"; + } + const std::string targetName = input.substr(nameStartPos, + endPos - nameStartPos); + if(targetName.find("$<", lastPos) != input.npos) + { + errorString = "$ requires its parameter to be a " + "literal."; + } + if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) + { + if(tgt->IsImported()) + { + input.replace(pos, sizeof("$ExportedTargets.find(tgt) != this->ExportedTargets.end()) + { + input.replace(pos, sizeof("$Namespace + targetName); + pos += sizeof("$HandleMissingTarget(namespacedTarget, missingTargets, + mf, target, tgt); + if (!namespacedTarget.empty()) + { + input.replace(pos, sizeof("$IssueMessage(cmake::FATAL_ERROR, errorString); + } +} + //---------------------------------------------------------------------------- void cmExportFileGenerator diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 4a75c52d5..0b89a642d 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -94,6 +94,10 @@ protected: cmTarget* depender, cmTarget* dependee) = 0; + void ResolveTargetsInGeneratorExpressions(std::string &input, + cmTarget* target, + std::vector &missingTargets); + // The namespace in which the exports are placed in the generated file. std::string Namespace;