summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2013-01-11 16:32:13 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2013-01-11 16:32:13 (GMT)
commitc0c8ef85fc8d65a47abfd293031bcde91e7ee930 (patch)
treeb6757f134e0f5ba48b6fe656d55a97eeb60535d5 /Source
parentffe93315a2554c16f7bb46a35a848602cea229f9 (diff)
parent77d26467848fd689fbbffbaa302d041aa2365b15 (diff)
downloadCMake-c0c8ef85fc8d65a47abfd293031bcde91e7ee930.zip
CMake-c0c8ef85fc8d65a47abfd293031bcde91e7ee930.tar.gz
CMake-c0c8ef85fc8d65a47abfd293031bcde91e7ee930.tar.bz2
Merge topic 'LINK_INTERFACE_LIBRARIES-genex'
77d2646 Allow generator expressions in LINK_INTERFACE_LIBRARIES. 94aeaf7 Split LINK_INTERFACE_LIBRARIES export handling into dedicated method. a3aedb8 Split the generator expression before extracting targets. b6036d1 Extract the AddTargetNamespace method. cb1afbf Don't pass a position when determining if a target name is a literal. f99196d Add cmGeneratorExpression::Split() API.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmExportBuildFileGenerator.cxx4
-rw-r--r--Source/cmExportFileGenerator.cxx252
-rw-r--r--Source/cmExportFileGenerator.h22
-rw-r--r--Source/cmExportInstallFileGenerator.cxx4
-rw-r--r--Source/cmGeneratorExpression.cxx61
-rw-r--r--Source/cmGeneratorExpression.h3
-rw-r--r--Source/cmTarget.cxx50
-rw-r--r--Source/cmTarget.h4
8 files changed, 286 insertions, 114 deletions
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 9533319..29f6743 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -107,6 +107,10 @@ cmExportBuildFileGenerator
std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix,
target, properties, missingTargets);
+ this->SetImportLinkInterface(config, suffix,
+ cmGeneratorExpression::BuildInterface,
+ target, properties, missingTargets);
+
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 90c0c41..94e24c7 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -184,10 +184,90 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
}
//----------------------------------------------------------------------------
+bool
+cmExportFileGenerator::AddTargetNamespace(std::string &input,
+ cmTarget* target,
+ std::vector<std::string> &missingTargets)
+{
+ cmMakefile *mf = target->GetMakefile();
+
+ cmTarget *tgt = mf->FindTargetToUse(input.c_str());
+ if (!tgt)
+ {
+ return false;
+ }
+
+ if(tgt->IsImported())
+ {
+ return true;
+ }
+ if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
+ {
+ input = this->Namespace + input;
+ }
+ else
+ {
+ std::string namespacedTarget;
+ this->HandleMissingTarget(namespacedTarget, missingTargets,
+ mf, target, tgt);
+ if (!namespacedTarget.empty())
+ {
+ input = namespacedTarget;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+static bool isGeneratorExpression(const std::string &lib)
+{
+ const std::string::size_type openpos = lib.find("$<");
+ return (openpos != std::string::npos)
+ && (lib.find(">", openpos) != std::string::npos);
+}
+
+//----------------------------------------------------------------------------
void
cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
std::string &input,
cmTarget* target,
+ std::vector<std::string> &missingTargets,
+ FreeTargetsReplace replace)
+{
+ if (replace == NoReplaceFreeTargets)
+ {
+ this->ResolveTargetsInGeneratorExpression(input, target, missingTargets);
+ return;
+ }
+ std::vector<std::string> parts;
+ cmGeneratorExpression::Split(input, parts);
+
+ std::string sep;
+ input = "";
+ for(std::vector<std::string>::iterator li = parts.begin();
+ li != parts.end(); ++li)
+ {
+ if (!isGeneratorExpression(*li))
+ {
+ this->AddTargetNamespace(*li, target, missingTargets);
+ }
+ else
+ {
+ this->ResolveTargetsInGeneratorExpression(
+ *li,
+ target,
+ missingTargets);
+ }
+ input += sep + *li;
+ sep = ";";
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
+ std::string &input,
+ cmTarget* target,
std::vector<std::string> &missingTargets)
{
std::string::size_type pos = 0;
@@ -212,45 +292,17 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
continue;
}
- const std::string targetName = input.substr(nameStartPos,
+ 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
+ if (!this->AddTargetNamespace(targetName, target, missingTargets))
{
errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires "
"its first parameter to be a reachable target.";
- }
- lastPos = pos;
- if (!errorString.empty())
- {
break;
}
+ input.replace(nameStartPos, commaPos - nameStartPos, targetName);
+ lastPos = pos + targetName.size();
}
if (!errorString.empty())
{
@@ -267,51 +319,24 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
if (endPos == input.npos)
{
errorString = "$<TARGET_NAME:...> expression incomplete";
+ break;
}
- const std::string targetName = input.substr(nameStartPos,
+ std::string targetName = input.substr(nameStartPos,
endPos - nameStartPos);
- if(targetName.find("$<", lastPos) != input.npos)
+ if(targetName.find("$<") != input.npos)
{
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"literal.";
+ break;
}
- 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
+ if (!this->AddTargetNamespace(targetName, target, missingTargets))
{
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"reachable target.";
- }
- lastPos = pos;
- if (!errorString.empty())
- {
break;
}
+ input.replace(pos, endPos - pos + 1, targetName);
+ lastPos = endPos;
}
if (!errorString.empty())
{
@@ -322,6 +347,64 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
//----------------------------------------------------------------------------
void
cmExportFileGenerator
+::SetImportLinkInterface(const char* config, std::string const& suffix,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmTarget* target, ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets)
+{
+ // Add the transitive link dependencies for this configuration.
+ cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
+ target);
+ if (!iface)
+ {
+ return;
+ }
+
+ if (iface->ImplementationIsInterface)
+ {
+ this->SetImportLinkProperty(suffix, target,
+ "IMPORTED_LINK_INTERFACE_LIBRARIES",
+ iface->Libraries, properties, missingTargets);
+ return;
+ }
+
+ const char *propContent;
+
+ if (const char *prop_suffixed = target->GetProperty(
+ ("LINK_INTERFACE_LIBRARIES" + suffix).c_str()))
+ {
+ propContent = prop_suffixed;
+ }
+ else if (const char *prop = target->GetProperty(
+ "LINK_INTERFACE_LIBRARIES"))
+ {
+ propContent = prop;
+ }
+ else
+ {
+ return;
+ }
+
+ if (!*propContent)
+ {
+ properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = "";
+ return;
+ }
+
+ std::string prepro = cmGeneratorExpression::Preprocess(propContent,
+ preprocessRule);
+ if (!prepro.empty())
+ {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target,
+ missingTargets,
+ ReplaceFreeTargets);
+ properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator
::SetImportDetailProperties(const char* config, std::string const& suffix,
cmTarget* target, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets
@@ -363,9 +446,7 @@ cmExportFileGenerator
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES",
iface->Languages, properties, missingTargets);
- this->SetImportLinkProperty(suffix, target,
- "IMPORTED_LINK_INTERFACE_LIBRARIES",
- iface->Libraries, properties, missingTargets);
+
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
iface->SharedDeps, properties, missingTargets);
@@ -397,9 +478,6 @@ cmExportFileGenerator
return;
}
- // Get the makefile in which to lookup target information.
- cmMakefile* mf = target->GetMakefile();
-
// Construct the property value.
std::string link_libs;
const char* sep = "";
@@ -410,33 +488,9 @@ cmExportFileGenerator
link_libs += sep;
sep = ";";
- // Append this entry.
- if(cmTarget* tgt = mf->FindTargetToUse(li->c_str()))
- {
- // This is a target.
- if(tgt->IsImported())
- {
- // The target is imported (and therefore is not in the
- // export). Append the raw name.
- link_libs += *li;
- }
- else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
- {
- // The target is in the export. Append it with the export
- // namespace.
- link_libs += this->Namespace;
- link_libs += *li;
- }
- else
- {
- this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt);
- }
- }
- else
- {
- // Append the raw name.
- link_libs += *li;
- }
+ std::string temp = *li;
+ this->AddTargetNamespace(temp, target, missingTargets);
+ link_libs += temp;
}
// Store the property.
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 7c58ad8..4d97a63 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -102,9 +102,20 @@ protected:
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
const ImportPropertyMap &properties);
+ void SetImportLinkInterface(const char* config, std::string const& suffix,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmTarget* target, ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets);
+
+ enum FreeTargetsReplace {
+ ReplaceFreeTargets,
+ NoReplaceFreeTargets
+ };
+
void ResolveTargetsInGeneratorExpressions(std::string &input,
- cmTarget* target,
- std::vector<std::string> &missingTargets);
+ cmTarget* target,
+ std::vector<std::string> &missingTargets,
+ FreeTargetsReplace replace = NoReplaceFreeTargets);
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
@@ -128,6 +139,13 @@ private:
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets);
+
+ bool AddTargetNamespace(std::string &input, cmTarget* target,
+ std::vector<std::string> &missingTargets);
+
+ void ResolveTargetsInGeneratorExpression(std::string &input,
+ cmTarget* target,
+ std::vector<std::string> &missingTargets);
};
#endif
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index bc953c9..68881a1 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -229,6 +229,10 @@ cmExportInstallFileGenerator
this->SetImportDetailProperties(config, suffix,
te->Target, properties, missingTargets);
+ this->SetImportLinkInterface(config, suffix,
+ cmGeneratorExpression::InstallInterface,
+ te->Target, properties, missingTargets);
+
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
// is done. Then this can be a propagated include directory.
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 4063697..d306dee 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -251,6 +251,67 @@ static std::string stripExportInterface(const std::string &input,
}
//----------------------------------------------------------------------------
+void cmGeneratorExpression::Split(const std::string &input,
+ std::vector<std::string> &output)
+{
+ std::string::size_type pos = 0;
+ std::string::size_type lastPos = pos;
+ while((pos = input.find("$<", lastPos)) != input.npos)
+ {
+ std::string part = input.substr(lastPos, pos - lastPos);
+ std::string preGenex;
+ if (!part.empty())
+ {
+ std::string::size_type startPos = input.rfind(";", pos);
+ if (startPos != pos - 1 && startPos >= lastPos)
+ {
+ part = input.substr(lastPos, startPos - lastPos);
+ preGenex = input.substr(startPos + 1, pos - startPos - 1);
+ }
+ cmSystemTools::ExpandListArgument(part.c_str(), output);
+ }
+ pos += 2;
+ int nestingLevel = 1;
+ const char *c = input.c_str() + pos;
+ const char * const cStart = c;
+ for ( ; *c; ++c)
+ {
+ if(c[0] == '$' && c[1] == '<')
+ {
+ ++nestingLevel;
+ ++c;
+ continue;
+ }
+ if(c[0] == '>')
+ {
+ --nestingLevel;
+ if (nestingLevel == 0)
+ {
+ break;
+ }
+ }
+ }
+ for ( ; *c; ++c)
+ {
+ // Capture the part after the genex and before the next ';'
+ if(c[0] == ';')
+ {
+ --c;
+ break;
+ }
+ }
+ const std::string::size_type traversed = (c - cStart) + 1;
+ output.push_back(preGenex + "$<" + input.substr(pos, traversed));
+ pos += traversed;
+ lastPos = pos;
+ }
+ if (lastPos < input.size())
+ {
+ cmSystemTools::ExpandListArgument(input.substr(lastPos), output);
+ }
+}
+
+//----------------------------------------------------------------------------
std::string cmGeneratorExpression::Preprocess(const std::string &input,
PreprocessContext context)
{
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index b58dde5..8f1aef6 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -59,6 +59,9 @@ public:
static std::string Preprocess(const std::string &input,
PreprocessContext context);
+ static void Split(const std::string &input,
+ std::vector<std::string> &output);
+
private:
cmGeneratorExpression(const cmGeneratorExpression &);
void operator=(const cmGeneratorExpression &);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 2cfb1bf..9b50b8e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -4896,16 +4896,30 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
{
std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
linkProp += suffix;
- if(const char* config_libs = this->GetProperty(linkProp.c_str()))
+
+ const char *propertyLibs = this->GetProperty(linkProp.c_str());
+
+ if(!propertyLibs)
{
- cmSystemTools::ExpandListArgument(config_libs,
- info.LinkInterface.Libraries);
+ linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+ propertyLibs = this->GetProperty(linkProp.c_str());
}
- else if(const char* libs =
- this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
+ if(propertyLibs)
{
- cmSystemTools::ExpandListArgument(libs,
- info.LinkInterface.Libraries);
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ linkProp, 0, 0);
+ cmSystemTools::ExpandListArgument(ge.Parse(propertyLibs)
+ ->Evaluate(this->Makefile,
+ desired_config.c_str(),
+ false,
+ headTarget,
+ this,
+ &dagChecker),
+ info.LinkInterface.Libraries);
}
}
@@ -5019,18 +5033,20 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// An explicit list of interface libraries may be set for shared
// libraries and executables that export symbols.
const char* explicitLibraries = 0;
+ std::string linkIfaceProp;
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->IsExecutableWithExports())
{
// Lookup the per-configuration property.
- std::string propName = "LINK_INTERFACE_LIBRARIES";
- propName += suffix;
- explicitLibraries = this->GetProperty(propName.c_str());
+ linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
+ linkIfaceProp += suffix;
+ explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
// If not set, try the generic property.
if(!explicitLibraries)
{
- explicitLibraries = this->GetProperty("LINK_INTERFACE_LIBRARIES");
+ linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
+ explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
}
}
@@ -5048,7 +5064,16 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
if(explicitLibraries)
{
// The interface libraries have been explicitly set.
- cmSystemTools::ExpandListArgument(explicitLibraries, iface.Libraries);
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
+ linkIfaceProp, 0, 0);
+ cmSystemTools::ExpandListArgument(ge.Parse(explicitLibraries)->Evaluate(
+ this->Makefile,
+ config,
+ false,
+ headTarget,
+ this, &dagChecker), iface.Libraries);
if(this->GetType() == cmTarget::SHARED_LIBRARY)
{
@@ -5091,6 +5116,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// The link implementation is the default link interface.
LinkImplementation const* impl = this->GetLinkImplementation(config,
headTarget);
+ iface.ImplementationIsInterface = true;
iface.Libraries = impl->Libraries;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
if(this->GetType() == cmTarget::STATIC_LIBRARY)
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 1188a6a..b4d053d 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -258,7 +258,9 @@ public:
// Needed only for OLD behavior of CMP0003.
std::vector<std::string> WrongConfigLibraries;
- LinkInterface(): Multiplicity(0) {}
+ bool ImplementationIsInterface;
+
+ LinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {}
};
/** Get the link interface for the given configuration. Returns 0