summaryrefslogtreecommitdiffstats
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
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.
-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
-rw-r--r--Tests/CMakeCommands/target_link_libraries/CMakeLists.txt10
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depD.cpp13
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depD.h11
-rw-r--r--Tests/CMakeCommands/target_link_libraries/targetB.cpp10
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt33
-rw-r--r--Tests/ExportImport/Export/testSharedLibDepends.cpp8
-rw-r--r--Tests/ExportImport/Export/testSharedLibDepends.h14
-rw-r--r--Tests/ExportImport/Export/testSharedLibRequired.cpp7
-rw-r--r--Tests/ExportImport/Export/testSharedLibRequired.h12
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt11
-rw-r--r--Tests/ExportImport/Import/A/deps_shared_iface.cpp11
19 files changed, 425 insertions, 115 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
diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
index 746d30c..1551c50 100644
--- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
@@ -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)
diff --git a/Tests/CMakeCommands/target_link_libraries/depD.cpp b/Tests/CMakeCommands/target_link_libraries/depD.cpp
new file mode 100644
index 0000000..b02c76c
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depD.cpp
@@ -0,0 +1,13 @@
+
+#include "depD.h"
+
+int DepD::foo()
+{
+ return 0;
+}
+
+DepA DepD::getA()
+{
+ DepA a;
+ return a;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depD.h b/Tests/CMakeCommands/target_link_libraries/depD.h
new file mode 100644
index 0000000..d24ff5f
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depD.h
@@ -0,0 +1,11 @@
+
+#include "depd_export.h"
+
+#include "depA.h"
+
+struct DEPD_EXPORT DepD
+{
+ int foo();
+
+ DepA getA();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/targetB.cpp b/Tests/CMakeCommands/target_link_libraries/targetB.cpp
new file mode 100644
index 0000000..063d63a
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/targetB.cpp
@@ -0,0 +1,10 @@
+
+#include "depD.h"
+
+int main(int argc, char **argv)
+{
+ DepD d;
+ DepA a = d.getA();
+
+ return d.foo() + a.foo();
+}
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index 569845a..779d889 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -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)
diff --git a/Tests/ExportImport/Export/testSharedLibDepends.cpp b/Tests/ExportImport/Export/testSharedLibDepends.cpp
new file mode 100644
index 0000000..e279207
--- /dev/null
+++ b/Tests/ExportImport/Export/testSharedLibDepends.cpp
@@ -0,0 +1,8 @@
+
+#include "testSharedLibDepends.h"
+
+int TestSharedLibDepends::foo()
+{
+ TestSharedLibRequired req;
+ return req.foo();
+}
diff --git a/Tests/ExportImport/Export/testSharedLibDepends.h b/Tests/ExportImport/Export/testSharedLibDepends.h
new file mode 100644
index 0000000..b93143a
--- /dev/null
+++ b/Tests/ExportImport/Export/testSharedLibDepends.h
@@ -0,0 +1,14 @@
+
+#ifndef TESTSHAREDLIBDEPENDS_H
+#define TESTSHAREDLIBDEPENDS_H
+
+#include "testsharedlibdepends_export.h"
+
+#include "testSharedLibRequired.h"
+
+struct TESTSHAREDLIBDEPENDS_EXPORT TestSharedLibDepends
+{
+ int foo();
+};
+
+#endif
diff --git a/Tests/ExportImport/Export/testSharedLibRequired.cpp b/Tests/ExportImport/Export/testSharedLibRequired.cpp
new file mode 100644
index 0000000..1ac34aa
--- /dev/null
+++ b/Tests/ExportImport/Export/testSharedLibRequired.cpp
@@ -0,0 +1,7 @@
+
+#include "testSharedLibRequired.h"
+
+int TestSharedLibRequired::foo()
+{
+ return 0;
+}
diff --git a/Tests/ExportImport/Export/testSharedLibRequired.h b/Tests/ExportImport/Export/testSharedLibRequired.h
new file mode 100644
index 0000000..edaddd4
--- /dev/null
+++ b/Tests/ExportImport/Export/testSharedLibRequired.h
@@ -0,0 +1,12 @@
+
+#ifndef TESTSHAREDLIBREQUIRED_H
+#define TESTSHAREDLIBREQUIRED_H
+
+#include "testsharedlibrequired_export.h"
+
+struct TESTSHAREDLIBREQUIRED_EXPORT TestSharedLibRequired
+{
+ int foo();
+};
+
+#endif
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 56cfea0..abb2ab0 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -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>
+)
diff --git a/Tests/ExportImport/Import/A/deps_shared_iface.cpp b/Tests/ExportImport/Import/A/deps_shared_iface.cpp
new file mode 100644
index 0000000..4f7eb23
--- /dev/null
+++ b/Tests/ExportImport/Import/A/deps_shared_iface.cpp
@@ -0,0 +1,11 @@
+
+
+#include "testSharedLibDepends.h"
+
+int main(int,char **)
+{
+ TestSharedLibDepends dep;
+ TestSharedLibRequired req;
+
+ return dep.foo() + req.foo();
+}