Add API to extract target names from a genex string.

The TARGET_NAME expression, which requires a literal, provides
target names. $<TARGET_PROPERTY:tgt,prop> also provides target
names in the cases where tgt is a literal, so that TARGET_NAME is
not needed then in addition.
This commit is contained in:
Stephen Kelly 2012-12-10 23:07:09 +01:00
parent b0c8f73eb6
commit e04f737c7a
2 changed files with 140 additions and 0 deletions

View File

@ -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<std::string> &missingTargets)
{
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
cmMakefile *mf = target->GetMakefile();
std::string errorString;
while((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != input.npos)
{
std::string::size_type nameStartPos = pos +
sizeof("$<TARGET_PROPERTY:") - 1;
std::string::size_type closePos = 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 = "$<TARGET_PROPERTY:" + targetName + ",prop> 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("$<TARGET_NAME:", lastPos)) != input.npos)
{
std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1;
std::string::size_type endPos = input.find(">", nameStartPos);
if (endPos == input.npos)
{
errorString = "$<TARGET_NAME:...> expression incomplete";
}
const std::string targetName = input.substr(nameStartPos,
endPos - nameStartPos);
if(targetName.find("$<", lastPos) != input.npos)
{
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"literal.";
}
if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str()))
{
if(tgt->IsImported())
{
input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
targetName);
pos += sizeof("$<TARGET_NAME:") + targetName.size();
}
else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
{
input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
this->Namespace + targetName);
pos += sizeof("$<TARGET_NAME:") + targetName.size();
}
else
{
std::string namespacedTarget;
this->HandleMissingTarget(namespacedTarget, missingTargets,
mf, target, tgt);
if (!namespacedTarget.empty())
{
input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
namespacedTarget);
pos += sizeof("$<TARGET_NAME:") + targetName.size();
}
}
}
else
{
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"reachable target.";
}
lastPos = pos;
if (!errorString.empty())
{
break;
}
}
if (!errorString.empty())
{
mf->IssueMessage(cmake::FATAL_ERROR, errorString);
}
}
//----------------------------------------------------------------------------
void
cmExportFileGenerator

View File

@ -94,6 +94,10 @@ protected:
cmTarget* depender,
cmTarget* dependee) = 0;
void ResolveTargetsInGeneratorExpressions(std::string &input,
cmTarget* target,
std::vector<std::string> &missingTargets);
// The namespace in which the exports are placed in the generated file.
std::string Namespace;