diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index cbc6ed1e9..130a033a8 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 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 srclists; while (s != args.end()) { srclists.push_back(*s); diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index 59354b0f5..64d048b27 100644 --- a/Source/cmAddLibraryCommand.h +++ b/Source/cmAddLibraryCommand.h @@ -151,6 +151,16 @@ public: "properties of , 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( 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 dec2b54d1..a2f3f7d8f 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 fb7b5b67d..d3b28ed95 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 7f2b592f3..5baf4bc65 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2555,6 +2555,10 @@ void cmGlobalGenerator::WriteSummary() for(std::map::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 61d02726e..e45d02456 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 88cd6e5f8..803e74bf3 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 (dep->GetMakefile()->GetLocalGenerator()); diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index b3fabdade..5296248db 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 b47566561..65eb3a9e1 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 e4244e062..b6deed2c2 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 59310162c..af80070c3 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -349,6 +349,10 @@ cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmTarget* target) void cmGlobalVisualStudioGenerator::FollowLinkDepends( cmTarget* target, std::set& 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 0a2b32b4f..5a0fb0794 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 c9624c8e0..6aa178f9a 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 9c0410965..a8eb9b830 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 c3789a022..aedd6edbf 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(this->GlobalGenerator) ->TargetIsFortranOnly(l->second)) { diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index e5b4057d2..f0f47cb61 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 bd6c86004..64de448dc 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -78,6 +78,10 @@ void cmLocalVisualStudio7Generator::AddHelperCommands() static_cast(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 34541e996..40e55c238 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 0829cab6a..59f65deaf 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 ac655da12..2461ed6d9 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 27b74ca4b..f7425742e 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 863b3917e..22f6a0361 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 const& debugConfigs = this->Makefile->GetCMakeInstance()->GetDebugConfigs(); diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 1862cb696..e7b699932 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 content; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index a26b2913a..0dbb5ebbf 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 += "\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(this->GlobalGenerator) diff --git a/Tests/AliasTarget/CMakeLists.txt b/Tests/AliasTarget/CMakeLists.txt index a5eb0f6de..fdb163840 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 9c3ed594f..ca32aacd7 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 ae1d2fa43..5ee9fd7a6 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 000000000..53aeb036b --- /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 000000000..decd37c51 --- /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 000000000..699964656 --- /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 000000000..378ba8165 --- /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 000000000..ad9b484b7 --- /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 000000000..c49ce905b --- /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 000000000..5b3c7db73 --- /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 000000000..c677f7067 --- /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 eec893d32..e79f3b74b 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 000000000..65f3b767e --- /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 e45aba378..5d662d191 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 000000000..d00491fd7 --- /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 000000000..76d5ea08a --- /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 000000000..ff5dfb353 --- /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 $<$>:piciface>) diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict5-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict5-result.txt new file mode 100644 index 000000000..d00491fd7 --- /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 000000000..ecd04928d --- /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 000000000..e6055f450 --- /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 000000000..d00491fd7 --- /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 000000000..0254e5557 --- /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 000000000..7ea7c5f73 --- /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 $<$>>:picoff>) diff --git a/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake b/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake index 64a340c9c..3a2009b48 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 000000000..12cd3c775 --- /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 000000000..56caf683f --- /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 000000000..d00491fd7 --- /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 000000000..c66e0800a --- /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 000000000..51a109d32 --- /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 000000000..d00491fd7 --- /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 000000000..be11b7754 --- /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 000000000..3182e8933 --- /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)