From fe732264e9abb6249d1d112b24ce36b226590105 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 2 Nov 2012 15:47:40 +0100 Subject: 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_ 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. --- Source/cmAddLibraryCommand.cxx | 30 +++++- Source/cmAddLibraryCommand.h | 10 ++ Source/cmComputeLinkDepends.cxx | 7 ++ Source/cmComputeLinkInformation.cxx | 5 + Source/cmGlobalGenerator.cxx | 4 + Source/cmGlobalNinjaGenerator.cxx | 7 +- Source/cmGlobalUnixMakefileGenerator3.cxx | 8 ++ Source/cmGlobalVisualStudio6Generator.cxx | 4 + Source/cmGlobalVisualStudio7Generator.cxx | 4 + Source/cmGlobalVisualStudio8Generator.cxx | 4 + Source/cmGlobalVisualStudioGenerator.cxx | 4 + Source/cmGlobalXCodeGenerator.cxx | 25 ++++- Source/cmInstallTargetGenerator.cxx | 5 + Source/cmLocalGenerator.cxx | 8 ++ Source/cmLocalVisualStudio10Generator.cxx | 4 + Source/cmLocalVisualStudio6Generator.cxx | 10 +- Source/cmLocalVisualStudio7Generator.cxx | 12 ++- Source/cmMakefile.cxx | 5 +- Source/cmMakefileTargetGenerator.cxx | 7 +- Source/cmTarget.cxx | 108 +++++++++++++-------- Source/cmTarget.h | 1 + Source/cmTargetLinkLibrariesCommand.cxx | 14 +++ Source/cmTargetPropCommandBase.cxx | 9 ++ Source/cmVisualStudio10TargetGenerator.cxx | 8 +- Tests/AliasTarget/CMakeLists.txt | 3 + Tests/CMakeLists.txt | 1 + Tests/CompatibleInterface/CMakeLists.txt | 2 +- Tests/InterfaceLibrary/CMakeLists.txt | 15 +++ Tests/InterfaceLibrary/definetestexe.cpp | 9 ++ Tests/InterfaceLibrary/libsdir/CMakeLists.txt | 26 +++++ Tests/InterfaceLibrary/libsdir/shareddependlib.cpp | 7 ++ .../libsdir/shareddependlib/shareddependlib.h | 12 +++ Tests/InterfaceLibrary/libsdir/sharedlib.cpp | 12 +++ .../InterfaceLibrary/libsdir/sharedlib/sharedlib.h | 15 +++ Tests/InterfaceLibrary/sharedlibtestexe.cpp | 19 ++++ Tests/PositionIndependentTargets/CMakeLists.txt | 1 + .../interface/CMakeLists.txt | 27 ++++++ Tests/RunCMake/CMakeLists.txt | 1 + .../PositionIndependentCode/Conflict4-result.txt | 1 + .../PositionIndependentCode/Conflict4-stderr.txt | 4 + .../PositionIndependentCode/Conflict4.cmake | 8 ++ .../PositionIndependentCode/Conflict5-result.txt | 1 + .../PositionIndependentCode/Conflict5-stderr.txt | 3 + .../PositionIndependentCode/Conflict5.cmake | 9 ++ .../PositionIndependentCode/Conflict6-result.txt | 1 + .../PositionIndependentCode/Conflict6-stderr.txt | 4 + .../PositionIndependentCode/Conflict6.cmake | 8 ++ .../PositionIndependentCode/RunCMakeTest.cmake | 3 + Tests/RunCMake/interface_library/CMakeLists.txt | 3 + .../RunCMake/interface_library/RunCMakeTest.cmake | 4 + .../interface_library/invalid_name-result.txt | 1 + .../interface_library/invalid_name-stderr.txt | 9 ++ .../RunCMake/interface_library/invalid_name.cmake | 4 + .../interface_library/target_commands-result.txt | 1 + .../interface_library/target_commands-stderr.txt | 47 +++++++++ .../interface_library/target_commands.cmake | 13 +++ 56 files changed, 528 insertions(+), 49 deletions(-) create mode 100644 Tests/InterfaceLibrary/CMakeLists.txt create mode 100644 Tests/InterfaceLibrary/definetestexe.cpp create mode 100644 Tests/InterfaceLibrary/libsdir/CMakeLists.txt create mode 100644 Tests/InterfaceLibrary/libsdir/shareddependlib.cpp create mode 100644 Tests/InterfaceLibrary/libsdir/shareddependlib/shareddependlib.h create mode 100644 Tests/InterfaceLibrary/libsdir/sharedlib.cpp create mode 100644 Tests/InterfaceLibrary/libsdir/sharedlib/sharedlib.h create mode 100644 Tests/InterfaceLibrary/sharedlibtestexe.cpp create mode 100644 Tests/PositionIndependentTargets/interface/CMakeLists.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict4-result.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict4-stderr.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict4.cmake create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict5-result.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict5-stderr.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict5.cmake create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict6-result.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict6-stderr.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict6.cmake create mode 100644 Tests/RunCMake/interface_library/CMakeLists.txt create mode 100644 Tests/RunCMake/interface_library/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/interface_library/invalid_name-result.txt create mode 100644 Tests/RunCMake/interface_library/invalid_name-stderr.txt create mode 100644 Tests/RunCMake/interface_library/invalid_name.cmake create mode 100644 Tests/RunCMake/interface_library/target_commands-result.txt create mode 100644 Tests/RunCMake/interface_library/target_commands-stderr.txt create mode 100644 Tests/RunCMake/interface_library/target_commands.cmake 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 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 59354b0..64d048b 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 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::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 (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& 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(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(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 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 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 += "\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 a5eb0f6..fdb1638 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 9c3ed59..ca32aac 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 ae1d2fa..5ee9fd7 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 0000000..53aeb03 --- /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 0000000..decd37c --- /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 0000000..6999646 --- /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 0000000..378ba81 --- /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 0000000..ad9b484 --- /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 0000000..c49ce90 --- /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 0000000..5b3c7db --- /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 0000000..c677f70 --- /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 eec893d..e79f3b7 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 0000000..65f3b76 --- /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 e45aba3..5d662d1 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 0000000..d00491f --- /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 0000000..76d5ea0 --- /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 0000000..ff5dfb3 --- /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 0000000..d00491f --- /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 0000000..ecd0492 --- /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 0000000..e6055f4 --- /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 0000000..d00491f --- /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 0000000..0254e55 --- /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 0000000..7ea7c5f --- /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 64a340c..3a2009b 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 0000000..12cd3c7 --- /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 0000000..56caf68 --- /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 0000000..d00491f --- /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 0000000..c66e080 --- /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 0000000..51a109d --- /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 0000000..d00491f --- /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 0000000..be11b77 --- /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 0000000..3182e89 --- /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) -- cgit v0.12 From 435c912848b08333e03c74439f725c9b96890d80 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 20 Nov 2012 10:58:15 +0100 Subject: export: Add support for INTERFACE_LIBRARY targets --- Source/cmAddLibraryCommand.cxx | 10 ++++++ Source/cmCoreTryCompile.cxx | 1 + Source/cmExportBuildFileGenerator.cxx | 24 +++++++++---- Source/cmExportCommand.cxx | 3 +- Source/cmExportFileGenerator.cxx | 16 ++++++--- Source/cmTarget.cxx | 3 +- Tests/ExportImport/Export/CMakeLists.txt | 2 ++ Tests/ExportImport/Export/Interface/CMakeLists.txt | 29 +++++++++++++++ .../Export/Interface/headeronly/headeronly.h | 7 ++++ Tests/ExportImport/Export/Interface/sharedlib.cpp | 7 ++++ .../Export/Interface/sharedlib/sharedlib.h | 7 ++++ Tests/ExportImport/Import/CMakeLists.txt | 3 ++ Tests/ExportImport/Import/Interface/CMakeLists.txt | 42 ++++++++++++++++++++++ .../Import/Interface/headeronlytest.cpp | 17 +++++++++ .../Import/Interface/interfacetest.cpp | 20 +++++++++++ .../interface_library/invalid_name-stderr.txt | 6 ++++ .../RunCMake/interface_library/invalid_name.cmake | 2 ++ 17 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 Tests/ExportImport/Export/Interface/CMakeLists.txt create mode 100644 Tests/ExportImport/Export/Interface/headeronly/headeronly.h create mode 100644 Tests/ExportImport/Export/Interface/sharedlib.cpp create mode 100644 Tests/ExportImport/Export/Interface/sharedlib/sharedlib.h create mode 100644 Tests/ExportImport/Import/Interface/CMakeLists.txt create mode 100644 Tests/ExportImport/Import/Interface/headeronlytest.cpp create mode 100644 Tests/ExportImport/Import/Interface/interfacetest.cpp diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 130a033..0e61c99 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -220,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())) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 086f27a..6f3274e 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -99,6 +99,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) { case cmTarget::SHARED_LIBRARY: case cmTarget::STATIC_LIBRARY: + case cmTarget::INTERFACE_LIBRARY: case cmTarget::UNKNOWN_LIBRARY: break; case cmTarget::EXECUTABLE: diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index cdc3316..243e5ce 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -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; - this->SetImportLocationProperty(config, suffix, target, properties); + + if (target->GetType() != cmTarget::INTERFACE_LIBRARY) + { + this->SetImportLocationProperty(config, suffix, target, properties); + } if(!properties.empty()) { // Get the rest of the target details. - this->SetImportDetailProperties(config, suffix, - target, properties, missingTargets); - this->SetImportLinkInterface(config, suffix, - cmGeneratorExpression::BuildInterface, - target, properties, missingTargets); - + 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 diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index f059ceb..be2ee31 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -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); } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index ef336ea..8c841cb 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -378,11 +378,14 @@ void getCompatibleInterfaceProperties(cmTarget *target, if (!info) { - 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()); + 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; } @@ -887,6 +890,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; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2461ed6..8a00fa4 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -6164,7 +6164,8 @@ 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; } diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 72ae78f..62aa86c 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -426,3 +426,5 @@ export(TARGETS testExe2 testLib4 testLib5 testLib6 testExe3 testExe2lib NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake ) + +add_subdirectory(Interface) diff --git a/Tests/ExportImport/Export/Interface/CMakeLists.txt b/Tests/ExportImport/Export/Interface/CMakeLists.txt new file mode 100644 index 0000000..01e89ef --- /dev/null +++ b/Tests/ExportImport/Export/Interface/CMakeLists.txt @@ -0,0 +1,29 @@ + +add_library(headeronly INTERFACE) +set_property(TARGET headeronly PROPERTY INTERFACE_INCLUDE_DIRECTORIES + "$" + "$" +) +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 + "$" + "$/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 +) diff --git a/Tests/ExportImport/Export/Interface/headeronly/headeronly.h b/Tests/ExportImport/Export/Interface/headeronly/headeronly.h new file mode 100644 index 0000000..3673c21 --- /dev/null +++ b/Tests/ExportImport/Export/Interface/headeronly/headeronly.h @@ -0,0 +1,7 @@ + +enum { one }; + +struct HeaderOnly +{ + int foo() const { return 0; } +}; diff --git a/Tests/ExportImport/Export/Interface/sharedlib.cpp b/Tests/ExportImport/Export/Interface/sharedlib.cpp new file mode 100644 index 0000000..88ca713 --- /dev/null +++ b/Tests/ExportImport/Export/Interface/sharedlib.cpp @@ -0,0 +1,7 @@ + +#include "sharedlib.h" + +int SharedLibObject::foo() const +{ + return 0; +} diff --git a/Tests/ExportImport/Export/Interface/sharedlib/sharedlib.h b/Tests/ExportImport/Export/Interface/sharedlib/sharedlib.h new file mode 100644 index 0000000..aad9ef3 --- /dev/null +++ b/Tests/ExportImport/Export/Interface/sharedlib/sharedlib.h @@ -0,0 +1,7 @@ + +#include "sharedlib_export.h" + +struct SHAREDLIB_EXPORT SharedLibObject +{ + int foo() const; +}; diff --git a/Tests/ExportImport/Import/CMakeLists.txt b/Tests/ExportImport/Import/CMakeLists.txt index 9c2d597..5e809a2 100644 --- a/Tests/ExportImport/Import/CMakeLists.txt +++ b/Tests/ExportImport/Import/CMakeLists.txt @@ -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) diff --git a/Tests/ExportImport/Import/Interface/CMakeLists.txt b/Tests/ExportImport/Import/Interface/CMakeLists.txt new file mode 100644 index 0000000..c8c8401 --- /dev/null +++ b/Tests/ExportImport/Import/Interface/CMakeLists.txt @@ -0,0 +1,42 @@ + +# Import targets from the exported build tree. +include(${Import_BINARY_DIR}/../Export/ExportInterfaceBuildTree.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_) diff --git a/Tests/ExportImport/Import/Interface/headeronlytest.cpp b/Tests/ExportImport/Import/Interface/headeronlytest.cpp new file mode 100644 index 0000000..20674a7 --- /dev/null +++ b/Tests/ExportImport/Import/Interface/headeronlytest.cpp @@ -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(); +} diff --git a/Tests/ExportImport/Import/Interface/interfacetest.cpp b/Tests/ExportImport/Import/Interface/interfacetest.cpp new file mode 100644 index 0000000..786458d --- /dev/null +++ b/Tests/ExportImport/Import/Interface/interfacetest.cpp @@ -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(); +} diff --git a/Tests/RunCMake/interface_library/invalid_name-stderr.txt b/Tests/RunCMake/interface_library/invalid_name-stderr.txt index c66e080..e14fcde 100644 --- a/Tests/RunCMake/interface_library/invalid_name-stderr.txt +++ b/Tests/RunCMake/interface_library/invalid_name-stderr.txt @@ -7,3 +7,9 @@ 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\) diff --git a/Tests/RunCMake/interface_library/invalid_name.cmake b/Tests/RunCMake/interface_library/invalid_name.cmake index 51a109d..9a965aa 100644 --- a/Tests/RunCMake/interface_library/invalid_name.cmake +++ b/Tests/RunCMake/interface_library/invalid_name.cmake @@ -2,3 +2,5 @@ add_library(if$ace INTERFACE) add_library(iface::target INTERFACE) + +add_library(if$target_imported INTERFACE IMPORTED) -- cgit v0.12 From ce0c303d62941d2b10098b1ec00de3ced8556919 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 20 Nov 2012 11:06:29 +0100 Subject: install: Teach EXPORT option to handle INTERFACE_LIBRARY targets --- Source/cmExportInstallFileGenerator.cxx | 19 ++++++++++++++++++- Source/cmInstallCommand.cxx | 8 +++++++- Tests/ExportImport/Export/Interface/CMakeLists.txt | 20 ++++++++++++++++++++ Tests/ExportImport/Import/Interface/CMakeLists.txt | 13 +++++++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index c8b4a79..c71008e 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -114,6 +114,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) std::vector missingTargets; bool require2_8_12 = false; + bool require2_8_13 = false; // Create all the imported targets. for(std::vector::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 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, diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 3c76bd6..d309a2a 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -379,7 +379,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector 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 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. diff --git a/Tests/ExportImport/Export/Interface/CMakeLists.txt b/Tests/ExportImport/Export/Interface/CMakeLists.txt index 01e89ef..fc9c0c7 100644 --- a/Tests/ExportImport/Export/Interface/CMakeLists.txt +++ b/Tests/ExportImport/Export/Interface/CMakeLists.txt @@ -27,3 +27,23 @@ 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) diff --git a/Tests/ExportImport/Import/Interface/CMakeLists.txt b/Tests/ExportImport/Import/Interface/CMakeLists.txt index c8c8401..c7bd13e 100644 --- a/Tests/ExportImport/Import/Interface/CMakeLists.txt +++ b/Tests/ExportImport/Import/Interface/CMakeLists.txt @@ -2,6 +2,9 @@ # 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) @@ -40,3 +43,13 @@ macro(do_try_compile prefix) 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_) -- cgit v0.12