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;
|
||||
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
|
||||
|
|
|
@ -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
|
||||
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)
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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
|
||||
cmExportFileGenerator
|
||||
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -250,6 +250,67 @@ static std::string stripExportInterface(const std::string &input,
|
|||
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,
|
||||
PreprocessContext context)
|
||||
|
|
|
@ -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 &);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -80,3 +80,13 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
|
|||
add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp)
|
||||
generate_export_header(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>
|
||||
)
|
||||
|
||||
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
|
||||
testLibIncludeRequired1
|
||||
testLibIncludeRequired2
|
||||
|
@ -165,10 +195,11 @@ install(TARGETS testLibRequired
|
|||
testLibIncludeRequired4
|
||||
testLibIncludeRequired5
|
||||
testLibIncludeRequired6
|
||||
testSharedLibRequired
|
||||
EXPORT RequiredExp DESTINATION lib )
|
||||
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)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
$<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