summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/cmAddLibraryCommand.cxx30
-rw-r--r--Source/cmAddLibraryCommand.h10
-rw-r--r--Source/cmComputeLinkDepends.cxx7
-rw-r--r--Source/cmComputeLinkInformation.cxx5
-rw-r--r--Source/cmGlobalGenerator.cxx4
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx7
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx8
-rw-r--r--Source/cmGlobalVisualStudio6Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx4
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx25
-rw-r--r--Source/cmInstallTargetGenerator.cxx5
-rw-r--r--Source/cmLocalGenerator.cxx8
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx4
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx10
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx12
-rw-r--r--Source/cmMakefile.cxx5
-rw-r--r--Source/cmMakefileTargetGenerator.cxx7
-rw-r--r--Source/cmTarget.cxx108
-rw-r--r--Source/cmTarget.h1
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx14
-rw-r--r--Source/cmTargetPropCommandBase.cxx9
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx8
-rw-r--r--Tests/AliasTarget/CMakeLists.txt3
-rw-r--r--Tests/CMakeLists.txt1
-rw-r--r--Tests/CompatibleInterface/CMakeLists.txt2
-rw-r--r--Tests/InterfaceLibrary/CMakeLists.txt15
-rw-r--r--Tests/InterfaceLibrary/definetestexe.cpp9
-rw-r--r--Tests/InterfaceLibrary/libsdir/CMakeLists.txt26
-rw-r--r--Tests/InterfaceLibrary/libsdir/shareddependlib.cpp7
-rw-r--r--Tests/InterfaceLibrary/libsdir/shareddependlib/shareddependlib.h12
-rw-r--r--Tests/InterfaceLibrary/libsdir/sharedlib.cpp12
-rw-r--r--Tests/InterfaceLibrary/libsdir/sharedlib/sharedlib.h15
-rw-r--r--Tests/InterfaceLibrary/sharedlibtestexe.cpp19
-rw-r--r--Tests/PositionIndependentTargets/CMakeLists.txt1
-rw-r--r--Tests/PositionIndependentTargets/interface/CMakeLists.txt27
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict4-result.txt1
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict4-stderr.txt4
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict4.cmake8
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict5-result.txt1
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict5-stderr.txt3
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict5.cmake9
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict6-result.txt1
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict6-stderr.txt4
-rw-r--r--Tests/RunCMake/PositionIndependentCode/Conflict6.cmake8
-rw-r--r--Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/interface_library/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/interface_library/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/interface_library/invalid_name-result.txt1
-rw-r--r--Tests/RunCMake/interface_library/invalid_name-stderr.txt9
-rw-r--r--Tests/RunCMake/interface_library/invalid_name.cmake4
-rw-r--r--Tests/RunCMake/interface_library/target_commands-result.txt1
-rw-r--r--Tests/RunCMake/interface_library/target_commands-stderr.txt47
-rw-r--r--Tests/RunCMake/interface_library/target_commands.cmake13
56 files changed, 528 insertions, 49 deletions
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index cbc6ed1e91..130a033a8b 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -82,6 +82,12 @@ bool cmAddLibraryCommand
++s;
isAlias = true;
}
+ else if(libType == "INTERFACE")
+ {
+ ++s;
+ type = cmTarget::INTERFACE_LIBRARY;
+ haveSpecifiedType = true;
+ }
else if(*s == "EXCLUDE_FROM_ALL")
{
++s;
@@ -151,7 +157,8 @@ bool cmAddLibraryCommand
if(aliasedType != cmTarget::SHARED_LIBRARY
&& aliasedType != cmTarget::STATIC_LIBRARY
&& aliasedType != cmTarget::MODULE_LIBRARY
- && aliasedType != cmTarget::OBJECT_LIBRARY)
+ && aliasedType != cmTarget::OBJECT_LIBRARY
+ && aliasedType != cmTarget::INTERFACE_LIBRARY)
{
cmOStringStream e;
e << "cannot create ALIAS target \"" << libName
@@ -249,6 +256,26 @@ bool cmAddLibraryCommand
}
}
+ std::vector<std::string> srclists;
+
+ if(type == cmTarget::INTERFACE_LIBRARY)
+ {
+ if (!cmGeneratorExpression::IsValidTargetName(libName)
+ || libName.find("::") != std::string::npos)
+ {
+ cmOStringStream e;
+ e << "Invalid name for INTERFACE library target: " << libName;
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
+ this->Makefile->AddLibrary(libName.c_str(),
+ type,
+ srclists,
+ excludeFromAll);
+ return true;
+ }
+
if (s == args.end())
{
std::string msg = "You have called ADD_LIBRARY for library ";
@@ -258,7 +285,6 @@ bool cmAddLibraryCommand
cmSystemTools::Message(msg.c_str() ,"Warning");
}
- std::vector<std::string> srclists;
while (s != args.end())
{
srclists.push_back(*s);
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index 59354b0f5d..64d048b277 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -151,6 +151,16 @@ public:
"properties of <target>, that is, it may not be used as the operand of "
"set_property, set_target_properties, target_link_libraries etc. An "
"ALIAS target may not be installed of exported."
+ "\n"
+ "The signature\n"
+ " add_library(<name> INTERFACE)\n"
+ "creates an interface target. An interface target does not directly "
+ "create build output, though it may have properties set on it and it "
+ "may be installed, exported and imported. Typically the INTERFACE_* "
+ "properties are populated on the interface target using the "
+ "set_property(), target_link_libraries(), target_include_directories() "
+ "and target_compile_defintions() commands, and then it is used as an "
+ "argument to target_link_libraries() like any other target."
;
}
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index dec2b54d17..a2f3f7d8fb 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -355,9 +355,16 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
if(cmTarget::LinkInterface const* iface =
entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
{
+ const bool isIface =
+ entry.Target->GetType() == cmTarget::INTERFACE_LIBRARY;
// This target provides its own link interface information.
this->AddLinkEntries(depender_index, iface->Libraries);
+ if (isIface)
+ {
+ return;
+ }
+
// Handle dependent shared libraries.
this->FollowSharedDeps(depender_index, iface);
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index fb7b5b67d0..d3b28ed952 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -655,6 +655,11 @@ void cmComputeLinkInformation::AddItem(std::string const& item, cmTarget* tgt)
(this->UseImportLibrary &&
(impexe || tgt->GetType() == cmTarget::SHARED_LIBRARY));
+ if(tgt->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ this->Items.push_back(Item(std::string(), true, tgt));
+ return;
+ }
// Pass the full path to the target file.
std::string lib = tgt->GetFullPath(config, implib, true);
if(!this->LinkDependsNoShared ||
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 7f2b592f3e..5baf4bc652 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2555,6 +2555,10 @@ void cmGlobalGenerator::WriteSummary()
for(std::map<cmStdString,cmTarget *>::const_iterator ti =
this->TotalTargets.begin(); ti != this->TotalTargets.end(); ++ti)
{
+ if ((ti->second)->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
this->WriteSummary(ti->second);
fout << ti->second->GetSupportDirectory() << "\n";
}
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 61d02726e3..e45d024560 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -877,7 +877,12 @@ cmGlobalNinjaGenerator
cmTargetDependSet const& targetDeps =
this->GetTargetDirectDepends(*target);
for (cmTargetDependSet::const_iterator i = targetDeps.begin();
- i != targetDeps.end(); ++i) {
+ i != targetDeps.end(); ++i)
+ {
+ if ((*i)->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
this->AppendTargetOutputs(*i, outputs);
}
}
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 88cd6e5f84..803e74bf3d 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -881,6 +881,10 @@ cmGlobalUnixMakefileGenerator3
for(TargetDependSet::const_iterator di = depends.begin();
di != depends.end(); ++di)
{
+ if ((*di)->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
count += this->CountProgressMarksInTarget(*di, emitted);
}
}
@@ -967,6 +971,10 @@ cmGlobalUnixMakefileGenerator3
{
// Create the target-level dependency.
cmTarget const* dep = *i;
+ if (dep->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
cmLocalUnixMakefileGenerator3* lg3 =
static_cast<cmLocalUnixMakefileGenerator3*>
(dep->GetMakefile()->GetLocalGenerator());
diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx
index b3fabdade2..5296248db9 100644
--- a/Source/cmGlobalVisualStudio6Generator.cxx
+++ b/Source/cmGlobalVisualStudio6Generator.cxx
@@ -200,6 +200,10 @@ void cmGlobalVisualStudio6Generator
tt != orderedProjectTargets.end(); ++tt)
{
cmTarget* target = *tt;
+ if(target->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
// Write the project into the DSW file
const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
if(expath)
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index b47566561e..65eb3a9e1b 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -392,6 +392,10 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends(
projectTargets.begin(); tt != projectTargets.end(); ++tt)
{
cmTarget* target = *tt;
+ if(target->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
cmMakefile* mf = target->GetMakefile();
const char *vcprojName =
target->GetProperty("GENERATOR_FILE_NAME");
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index e4244e062b..b6deed2c2e 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -406,6 +406,10 @@ void cmGlobalVisualStudio8Generator::WriteProjectDepends(
for(OrderedTargetDependSet::const_iterator i = depends.begin();
i != depends.end(); ++i)
{
+ if((*i)->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
std::string guid = this->GetGUID((*i)->GetName());
fout << "\t\t{" << guid << "} = {" << guid << "}\n";
}
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 59310162ce..af80070c34 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -349,6 +349,10 @@ cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmTarget* target)
void cmGlobalVisualStudioGenerator::FollowLinkDepends(
cmTarget* target, std::set<cmTarget*>& linked)
{
+ if(target->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ return;
+ }
if(linked.insert(target).second &&
target->GetType() == cmTarget::STATIC_LIBRARY)
{
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 0a2b32b4fb..5a0fb0794b 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -976,6 +976,11 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
continue;
}
+ if(cmtarget.GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
+
if(cmtarget.GetType() == cmTarget::UTILITY ||
cmtarget.GetType() == cmTarget::GLOBAL_TARGET)
{
@@ -1686,6 +1691,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
cmXCodeObject* buildSettings,
const char* configName)
{
+ if(target.GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ return;
+ }
+
std::string flags;
std::string defFlags;
bool shared = ((target.GetType() == cmTarget::SHARED_LIBRARY) ||
@@ -2550,6 +2560,10 @@ cmXCodeObject*
cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
cmXCodeObject* buildPhases)
{
+ if(cmtarget.GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ return 0;
+ }
cmXCodeObject* target =
this->CreateObject(cmXCodeObject::PBXNativeTarget);
target->AddAttribute("buildPhases", buildPhases);
@@ -2756,6 +2770,10 @@ void cmGlobalXCodeGenerator
::AddDependAndLinkInformation(cmXCodeObject* target)
{
cmTarget* cmtarget = target->GetTarget();
+ if(cmtarget->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ return;
+ }
if(!cmtarget)
{
cmSystemTools::Error("Error no target on xobject\n");
@@ -2867,7 +2885,8 @@ void cmGlobalXCodeGenerator
{
linkLibs += this->XCodeEscapePath(li->Value.c_str());
}
- else
+ else if (!li->Target
+ || li->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
linkLibs += li->Value;
}
@@ -2909,6 +2928,10 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
{
continue;
}
+ if(cmtarget.GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
// add the soon to be generated Info.plist file as a source for a
// MACOSX_BUNDLE file
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index c9624c8e0e..6aa178f9af 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -90,6 +90,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
case cmTarget::STATIC_LIBRARY: type = cmInstallType_STATIC_LIBRARY; break;
case cmTarget::SHARED_LIBRARY: type = cmInstallType_SHARED_LIBRARY; break;
case cmTarget::MODULE_LIBRARY: type = cmInstallType_MODULE_LIBRARY; break;
+ case cmTarget::INTERFACE_LIBRARY:
+ // Not reachable. We never create a cmInstallTargetGenerator for
+ // an INTERFACE_LIBRARY.
+ assert(!"INTERFACE_LIBRARY targets have no installable outputs.");
+ break;
case cmTarget::OBJECT_LIBRARY:
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 9c04109656..a8eb9b8307 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1793,6 +1793,10 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
ItemVector const& items = cli.GetItems();
for(ItemVector::const_iterator li = items.begin(); li != items.end(); ++li)
{
+ if(li->Target && li->Target->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
if(li->IsPath)
{
linkLibs += this->ConvertToLinkReference(li->Value);
@@ -1996,6 +2000,10 @@ bool cmLocalGenerator::GetRealDependency(const char* inName,
// An object library has no single file on which to depend.
// This was listed to get the target-level dependency.
return false;
+ case cmTarget::INTERFACE_LIBRARY:
+ // An interface library has no file on which to depend.
+ // This was listed to get the target-level dependency.
+ return false;
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
// A utility target has no file on which to depend. This was listed
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index c3789a0225..aedd6edbf7 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -76,6 +76,10 @@ void cmLocalVisualStudio10Generator::Generate()
cmTargets &tgts = this->Makefile->GetTargets();
for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
{
+ if(l->second.GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
if(static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
->TargetIsFortranOnly(l->second))
{
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index e5b4057d28..f0f47cb616 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -91,6 +91,11 @@ void cmLocalVisualStudio6Generator::AddCMakeListsRules()
for(cmTargets::iterator l = tgts.begin();
l != tgts.end(); l++)
{
+ if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
+
// Add a rule to regenerate the build system when the target
// specification source changes.
const char* suppRegenRule =
@@ -146,6 +151,8 @@ void cmLocalVisualStudio6Generator::OutputDSPFile()
case cmTarget::GLOBAL_TARGET:
this->SetBuildType(UTILITY, l->first.c_str(), l->second);
break;
+ case cmTarget::INTERFACE_LIBRARY:
+ continue;
default:
cmSystemTools::Error("Bad target type", l->first.c_str());
break;
@@ -1839,7 +1846,8 @@ void cmLocalVisualStudio6Generator
options +=
this->ConvertToOptionallyRelativeOutputPath(l->Value.c_str());
}
- else
+ else if (!l->Target
+ || l->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
options += l->Value;
}
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index bd6c860047..64de448dc5 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -78,6 +78,10 @@ void cmLocalVisualStudio7Generator::AddHelperCommands()
static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
{
+ if(l->second.GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
const char* path = l->second.GetProperty("EXTERNAL_MSPROJECT");
if(path)
{
@@ -181,6 +185,10 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles()
for(cmTargets::iterator l = tgts.begin();
l != tgts.end(); l++)
{
+ if(l->second.GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
// INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
// so don't build a projectfile for it
if(!l->second.GetProperty("EXTERNAL_MSPROJECT"))
@@ -1258,6 +1266,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
}
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
+ case cmTarget::INTERFACE_LIBRARY:
break;
}
}
@@ -1288,7 +1297,8 @@ cmLocalVisualStudio7GeneratorInternals
cmLocalGenerator::UNCHANGED);
fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
}
- else
+ else if (!l->Target
+ || l->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
fout << l->Value << " ";
}
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 34541e996c..40e55c238b 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1463,6 +1463,7 @@ void cmMakefile::AddLinkLibraryForTarget(const char *target,
// if it is not a static or shared library then you can not link to it
if(!((tgt->GetType() == cmTarget::STATIC_LIBRARY) ||
(tgt->GetType() == cmTarget::SHARED_LIBRARY) ||
+ (tgt->GetType() == cmTarget::INTERFACE_LIBRARY) ||
tgt->IsExecutableWithExports()))
{
cmOStringStream e;
@@ -1990,6 +1991,7 @@ void cmMakefile::AddGlobalLinkInformation(const char* name, cmTarget& target)
{
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
+ case cmTarget::INTERFACE_LIBRARY:
return;
default:;
}
@@ -2017,7 +2019,8 @@ cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
if ( (type != cmTarget::STATIC_LIBRARY)
&& (type != cmTarget::SHARED_LIBRARY)
&& (type != cmTarget::MODULE_LIBRARY)
- && (type != cmTarget::OBJECT_LIBRARY))
+ && (type != cmTarget::OBJECT_LIBRARY)
+ && (type != cmTarget::INTERFACE_LIBRARY))
{
this->IssueMessage(cmake::INTERNAL_ERROR,
"cmMakefile::AddLibrary given invalid target type.");
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 0829cab6a9..59f65deaf9 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -996,7 +996,12 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
i = items.begin(); i != items.end(); ++i)
{
cmTarget const* linkee = i->Target;
- if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
+ if(linkee && !linkee->IsImported()
+ // We can ignore the INTERFACE_LIBRARY items because
+ // Target->GetLinkInformation already processed their
+ // link interface and they don't have any output themselves.
+ && linkee->GetType() != cmTarget::INTERFACE_LIBRARY
+ && emitted.insert(linkee).second)
{
cmMakefile* mf = linkee->GetMakefile();
cmLocalGenerator* lg = mf->GetLocalGenerator();
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index ac655da128..2461ed6d97 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -47,6 +47,8 @@ const char* cmTarget::GetTargetTypeName(TargetType targetType)
return "UTILITY";
case cmTarget::GLOBAL_TARGET:
return "GLOBAL_TARGET";
+ case cmTarget::INTERFACE_LIBRARY:
+ return "INTERFACE_LIBRARY";
case cmTarget::UNKNOWN_LIBRARY:
return "UNKNOWN_LIBRARY";
}
@@ -1727,6 +1729,14 @@ void cmTarget::SetMakefile(cmMakefile* mf)
CM_FOR_EACH_TARGET_POLICY(CAPTURE_TARGET_POLICY)
#undef CAPTURE_TARGET_POLICY
+
+ if (this->TargetTypeValue == INTERFACE_LIBRARY)
+ {
+ // This policy is checked in a few conditions. The properties relevant
+ // to the policy are always ignored for INTERFACE_LIBRARY targets,
+ // so ensure that the conditions don't lead to nonsense.
+ this->PolicyStatusCMP0022 = cmPolicies::NEW;
+ }
}
//----------------------------------------------------------------------------
@@ -1792,6 +1802,7 @@ bool cmTarget::IsLinkable()
this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY ||
this->GetType() == cmTarget::UNKNOWN_LIBRARY ||
+ this->GetType() == cmTarget::INTERFACE_LIBRARY ||
this->IsExecutableWithExports());
}
@@ -2563,8 +2574,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
return;
}
- {
cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
+ {
const bool isNonImportedTarget = tgt && !tgt->IsImported();
const std::string libName = (isNonImportedTarget && llt != GENERAL)
@@ -2575,7 +2586,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
llt).c_str());
}
- if (cmGeneratorExpression::Find(lib) != std::string::npos)
+ if (cmGeneratorExpression::Find(lib) != std::string::npos
+ || (tgt && tgt->GetType() == INTERFACE_LIBRARY))
{
return;
}
@@ -4091,6 +4103,7 @@ const char *cmTarget::GetProperty(const char* prop,
this->GetType() == cmTarget::STATIC_LIBRARY ||
this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY ||
+ this->GetType() == cmTarget::INTERFACE_LIBRARY ||
this->GetType() == cmTarget::UNKNOWN_LIBRARY)
{
if(strcmp(prop,"LOCATION") == 0)
@@ -5999,6 +6012,10 @@ cmTarget::GetImportInfo(const char* config, cmTarget *headTarget)
i = this->Internal->ImportInfoMap.insert(entry).first;
}
+ if(this->GetType() == INTERFACE_LIBRARY)
+ {
+ return &i->second;
+ }
// If the location is empty then the target is not available for
// this configuration.
if(i->second.Location.empty() && i->second.ImportLibrary.empty())
@@ -6152,6 +6169,49 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
return;
}
+ // Get the link interface.
+ {
+ std::string linkProp = "INTERFACE_LINK_LIBRARIES";
+ const char *propertyLibs = this->GetProperty(linkProp.c_str());
+
+ if (this->GetType() != INTERFACE_LIBRARY)
+ {
+ if(!propertyLibs)
+ {
+ linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+ linkProp += suffix;
+ propertyLibs = this->GetProperty(linkProp.c_str());
+ }
+
+ if(!propertyLibs)
+ {
+ linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+ propertyLibs = this->GetProperty(linkProp.c_str());
+ }
+ }
+ if(propertyLibs)
+ {
+ 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);
+ }
+ }
+ if(this->GetType() == INTERFACE_LIBRARY)
+ {
+ return;
+ }
+
// A provided configuration has been chosen. Load the
// configuration's properties.
@@ -6224,42 +6284,6 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
}
- // Get the link interface.
- {
- std::string linkProp = "INTERFACE_LINK_LIBRARIES";
- const char *propertyLibs = this->GetProperty(linkProp.c_str());
-
- if (!propertyLibs)
- {
- linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
- linkProp += suffix;
- propertyLibs = this->GetProperty(linkProp.c_str());
- }
-
- if(!propertyLibs)
- {
- linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
- propertyLibs = this->GetProperty(linkProp.c_str());
- }
- if(propertyLibs)
- {
- 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);
- }
- }
-
// Get the link dependencies.
{
std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
@@ -6520,6 +6544,11 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
}
}
}
+ else if (this->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ explicitLibraries = newExplicitLibraries;
+ linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
+ }
// There is no implicit link interface for executables or modules
// so if none was explicitly set then there is no link interface.
@@ -6547,7 +6576,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
this, &dagChecker), iface.Libraries);
if(this->GetType() == cmTarget::SHARED_LIBRARY
- || this->GetType() == cmTarget::STATIC_LIBRARY)
+ || this->GetType() == cmTarget::STATIC_LIBRARY
+ || this->GetType() == cmTarget::INTERFACE_LIBRARY)
{
// Shared libraries may have runtime implementation dependencies
// on other shared libraries that are not in the interface.
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 27b74ca4b0..f7425742eb 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -72,6 +72,7 @@ public:
enum TargetType { EXECUTABLE, STATIC_LIBRARY,
SHARED_LIBRARY, MODULE_LIBRARY,
OBJECT_LIBRARY, UTILITY, GLOBAL_TARGET,
+ INTERFACE_LIBRARY,
UNKNOWN_LIBRARY};
static const char* GetTargetTypeName(TargetType targetType);
enum CustomCommandType { PRE_BUILD, PRE_LINK, POST_BUILD };
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 863b3917eb..22f6a03614 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -322,6 +322,15 @@ bool
cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
cmTarget::LinkLibraryType llt)
{
+ if(this->Target->GetType() == cmTarget::INTERFACE_LIBRARY
+ && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
+ {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "INTERFACE library can only be used with the INTERFACE keyword of "
+ "target_link_libraries");
+ return false;
+ }
+
cmTarget::TLLSignature sig =
(this->CurrentProcessingState == ProcessingPlainPrivateInterface
|| this->CurrentProcessingState == ProcessingPlainPublicInterface
@@ -407,6 +416,11 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
return true;
}
+ if (this->Target->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ return true;
+ }
+
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> const& debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 1862cb6961..e7b699932b 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -47,6 +47,7 @@ bool cmTargetPropCommandBase
&& (this->Target->GetType() != cmTarget::STATIC_LIBRARY)
&& (this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
&& (this->Target->GetType() != cmTarget::MODULE_LIBRARY)
+ && (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
&& (this->Target->GetType() != cmTarget::EXECUTABLE))
{
this->SetError("called with non-compilable target type");
@@ -112,6 +113,14 @@ bool cmTargetPropCommandBase
return false;
}
+ if (this->Target->GetType() == cmTarget::INTERFACE_LIBRARY
+ && scope != "INTERFACE")
+ {
+ this->SetError("may only be set INTERFACE properties on INTERFACE "
+ "targets");
+ return false;
+ }
+
++argIndex;
std::vector<std::string> content;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index a26b2913ab..0dbb5ebbf7 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -490,6 +490,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
break;
case cmTarget::GLOBAL_TARGET:
case cmTarget::UNKNOWN_LIBRARY:
+ case cmTarget::INTERFACE_LIBRARY:
break;
}
configType += "</ConfigurationType>\n";
@@ -1701,7 +1702,8 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
libstring += sep;
libstring += path;
}
- else
+ else if (!l->Target
+ || l->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
libstring += sep;
libstring += l->Value;
@@ -1836,6 +1838,10 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
i != depends.end(); ++i)
{
cmTarget* dt = *i;
+ if(dt->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ continue;
+ }
// skip fortran targets as they can not be processed by MSBuild
// the only reference will be in the .sln file
if(static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
diff --git a/Tests/AliasTarget/CMakeLists.txt b/Tests/AliasTarget/CMakeLists.txt
index a5eb0f6de7..fdb1638406 100644
--- a/Tests/AliasTarget/CMakeLists.txt
+++ b/Tests/AliasTarget/CMakeLists.txt
@@ -45,3 +45,6 @@ get_property(_alt2 TARGET PREFIX::Foo PROPERTY ALIASED_TARGET)
if (NOT ${_alt2} STREQUAL foo)
message(SEND_ERROR "ALIASED_TARGET is not foo.")
endif()
+
+add_library(iface INTERFACE)
+add_library(Alias::Iface ALIAS iface)
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 9c3ed594f7..ca32aacd78 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -246,6 +246,7 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(CompileOptions CompileOptions)
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
ADD_TEST_MACRO(AliasTarget AliasTarget)
+ ADD_TEST_MACRO(InterfaceLibrary InterfaceLibrary)
set_tests_properties(EmptyLibrary PROPERTIES
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test")
ADD_TEST_MACRO(CrossCompile CrossCompile)
diff --git a/Tests/CompatibleInterface/CMakeLists.txt b/Tests/CompatibleInterface/CMakeLists.txt
index ae1d2fa431..5ee9fd7a69 100644
--- a/Tests/CompatibleInterface/CMakeLists.txt
+++ b/Tests/CompatibleInterface/CMakeLists.txt
@@ -6,7 +6,7 @@ project(CompatibleInterface)
include(GenerateExportHeader)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
-add_library(iface1 empty.cpp)
+add_library(iface1 INTERFACE)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL
BOOL_PROP1
diff --git a/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt
new file mode 100644
index 0000000000..53aeb036b0
--- /dev/null
+++ b/Tests/InterfaceLibrary/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+cmake_minimum_required(VERSION 2.8)
+
+project(InterfaceLibrary)
+
+add_library(iface_nodepends INTERFACE)
+target_compile_definitions(iface_nodepends INTERFACE IFACE_DEFINE)
+
+add_executable(InterfaceLibrary definetestexe.cpp)
+target_link_libraries(InterfaceLibrary iface_nodepends)
+
+add_subdirectory(libsdir)
+
+add_executable(sharedlibtestexe sharedlibtestexe.cpp)
+target_link_libraries(sharedlibtestexe shared_iface)
diff --git a/Tests/InterfaceLibrary/definetestexe.cpp b/Tests/InterfaceLibrary/definetestexe.cpp
new file mode 100644
index 0000000000..decd37c51d
--- /dev/null
+++ b/Tests/InterfaceLibrary/definetestexe.cpp
@@ -0,0 +1,9 @@
+
+#ifndef IFACE_DEFINE
+#error Expected IFACE_DEFINE
+#endif
+
+int main(int,char**)
+{
+ return 0;
+}
diff --git a/Tests/InterfaceLibrary/libsdir/CMakeLists.txt b/Tests/InterfaceLibrary/libsdir/CMakeLists.txt
new file mode 100644
index 0000000000..6999646561
--- /dev/null
+++ b/Tests/InterfaceLibrary/libsdir/CMakeLists.txt
@@ -0,0 +1,26 @@
+
+include(GenerateExportHeader)
+
+add_library(sharedlib SHARED sharedlib.cpp)
+generate_export_header(sharedlib)
+
+add_library(shareddependlib SHARED shareddependlib.cpp)
+generate_export_header(shareddependlib)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
+
+target_link_libraries(sharedlib PUBLIC shareddependlib)
+
+target_include_directories(shareddependlib
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/shareddependlib")
+target_compile_definitions(shareddependlib
+ INTERFACE $<1:SHAREDDEPENDLIB_DEFINE>)
+
+target_include_directories(sharedlib
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/sharedlib")
+target_compile_definitions(shareddependlib
+ INTERFACE $<1:SHAREDLIB_DEFINE>)
+
+add_library(shared_iface INTERFACE)
+target_link_libraries(shared_iface INTERFACE sharedlib)
diff --git a/Tests/InterfaceLibrary/libsdir/shareddependlib.cpp b/Tests/InterfaceLibrary/libsdir/shareddependlib.cpp
new file mode 100644
index 0000000000..378ba8165f
--- /dev/null
+++ b/Tests/InterfaceLibrary/libsdir/shareddependlib.cpp
@@ -0,0 +1,7 @@
+
+#include "shareddependlib.h"
+
+int SharedDependLibObject::foo() const
+{
+ return 0;
+}
diff --git a/Tests/InterfaceLibrary/libsdir/shareddependlib/shareddependlib.h b/Tests/InterfaceLibrary/libsdir/shareddependlib/shareddependlib.h
new file mode 100644
index 0000000000..ad9b484b7a
--- /dev/null
+++ b/Tests/InterfaceLibrary/libsdir/shareddependlib/shareddependlib.h
@@ -0,0 +1,12 @@
+
+#ifndef SHAREDDEPENDLIB_H
+#define SHAREDDEPENDLIB_H
+
+#include "shareddependlib_export.h"
+
+struct SHAREDDEPENDLIB_EXPORT SharedDependLibObject
+{
+ int foo() const;
+};
+
+#endif
diff --git a/Tests/InterfaceLibrary/libsdir/sharedlib.cpp b/Tests/InterfaceLibrary/libsdir/sharedlib.cpp
new file mode 100644
index 0000000000..c49ce905b1
--- /dev/null
+++ b/Tests/InterfaceLibrary/libsdir/sharedlib.cpp
@@ -0,0 +1,12 @@
+
+#include "sharedlib.h"
+
+SharedDependLibObject SharedLibObject::object() const
+{
+ SharedDependLibObject sdlo;
+ return sdlo;
+}
+int SharedLibObject::foo() const
+{
+ return 0;
+}
diff --git a/Tests/InterfaceLibrary/libsdir/sharedlib/sharedlib.h b/Tests/InterfaceLibrary/libsdir/sharedlib/sharedlib.h
new file mode 100644
index 0000000000..5b3c7db732
--- /dev/null
+++ b/Tests/InterfaceLibrary/libsdir/sharedlib/sharedlib.h
@@ -0,0 +1,15 @@
+
+#ifndef SHAREDLIB_H
+#define SHAREDLIB_H
+
+#include "sharedlib_export.h"
+
+#include "shareddependlib.h"
+
+struct SHAREDLIB_EXPORT SharedLibObject
+{
+ SharedDependLibObject object() const;
+ int foo() const;
+};
+
+#endif
diff --git a/Tests/InterfaceLibrary/sharedlibtestexe.cpp b/Tests/InterfaceLibrary/sharedlibtestexe.cpp
new file mode 100644
index 0000000000..c677f7067a
--- /dev/null
+++ b/Tests/InterfaceLibrary/sharedlibtestexe.cpp
@@ -0,0 +1,19 @@
+
+#ifndef SHAREDLIB_DEFINE
+#error Expected SHAREDLIB_DEFINE
+#endif
+
+#ifndef SHAREDDEPENDLIB_DEFINE
+#error Expected SHAREDDEPENDLIB_DEFINE
+#endif
+
+#include "sharedlib.h"
+#include "shareddependlib.h"
+
+int main(int,char**)
+{
+ SharedLibObject sl;
+ SharedDependLibObject sdl = sl.object();
+
+ return sdl.foo() + sl.foo();
+}
diff --git a/Tests/PositionIndependentTargets/CMakeLists.txt b/Tests/PositionIndependentTargets/CMakeLists.txt
index eec893d320..e79f3b74b7 100644
--- a/Tests/PositionIndependentTargets/CMakeLists.txt
+++ b/Tests/PositionIndependentTargets/CMakeLists.txt
@@ -9,5 +9,6 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}") # For pic_test.h
add_subdirectory(global)
add_subdirectory(targets)
+add_subdirectory(interface)
add_executable(PositionIndependentTargets main.cpp)
diff --git a/Tests/PositionIndependentTargets/interface/CMakeLists.txt b/Tests/PositionIndependentTargets/interface/CMakeLists.txt
new file mode 100644
index 0000000000..65f3b767ed
--- /dev/null
+++ b/Tests/PositionIndependentTargets/interface/CMakeLists.txt
@@ -0,0 +1,27 @@
+
+add_library(piciface INTERFACE)
+set_property(TARGET piciface PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
+
+add_executable(test_empty_iface "${CMAKE_CURRENT_SOURCE_DIR}/../pic_main.cpp")
+target_link_libraries(test_empty_iface piciface)
+
+add_library(sharedlib SHARED "${CMAKE_CURRENT_SOURCE_DIR}/../pic_lib.cpp")
+target_link_libraries(sharedlib piciface)
+set_property(TARGET sharedlib PROPERTY DEFINE_SYMBOL PIC_TEST_BUILD_DLL)
+
+add_executable(test_iface_via_shared "${CMAKE_CURRENT_SOURCE_DIR}/../pic_main.cpp")
+target_link_libraries(test_iface_via_shared sharedlib)
+
+add_library(sharedlibpic SHARED "${CMAKE_CURRENT_SOURCE_DIR}/../pic_lib.cpp")
+set_property(TARGET sharedlibpic PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
+set_property(TARGET sharedlibpic PROPERTY DEFINE_SYMBOL PIC_TEST_BUILD_DLL)
+
+add_library(shared_iface INTERFACE)
+target_link_libraries(shared_iface INTERFACE sharedlibpic)
+
+add_executable(test_shared_via_iface "${CMAKE_CURRENT_SOURCE_DIR}/../pic_main.cpp")
+target_link_libraries(test_shared_via_iface shared_iface)
+
+add_executable(test_shared_via_iface_non_conflict "${CMAKE_CURRENT_SOURCE_DIR}/../pic_main.cpp")
+set_property(TARGET test_shared_via_iface_non_conflict PROPERTY POSITION_INDEPENDENT_CODE ON)
+target_link_libraries(test_shared_via_iface_non_conflict shared_iface)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index e45aba3781..5d662d191d 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -100,6 +100,7 @@ add_RunCMake_test(variable_watch)
add_RunCMake_test(CMP0004)
add_RunCMake_test(TargetPolicies)
add_RunCMake_test(alias_targets)
+add_RunCMake_test(interface_library)
find_package(Qt4 QUIET)
find_package(Qt5Core QUIET)
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict4-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict4-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict4-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict4-stderr.txt
new file mode 100644
index 0000000000..76d5ea08a4
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict4-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error: Property POSITION_INDEPENDENT_CODE on target "conflict" is
+implied to be FALSE because it was used to determine the link libraries
+already. The INTERFACE_POSITION_INDEPENDENT_CODE property on
+dependency "picon" is in conflict.
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict4.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict4.cmake
new file mode 100644
index 0000000000..ff5dfb353c
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict4.cmake
@@ -0,0 +1,8 @@
+
+add_library(piciface INTERFACE)
+
+add_library(picon INTERFACE)
+set_property(TARGET picon PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
+
+add_executable(conflict "main.cpp")
+target_link_libraries(conflict picon $<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:piciface>)
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict5-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict5-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict5-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict5-stderr.txt
new file mode 100644
index 0000000000..ecd04928d3
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict5-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error: The INTERFACE_POSITION_INDEPENDENT_CODE property of "picoff" does
+not agree with the value of POSITION_INDEPENDENT_CODE already determined
+for "conflict".
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict5.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict5.cmake
new file mode 100644
index 0000000000..e6055f4508
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict5.cmake
@@ -0,0 +1,9 @@
+
+add_library(picon INTERFACE)
+set_property(TARGET picon PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
+
+add_library(picoff INTERFACE)
+set_property(TARGET picoff PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF)
+
+add_executable(conflict "main.cpp")
+target_link_libraries(conflict picon picoff)
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict6-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict6-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict6-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict6-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict6-stderr.txt
new file mode 100644
index 0000000000..0254e55575
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict6-stderr.txt
@@ -0,0 +1,4 @@
+Property POSITION_INDEPENDENT_CODE on target "conflict" is
+implied to be FALSE because it was used to determine the link libraries
+already. The INTERFACE_POSITION_INDEPENDENT_CODE property on
+dependency "picon" is in conflict.
diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict6.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict6.cmake
new file mode 100644
index 0000000000..7ea7c5f731
--- /dev/null
+++ b/Tests/RunCMake/PositionIndependentCode/Conflict6.cmake
@@ -0,0 +1,8 @@
+
+add_library(picoff INTERFACE)
+
+add_library(picon INTERFACE)
+set_property(TARGET picon PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
+
+add_executable(conflict "main.cpp")
+target_link_libraries(conflict picon $<$<NOT:$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>>:picoff>)
diff --git a/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake b/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake
index 64a340c9c9..3a2009b48c 100644
--- a/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake
+++ b/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake
@@ -3,3 +3,6 @@ include(RunCMake)
run_cmake(Conflict1)
run_cmake(Conflict2)
run_cmake(Conflict3)
+run_cmake(Conflict4)
+run_cmake(Conflict5)
+run_cmake(Conflict6)
diff --git a/Tests/RunCMake/interface_library/CMakeLists.txt b/Tests/RunCMake/interface_library/CMakeLists.txt
new file mode 100644
index 0000000000..12cd3c7757
--- /dev/null
+++ b/Tests/RunCMake/interface_library/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.4)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/interface_library/RunCMakeTest.cmake b/Tests/RunCMake/interface_library/RunCMakeTest.cmake
new file mode 100644
index 0000000000..56caf683fb
--- /dev/null
+++ b/Tests/RunCMake/interface_library/RunCMakeTest.cmake
@@ -0,0 +1,4 @@
+include(RunCMake)
+
+run_cmake(invalid_name)
+run_cmake(target_commands)
diff --git a/Tests/RunCMake/interface_library/invalid_name-result.txt b/Tests/RunCMake/interface_library/invalid_name-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/interface_library/invalid_name-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/interface_library/invalid_name-stderr.txt b/Tests/RunCMake/interface_library/invalid_name-stderr.txt
new file mode 100644
index 0000000000..c66e0800ae
--- /dev/null
+++ b/Tests/RunCMake/interface_library/invalid_name-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at invalid_name.cmake:2 \(add_library\):
+ add_library Invalid name for INTERFACE library target: if\$ace
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_name.cmake:4 \(add_library\):
+ add_library Invalid name for INTERFACE library target: iface::target
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/interface_library/invalid_name.cmake b/Tests/RunCMake/interface_library/invalid_name.cmake
new file mode 100644
index 0000000000..51a109d325
--- /dev/null
+++ b/Tests/RunCMake/interface_library/invalid_name.cmake
@@ -0,0 +1,4 @@
+
+add_library(if$ace INTERFACE)
+
+add_library(iface::target INTERFACE)
diff --git a/Tests/RunCMake/interface_library/target_commands-result.txt b/Tests/RunCMake/interface_library/target_commands-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/interface_library/target_commands-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/interface_library/target_commands-stderr.txt b/Tests/RunCMake/interface_library/target_commands-stderr.txt
new file mode 100644
index 0000000000..be11b77545
--- /dev/null
+++ b/Tests/RunCMake/interface_library/target_commands-stderr.txt
@@ -0,0 +1,47 @@
+CMake Error at target_commands.cmake:4 \(target_link_libraries\):
+ INTERFACE library can only be used with the INTERFACE keyword of
+ target_link_libraries
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at target_commands.cmake:5 \(target_link_libraries\):
+ INTERFACE library can only be used with the INTERFACE keyword of
+ target_link_libraries
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at target_commands.cmake:6 \(target_link_libraries\):
+ INTERFACE library can only be used with the INTERFACE keyword of
+ target_link_libraries
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at target_commands.cmake:7 \(target_link_libraries\):
+ INTERFACE library can only be used with the INTERFACE keyword of
+ target_link_libraries
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at target_commands.cmake:9 \(target_include_directories\):
+ target_include_directories may only be set INTERFACE properties on
+ INTERFACE targets
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at target_commands.cmake:10 \(target_include_directories\):
+ target_include_directories may only be set INTERFACE properties on
+ INTERFACE targets
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at target_commands.cmake:12 \(target_compile_definitions\):
+ target_compile_definitions may only be set INTERFACE properties on
+ INTERFACE targets
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at target_commands.cmake:13 \(target_compile_definitions\):
+ target_compile_definitions may only be set INTERFACE properties on
+ INTERFACE targets
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/interface_library/target_commands.cmake b/Tests/RunCMake/interface_library/target_commands.cmake
new file mode 100644
index 0000000000..3182e8933e
--- /dev/null
+++ b/Tests/RunCMake/interface_library/target_commands.cmake
@@ -0,0 +1,13 @@
+
+add_library(iface INTERFACE)
+
+target_link_libraries(iface PRIVATE foo)
+target_link_libraries(iface PUBLIC foo)
+target_link_libraries(iface foo)
+target_link_libraries(iface LINK_INTERFACE_LIBRARIES foo)
+
+target_include_directories(iface PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
+target_include_directories(iface PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
+
+target_compile_definitions(iface PRIVATE SOME_DEFINE)
+target_compile_definitions(iface PUBLIC SOME_DEFINE)