summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2012-11-02 14:47:40 (GMT)
committerBrad King <brad.king@kitware.com>2013-10-07 23:56:31 (GMT)
commitfe732264e9abb6249d1d112b24ce36b226590105 (patch)
tree97c08c00ec43b68f692d50729f536d84c7c0d13a /Source
parentd4134352abf69374fdad24d53d67734a135daaa5 (diff)
downloadCMake-fe732264e9abb6249d1d112b24ce36b226590105.zip
CMake-fe732264e9abb6249d1d112b24ce36b226590105.tar.gz
CMake-fe732264e9abb6249d1d112b24ce36b226590105.tar.bz2
Add the INTERFACE_LIBRARY target type.
This target type only contains INTERFACE_* properties, so it can be used as a structural node. The target-specific commands enforce that they may only be used with the INTERFACE keyword when used with INTERFACE_LIBRARY targets. The old-style target properties matching LINK_INTERFACE_LIBRARIES_<CONFIG> are always ignored for this target type. The name of the INTERFACE_LIBRARY must match a validity generator expression. The validity is similar to that of an ALIAS target, but with the additional restriction that it may not contain double colons. Double colons will carry the meaning of IMPORTED or ALIAS targets in CMake 2.8.13. An ALIAS target may be created for an INTERFACE library. At this point it can not be exported and does not appear in the buildsystem and project files are not created for them. That may be added as a feature in a later commit. The generators need some changes to handle the INTERFACE_LIBRARY targets returned by cmComputeLinkInterface::GetItems. The Ninja generator does not use that API, so it doesn't require changes related to that.
Diffstat (limited to 'Source')
-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
24 files changed, 255 insertions, 48 deletions
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index cbc6ed1..130a033 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 59354b0..64d048b 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 dec2b54..a2f3f7d 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 fb7b5b6..d3b28ed 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 7f2b592..5baf4bc 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 61d0272..e45d024 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 88cd6e5..803e74b 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 b3fabda..5296248 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 b475665..65eb3a9 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 e4244e0..b6deed2 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 5931016..af80070 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 0a2b32b..5a0fb07 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 c9624c8..6aa178f 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 9c04109..a8eb9b8 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 c3789a0..aedd6ed 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 e5b4057..f0f47cb 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 bd6c860..64de448 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 34541e9..40e55c2 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 0829cab..59f65de 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 ac655da..2461ed6 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 27b74ca..f742574 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 863b391..22f6a03 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 1862cb6..e7b6999 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 a26b291..0dbb5eb 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)