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.
This commit is contained in:
commit
c0c8ef85fc
|
@ -107,6 +107,10 @@ cmExportBuildFileGenerator
|
||||||
std::vector<std::string> missingTargets;
|
std::vector<std::string> missingTargets;
|
||||||
this->SetImportDetailProperties(config, suffix,
|
this->SetImportDetailProperties(config, suffix,
|
||||||
target, properties, missingTargets);
|
target, properties, missingTargets);
|
||||||
|
this->SetImportLinkInterface(config, suffix,
|
||||||
|
cmGeneratorExpression::BuildInterface,
|
||||||
|
target, properties, missingTargets);
|
||||||
|
|
||||||
|
|
||||||
// TOOD: PUBLIC_HEADER_LOCATION
|
// TOOD: PUBLIC_HEADER_LOCATION
|
||||||
// This should wait until the build feature propagation stuff
|
// This should wait until the build feature propagation stuff
|
||||||
|
|
|
@ -183,9 +183,89 @@ 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
|
void
|
||||||
cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
|
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,
|
std::string &input,
|
||||||
cmTarget* target,
|
cmTarget* target,
|
||||||
std::vector<std::string> &missingTargets)
|
std::vector<std::string> &missingTargets)
|
||||||
|
@ -212,45 +292,17 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string targetName = input.substr(nameStartPos,
|
std::string targetName = input.substr(nameStartPos,
|
||||||
commaPos - nameStartPos);
|
commaPos - nameStartPos);
|
||||||
|
|
||||||
pos = nameStartPos; // We're not going to replace the entire expression,
|
if (!this->AddTargetNamespace(targetName, target, missingTargets))
|
||||||
// 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 "
|
errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires "
|
||||||
"its first parameter to be a reachable target.";
|
"its first parameter to be a reachable target.";
|
||||||
}
|
|
||||||
lastPos = pos;
|
|
||||||
if (!errorString.empty())
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
input.replace(nameStartPos, commaPos - nameStartPos, targetName);
|
||||||
|
lastPos = pos + targetName.size();
|
||||||
}
|
}
|
||||||
if (!errorString.empty())
|
if (!errorString.empty())
|
||||||
{
|
{
|
||||||
|
@ -267,51 +319,24 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
|
||||||
if (endPos == input.npos)
|
if (endPos == input.npos)
|
||||||
{
|
{
|
||||||
errorString = "$<TARGET_NAME:...> expression incomplete";
|
errorString = "$<TARGET_NAME:...> expression incomplete";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
const std::string targetName = input.substr(nameStartPos,
|
std::string targetName = input.substr(nameStartPos,
|
||||||
endPos - nameStartPos);
|
endPos - nameStartPos);
|
||||||
if(targetName.find("$<", lastPos) != input.npos)
|
if(targetName.find("$<") != input.npos)
|
||||||
{
|
{
|
||||||
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
|
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
|
||||||
"literal.";
|
"literal.";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str()))
|
if (!this->AddTargetNamespace(targetName, target, missingTargets))
|
||||||
{
|
|
||||||
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 "
|
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
|
||||||
"reachable target.";
|
"reachable target.";
|
||||||
}
|
|
||||||
lastPos = pos;
|
|
||||||
if (!errorString.empty())
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
input.replace(pos, endPos - pos + 1, targetName);
|
||||||
|
lastPos = endPos;
|
||||||
}
|
}
|
||||||
if (!errorString.empty())
|
if (!errorString.empty())
|
||||||
{
|
{
|
||||||
|
@ -319,6 +344,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
|
void
|
||||||
cmExportFileGenerator
|
cmExportFileGenerator
|
||||||
|
@ -363,9 +446,7 @@ cmExportFileGenerator
|
||||||
this->SetImportLinkProperty(suffix, target,
|
this->SetImportLinkProperty(suffix, target,
|
||||||
"IMPORTED_LINK_INTERFACE_LANGUAGES",
|
"IMPORTED_LINK_INTERFACE_LANGUAGES",
|
||||||
iface->Languages, properties, missingTargets);
|
iface->Languages, properties, missingTargets);
|
||||||
this->SetImportLinkProperty(suffix, target,
|
|
||||||
"IMPORTED_LINK_INTERFACE_LIBRARIES",
|
|
||||||
iface->Libraries, properties, missingTargets);
|
|
||||||
this->SetImportLinkProperty(suffix, target,
|
this->SetImportLinkProperty(suffix, target,
|
||||||
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
|
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
|
||||||
iface->SharedDeps, properties, missingTargets);
|
iface->SharedDeps, properties, missingTargets);
|
||||||
|
@ -397,9 +478,6 @@ cmExportFileGenerator
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the makefile in which to lookup target information.
|
|
||||||
cmMakefile* mf = target->GetMakefile();
|
|
||||||
|
|
||||||
// Construct the property value.
|
// Construct the property value.
|
||||||
std::string link_libs;
|
std::string link_libs;
|
||||||
const char* sep = "";
|
const char* sep = "";
|
||||||
|
@ -410,33 +488,9 @@ cmExportFileGenerator
|
||||||
link_libs += sep;
|
link_libs += sep;
|
||||||
sep = ";";
|
sep = ";";
|
||||||
|
|
||||||
// Append this entry.
|
std::string temp = *li;
|
||||||
if(cmTarget* tgt = mf->FindTargetToUse(li->c_str()))
|
this->AddTargetNamespace(temp, target, missingTargets);
|
||||||
{
|
link_libs += temp;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the property.
|
// Store the property.
|
||||||
|
|
|
@ -102,9 +102,20 @@ protected:
|
||||||
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
|
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
|
||||||
const ImportPropertyMap &properties);
|
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,
|
void ResolveTargetsInGeneratorExpressions(std::string &input,
|
||||||
cmTarget* target,
|
cmTarget* target,
|
||||||
std::vector<std::string> &missingTargets);
|
std::vector<std::string> &missingTargets,
|
||||||
|
FreeTargetsReplace replace = NoReplaceFreeTargets);
|
||||||
|
|
||||||
// The namespace in which the exports are placed in the generated file.
|
// The namespace in which the exports are placed in the generated file.
|
||||||
std::string Namespace;
|
std::string Namespace;
|
||||||
|
@ -128,6 +139,13 @@ private:
|
||||||
cmGeneratorExpression::PreprocessContext,
|
cmGeneratorExpression::PreprocessContext,
|
||||||
ImportPropertyMap &properties,
|
ImportPropertyMap &properties,
|
||||||
std::vector<std::string> &missingTargets);
|
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
|
#endif
|
||||||
|
|
|
@ -229,6 +229,10 @@ cmExportInstallFileGenerator
|
||||||
this->SetImportDetailProperties(config, suffix,
|
this->SetImportDetailProperties(config, suffix,
|
||||||
te->Target, properties, missingTargets);
|
te->Target, properties, missingTargets);
|
||||||
|
|
||||||
|
this->SetImportLinkInterface(config, suffix,
|
||||||
|
cmGeneratorExpression::InstallInterface,
|
||||||
|
te->Target, properties, missingTargets);
|
||||||
|
|
||||||
// TOOD: PUBLIC_HEADER_LOCATION
|
// TOOD: PUBLIC_HEADER_LOCATION
|
||||||
// This should wait until the build feature propagation stuff
|
// This should wait until the build feature propagation stuff
|
||||||
// is done. Then this can be a propagated include directory.
|
// is done. Then this can be a propagated include directory.
|
||||||
|
|
|
@ -250,6 +250,67 @@ static std::string stripExportInterface(const std::string &input,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
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,
|
std::string cmGeneratorExpression::Preprocess(const std::string &input,
|
||||||
PreprocessContext context)
|
PreprocessContext context)
|
||||||
|
|
|
@ -59,6 +59,9 @@ public:
|
||||||
static std::string Preprocess(const std::string &input,
|
static std::string Preprocess(const std::string &input,
|
||||||
PreprocessContext context);
|
PreprocessContext context);
|
||||||
|
|
||||||
|
static void Split(const std::string &input,
|
||||||
|
std::vector<std::string> &output);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cmGeneratorExpression(const cmGeneratorExpression &);
|
cmGeneratorExpression(const cmGeneratorExpression &);
|
||||||
void operator=(const cmGeneratorExpression &);
|
void operator=(const cmGeneratorExpression &);
|
||||||
|
|
|
@ -4896,16 +4896,30 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
||||||
{
|
{
|
||||||
std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
|
std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
|
||||||
linkProp += suffix;
|
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,
|
linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
|
||||||
info.LinkInterface.Libraries);
|
propertyLibs = this->GetProperty(linkProp.c_str());
|
||||||
}
|
}
|
||||||
else if(const char* libs =
|
if(propertyLibs)
|
||||||
this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
|
|
||||||
{
|
{
|
||||||
cmSystemTools::ExpandListArgument(libs,
|
cmListFileBacktrace lfbt;
|
||||||
info.LinkInterface.Libraries);
|
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
|
// An explicit list of interface libraries may be set for shared
|
||||||
// libraries and executables that export symbols.
|
// libraries and executables that export symbols.
|
||||||
const char* explicitLibraries = 0;
|
const char* explicitLibraries = 0;
|
||||||
|
std::string linkIfaceProp;
|
||||||
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||||
this->IsExecutableWithExports())
|
this->IsExecutableWithExports())
|
||||||
{
|
{
|
||||||
// Lookup the per-configuration property.
|
// Lookup the per-configuration property.
|
||||||
std::string propName = "LINK_INTERFACE_LIBRARIES";
|
linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
|
||||||
propName += suffix;
|
linkIfaceProp += suffix;
|
||||||
explicitLibraries = this->GetProperty(propName.c_str());
|
explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
|
||||||
|
|
||||||
// If not set, try the generic property.
|
// If not set, try the generic property.
|
||||||
if(!explicitLibraries)
|
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)
|
if(explicitLibraries)
|
||||||
{
|
{
|
||||||
// The interface libraries have been explicitly set.
|
// 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)
|
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.
|
// The link implementation is the default link interface.
|
||||||
LinkImplementation const* impl = this->GetLinkImplementation(config,
|
LinkImplementation const* impl = this->GetLinkImplementation(config,
|
||||||
headTarget);
|
headTarget);
|
||||||
|
iface.ImplementationIsInterface = true;
|
||||||
iface.Libraries = impl->Libraries;
|
iface.Libraries = impl->Libraries;
|
||||||
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
|
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
|
||||||
if(this->GetType() == cmTarget::STATIC_LIBRARY)
|
if(this->GetType() == cmTarget::STATIC_LIBRARY)
|
||||||
|
|
|
@ -258,7 +258,9 @@ public:
|
||||||
// Needed only for OLD behavior of CMP0003.
|
// Needed only for OLD behavior of CMP0003.
|
||||||
std::vector<std::string> WrongConfigLibraries;
|
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
|
/** Get the link interface for the given configuration. Returns 0
|
||||||
|
|
|
@ -80,3 +80,13 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
|
||||||
add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp)
|
add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp)
|
||||||
generate_export_header(depIfaceOnly)
|
generate_export_header(depIfaceOnly)
|
||||||
set_property(TARGET depB APPEND PROPERTY LINK_INTERFACE_LIBRARIES depIfaceOnly)
|
set_property(TARGET depB APPEND PROPERTY LINK_INTERFACE_LIBRARIES depIfaceOnly)
|
||||||
|
|
||||||
|
add_library(depD SHARED depD.cpp)
|
||||||
|
generate_export_header(depD)
|
||||||
|
set_property(TARGET depD APPEND PROPERTY
|
||||||
|
LINK_INTERFACE_LIBRARIES
|
||||||
|
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:depA>
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(targetB targetB.cpp)
|
||||||
|
target_link_libraries(targetB depD)
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
#include "depD.h"
|
||||||
|
|
||||||
|
int DepD::foo()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DepA DepD::getA()
|
||||||
|
{
|
||||||
|
DepA a;
|
||||||
|
return a;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#include "depd_export.h"
|
||||||
|
|
||||||
|
#include "depA.h"
|
||||||
|
|
||||||
|
struct DEPD_EXPORT DepD
|
||||||
|
{
|
||||||
|
int foo();
|
||||||
|
|
||||||
|
DepA getA();
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#include "depD.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
DepD d;
|
||||||
|
DepA a = d.getA();
|
||||||
|
|
||||||
|
return d.foo() + a.foo();
|
||||||
|
}
|
|
@ -158,6 +158,36 @@ set_property(TARGET testLibRequired APPEND PROPERTY
|
||||||
$<INSTALL_INTERFACE:InstallOnly_DEFINE>
|
$<INSTALL_INTERFACE:InstallOnly_DEFINE>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
include(GenerateExportHeader)
|
||||||
|
|
||||||
|
add_library(testSharedLibRequired SHARED testSharedLibRequired.cpp)
|
||||||
|
generate_export_header(testSharedLibRequired)
|
||||||
|
set_property(TARGET testSharedLibRequired APPEND PROPERTY
|
||||||
|
INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
)
|
||||||
|
set_property(TARGET testSharedLibRequired APPEND PROPERTY
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(testSharedLibDepends SHARED testSharedLibDepends.cpp)
|
||||||
|
set_property(TARGET testSharedLibDepends APPEND PROPERTY
|
||||||
|
INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
)
|
||||||
|
generate_export_header(testSharedLibDepends)
|
||||||
|
|
||||||
|
set_property(TARGET testSharedLibDepends APPEND PROPERTY
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES
|
||||||
|
$<TARGET_PROPERTY:testSharedLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
|
)
|
||||||
|
set_property(TARGET testSharedLibDepends APPEND PROPERTY
|
||||||
|
LINK_INTERFACE_LIBRARIES
|
||||||
|
$<1:$<TARGET_NAME:testSharedLibRequired>>
|
||||||
|
)
|
||||||
|
|
||||||
|
# LINK_PRIVATE because the LINK_INTERFACE_LIBRARIES is specified above.
|
||||||
|
target_link_libraries(testSharedLibDepends LINK_PRIVATE testSharedLibRequired)
|
||||||
|
|
||||||
install(TARGETS testLibRequired
|
install(TARGETS testLibRequired
|
||||||
testLibIncludeRequired1
|
testLibIncludeRequired1
|
||||||
testLibIncludeRequired2
|
testLibIncludeRequired2
|
||||||
|
@ -165,10 +195,11 @@ install(TARGETS testLibRequired
|
||||||
testLibIncludeRequired4
|
testLibIncludeRequired4
|
||||||
testLibIncludeRequired5
|
testLibIncludeRequired5
|
||||||
testLibIncludeRequired6
|
testLibIncludeRequired6
|
||||||
|
testSharedLibRequired
|
||||||
EXPORT RequiredExp DESTINATION lib )
|
EXPORT RequiredExp DESTINATION lib )
|
||||||
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired)
|
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired)
|
||||||
|
|
||||||
install(TARGETS testLibDepends EXPORT DependsExp DESTINATION lib )
|
install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib )
|
||||||
install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends)
|
install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
#include "testSharedLibDepends.h"
|
||||||
|
|
||||||
|
int TestSharedLibDepends::foo()
|
||||||
|
{
|
||||||
|
TestSharedLibRequired req;
|
||||||
|
return req.foo();
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
#ifndef TESTSHAREDLIBDEPENDS_H
|
||||||
|
#define TESTSHAREDLIBDEPENDS_H
|
||||||
|
|
||||||
|
#include "testsharedlibdepends_export.h"
|
||||||
|
|
||||||
|
#include "testSharedLibRequired.h"
|
||||||
|
|
||||||
|
struct TESTSHAREDLIBDEPENDS_EXPORT TestSharedLibDepends
|
||||||
|
{
|
||||||
|
int foo();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include "testSharedLibRequired.h"
|
||||||
|
|
||||||
|
int TestSharedLibRequired::foo()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
#ifndef TESTSHAREDLIBREQUIRED_H
|
||||||
|
#define TESTSHAREDLIBREQUIRED_H
|
||||||
|
|
||||||
|
#include "testsharedlibrequired_export.h"
|
||||||
|
|
||||||
|
struct TESTSHAREDLIBREQUIRED_EXPORT TestSharedLibRequired
|
||||||
|
{
|
||||||
|
int foo();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -167,3 +167,14 @@ set_property(TARGET deps_iface APPEND PROPERTY
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
$<TARGET_PROPERTY:testLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
|
$<TARGET_PROPERTY:testLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_executable(deps_shared_iface deps_shared_iface.cpp)
|
||||||
|
target_link_libraries(deps_shared_iface testSharedLibDepends)
|
||||||
|
set_property(TARGET deps_shared_iface APPEND PROPERTY
|
||||||
|
COMPILE_DEFINITIONS
|
||||||
|
$<TARGET_PROPERTY:testSharedLibDepends,INTERFACE_COMPILE_DEFINITIONS>
|
||||||
|
)
|
||||||
|
set_property(TARGET deps_shared_iface APPEND PROPERTY
|
||||||
|
INCLUDE_DIRECTORIES
|
||||||
|
$<TARGET_PROPERTY:testSharedLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include "testSharedLibDepends.h"
|
||||||
|
|
||||||
|
int main(int,char **)
|
||||||
|
{
|
||||||
|
TestSharedLibDepends dep;
|
||||||
|
TestSharedLibRequired req;
|
||||||
|
|
||||||
|
return dep.foo() + req.foo();
|
||||||
|
}
|
Loading…
Reference in New Issue