Merge topic 'INTERFACE_LIBRARY-target-type'

ce0c303 install: Teach EXPORT option to handle INTERFACE_LIBRARY targets
435c912 export: Add support for INTERFACE_LIBRARY targets
fe73226 Add the INTERFACE_LIBRARY target type.
This commit is contained in:
Brad King 2013-10-08 10:58:40 -04:00 committed by CMake Topic Stage
commit f8241136b4
71 changed files with 771 additions and 65 deletions

View File

@ -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
@ -213,6 +220,16 @@ bool cmAddLibraryCommand
);
return true;
}
if(type == cmTarget::INTERFACE_LIBRARY)
{
if (!cmGeneratorExpression::IsValidTargetName(libName))
{
cmOStringStream e;
e << "Invalid name for IMPORTED INTERFACE library target: " << libName;
this->SetError(e.str().c_str());
return false;
}
}
// Make sure the target does not already exist.
if(this->Makefile->FindTargetToUse(libName.c_str()))
@ -249,6 +266,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 +295,6 @@ bool cmAddLibraryCommand
cmSystemTools::Message(msg.c_str() ,"Warning");
}
std::vector<std::string> srclists;
while (s != args.end())
{
srclists.push_back(*s);

View File

@ -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."
;
}

View File

@ -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);

View File

@ -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 ||

View File

@ -99,6 +99,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
{
case cmTarget::SHARED_LIBRARY:
case cmTarget::STATIC_LIBRARY:
case cmTarget::INTERFACE_LIBRARY:
case cmTarget::UNKNOWN_LIBRARY:
break;
case cmTarget::EXECUTABLE:

View File

@ -47,6 +47,10 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
}
return false;
}
if (te->GetType() == cmTarget::INTERFACE_LIBRARY)
{
this->GenerateRequiredCMakeVersion(os, "2.8.12.20131007"); // 2.8.13
}
}
this->GenerateExpectedTargetsCode(os, expectedTargets);
@ -118,16 +122,22 @@ cmExportBuildFileGenerator
// Collect import properties for this target.
cmTarget* target = *tei;
ImportPropertyMap properties;
if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
this->SetImportLocationProperty(config, suffix, target, properties);
}
if(!properties.empty())
{
// Get the rest of the target details.
if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
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

View File

@ -130,7 +130,8 @@ bool cmExportCommand
if((target->GetType() == cmTarget::EXECUTABLE) ||
(target->GetType() == cmTarget::STATIC_LIBRARY) ||
(target->GetType() == cmTarget::SHARED_LIBRARY) ||
(target->GetType() == cmTarget::MODULE_LIBRARY))
(target->GetType() == cmTarget::MODULE_LIBRARY) ||
(target->GetType() == cmTarget::INTERFACE_LIBRARY))
{
targets.push_back(target);
}

View File

@ -377,12 +377,15 @@ void getCompatibleInterfaceProperties(cmTarget *target,
cmComputeLinkInformation *info = target->GetLinkInformation(config);
if (!info)
{
if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
cmMakefile* mf = target->GetMakefile();
cmOStringStream e;
e << "Exporting the target \"" << target->GetName() << "\" is not "
"allowed since its linker language cannot be determined";
mf->IssueMessage(cmake::FATAL_ERROR, e.str());
}
return;
}
@ -888,6 +891,9 @@ cmExportFileGenerator
case cmTarget::UNKNOWN_LIBRARY:
os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
break;
case cmTarget::INTERFACE_LIBRARY:
os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
break;
default: // should never happen
break;
}

View File

@ -114,6 +114,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
std::vector<std::string> missingTargets;
bool require2_8_12 = false;
bool require2_8_13 = false;
// Create all the imported targets.
for(std::vector<cmTargetExport*>::const_iterator
tei = allTargets.begin();
@ -153,6 +154,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
require2_8_12 = true;
}
}
if (te->GetType() == cmTarget::INTERFACE_LIBRARY)
{
require2_8_13 = true;
}
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
@ -160,7 +165,11 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateInterfaceProperties(te, os, properties);
}
if (require2_8_12)
if (require2_8_13)
{
this->GenerateRequiredCMakeVersion(os, "2.8.12.20131007");
}
else if (require2_8_12)
{
this->GenerateRequiredCMakeVersion(os, "2.8.12");
}
@ -286,6 +295,14 @@ cmExportInstallFileGenerator
cmTargetExport const* te = *tei;
ImportPropertyMap properties;
std::set<std::string> importedLocations;
if (!properties.empty()
&& te->Target->GetType() == cmTarget::INTERFACE_LIBRARY)
{
this->GenerateImportPropertyCode(os, config, te->Target, properties);
this->GenerateImportedFileChecksCode(os, te->Target, properties,
importedLocations);
continue;
}
this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
properties, importedLocations);
this->SetImportLocationProperty(config, suffix, te->LibraryGenerator,

View File

@ -2563,6 +2563,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";
}

View File

@ -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);
}
}

View File

@ -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());

View File

@ -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)

View File

@ -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");

View File

@ -409,6 +409,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";
}

View File

@ -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)
{

View File

@ -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

View File

@ -379,7 +379,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
target->GetType() != cmTarget::STATIC_LIBRARY &&
target->GetType() != cmTarget::SHARED_LIBRARY &&
target->GetType() != cmTarget::MODULE_LIBRARY &&
target->GetType() != cmTarget::OBJECT_LIBRARY)
target->GetType() != cmTarget::OBJECT_LIBRARY &&
target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
cmOStringStream e;
e << "TARGETS given target \"" << (*targetIt)
@ -626,6 +627,11 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
}
break;
case cmTarget::INTERFACE_LIBRARY:
// Nothing to do. An INTERFACE_LIBRARY can be installed, but the
// only effect of that is to make it exportable. It installs no
// other files itself.
break;
default:
// This should never happen due to the above type check.
// Ignore the case.

View File

@ -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:

View File

@ -1794,6 +1794,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);
@ -1997,6 +2001,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

View File

@ -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))
{

View File

@ -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;
}

View File

@ -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 << " ";
}

View File

@ -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.");

View File

@ -1004,7 +1004,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();

View File

@ -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";
}
@ -1743,6 +1745,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;
}
}
//----------------------------------------------------------------------------
@ -1808,6 +1818,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());
}
@ -2579,8 +2590,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)
@ -2591,7 +2602,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;
}
@ -4137,6 +4149,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)
@ -6061,6 +6074,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())
@ -6209,7 +6226,51 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
const char* loc = 0;
const char* imp = 0;
std::string suffix;
if (!this->GetMappedConfig(desired_config, &loc, &imp, suffix))
if (this->GetType() != INTERFACE_LIBRARY &&
!this->GetMappedConfig(desired_config, &loc, &imp, suffix))
{
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;
}
@ -6286,42 +6347,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";
@ -6582,6 +6607,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.
@ -6609,7 +6639,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.

View File

@ -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 };

View File

@ -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();

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -436,3 +436,5 @@ export(TARGETS testExe2 testLib4 testLib5 testLib6 testExe3 testExe2lib
NAMESPACE bld_
APPEND FILE ExportBuildTree.cmake
)
add_subdirectory(Interface)

View File

@ -0,0 +1,49 @@
add_library(headeronly INTERFACE)
set_property(TARGET headeronly PROPERTY INTERFACE_INCLUDE_DIRECTORIES
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/headeronly>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/headeronly>"
)
set_property(TARGET headeronly PROPERTY INTERFACE_COMPILE_DEFINITIONS "HEADERONLY_DEFINE")
include(GenerateExportHeader)
add_library(sharedlib SHARED sharedlib.cpp)
generate_export_header(sharedlib)
set_property(TARGET sharedlib PROPERTY INCLUDE_DIRECTORIES
"${CMAKE_CURRENT_SOURCE_DIR}/sharedlib"
"${CMAKE_CURRENT_BINARY_DIR}"
)
set_property(TARGET sharedlib PROPERTY INTERFACE_INCLUDE_DIRECTORIES
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/sharedlib;${CMAKE_CURRENT_BINARY_DIR}>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/sharedlib>"
)
set_property(TARGET sharedlib PROPERTY INTERFACE_COMPILE_DEFINITIONS "SHAREDLIB_DEFINE")
add_library(sharediface INTERFACE)
target_link_libraries(sharediface INTERFACE sharedlib)
export(TARGETS sharediface sharedlib headeronly
NAMESPACE bld_
FILE ../ExportInterfaceBuildTree.cmake
)
install(TARGETS headeronly sharediface sharedlib
EXPORT expInterface
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib NAMELINK_SKIP
ARCHIVE DESTINATION lib
FRAMEWORK DESTINATION Frameworks
BUNDLE DESTINATION Applications
)
install(FILES
headeronly/headeronly.h
DESTINATION include/headeronly
)
install(FILES
sharedlib/sharedlib.h
"${CMAKE_CURRENT_BINARY_DIR}/sharedlib_export.h"
DESTINATION include/sharedlib
)
install(EXPORT expInterface NAMESPACE exp_ DESTINATION lib/exp)

View File

@ -0,0 +1,7 @@
enum { one };
struct HeaderOnly
{
int foo() const { return 0; }
};

View File

@ -0,0 +1,7 @@
#include "sharedlib.h"
int SharedLibObject::foo() const
{
return 0;
}

View File

@ -0,0 +1,7 @@
#include "sharedlib_export.h"
struct SHAREDLIB_EXPORT SharedLibObject
{
int foo() const;
};

View File

@ -19,3 +19,6 @@ add_executable(imp_testTransExe1b imp_testTransExe1.c)
target_link_libraries(imp_testTransExe1b imp_lib1b)
add_subdirectory(try_compile)
# Test package INTERFACE controls
add_subdirectory(Interface)

View File

@ -0,0 +1,55 @@
# Import targets from the exported build tree.
include(${Import_BINARY_DIR}/../Export/ExportInterfaceBuildTree.cmake)
# Import targets from the exported install tree.
include(${CMAKE_INSTALL_PREFIX}/lib/exp/expInterface.cmake)
add_library(define_iface INTERFACE)
set_property(TARGET define_iface PROPERTY
INTERFACE_COMPILE_DEFINITIONS DEFINE_IFACE_DEFINE)
add_executable(headeronlytest_bld headeronlytest.cpp)
target_link_libraries(headeronlytest_bld bld_headeronly)
set_property(TARGET bld_sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
add_executable(interfacetest_bld interfacetest.cpp)
target_link_libraries(interfacetest_bld bld_sharediface)
include(CheckCXXSourceCompiles)
macro(do_try_compile prefix)
set(CMAKE_REQUIRED_LIBRARIES ${prefix}headeronly)
check_cxx_source_compiles(
"
#include \"headeronly.h\"
#ifndef HEADERONLY_DEFINE
#error Expected HEADERONLY_DEFINE
#endif
int main(int,char**)
{
HeaderOnly ho;
return ho.foo();
}
" ${prefix}IFACE_TRY_COMPILE)
if(NOT ${prefix}IFACE_TRY_COMPILE)
message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}")
endif()
endmacro()
do_try_compile(bld_)
add_executable(headeronlytest_exp headeronlytest.cpp)
target_link_libraries(headeronlytest_exp exp_headeronly)
set_property(TARGET exp_sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
add_executable(interfacetest_exp interfacetest.cpp)
target_link_libraries(interfacetest_exp exp_sharediface)
do_try_compile(exp_)

View File

@ -0,0 +1,17 @@
#include "headeronly.h"
#ifndef HEADERONLY_DEFINE
#error Expected HEADERONLY_DEFINE
#endif
#ifdef SHAREDLIB_DEFINE
#error Unexpected SHAREDLIB_DEFINE
#endif
int main(int,char**)
{
HeaderOnly ho;
return ho.foo();
}

View File

@ -0,0 +1,20 @@
#include "sharedlib.h"
#ifndef SHAREDLIB_DEFINE
#error Expected SHAREDLIB_DEFINE
#endif
#ifdef HEADERONLY_DEFINE
#error Unexpected HEADERONLY_DEFINE
#endif
#ifndef DEFINE_IFACE_DEFINE
#error Expected DEFINE_IFACE_DEFINE
#endif
int main(int,char**)
{
SharedLibObject slo;
return slo.foo();
}

View File

@ -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)

View File

@ -0,0 +1,9 @@
#ifndef IFACE_DEFINE
#error Expected IFACE_DEFINE
#endif
int main(int,char**)
{
return 0;
}

View File

@ -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)

View File

@ -0,0 +1,7 @@
#include "shareddependlib.h"
int SharedDependLibObject::foo() const
{
return 0;
}

View File

@ -0,0 +1,12 @@
#ifndef SHAREDDEPENDLIB_H
#define SHAREDDEPENDLIB_H
#include "shareddependlib_export.h"
struct SHAREDDEPENDLIB_EXPORT SharedDependLibObject
{
int foo() const;
};
#endif

View File

@ -0,0 +1,12 @@
#include "sharedlib.h"
SharedDependLibObject SharedLibObject::object() const
{
SharedDependLibObject sdlo;
return sdlo;
}
int SharedLibObject::foo() const
{
return 0;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -0,0 +1 @@
1

View File

@ -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.

View File

@ -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>)

View File

@ -0,0 +1 @@
1

View File

@ -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".

View File

@ -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)

View File

@ -0,0 +1 @@
1

View File

@ -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.

View File

@ -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>)

View File

@ -3,3 +3,6 @@ include(RunCMake)
run_cmake(Conflict1)
run_cmake(Conflict2)
run_cmake(Conflict3)
run_cmake(Conflict4)
run_cmake(Conflict5)
run_cmake(Conflict6)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,4 @@
include(RunCMake)
run_cmake(invalid_name)
run_cmake(target_commands)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,15 @@
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\)
+
CMake Error at invalid_name.cmake:6 \(add_library\):
add_library Invalid name for IMPORTED INTERFACE library target:
if\$target_imported
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,6 @@
add_library(if$ace INTERFACE)
add_library(iface::target INTERFACE)
add_library(if$target_imported INTERFACE IMPORTED)

View File

@ -0,0 +1 @@
1

View File

@ -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\)

View File

@ -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)