Merge topic 'refactor-link-internals'

f5c18c9c cmTarget: Drop GetDirectLinkLibraries methods
281eb3d8 cmTarget: Improve HaveBuildTreeRPATH implementation
d912220e cmTarget: Lookup targets in LinkInterface and LinkImplementation
edce4351 cmExportFileGenerator: Make SetImportLinkProperty a template
097be413 cmTarget: Add GetUtilityItems to get target ordering dependencies
4dad5fd2 cmTarget: Add cmLinkItem to refer to a target by name and pointer
a2723442 Fix scope of transitive target name lookups
069d60fe cmTarget: Add method to lookup other targets in a target's scope
47ab3ca6 cmTarget: Constify GetLinkImplementationClosure results
9f3ed029 cmTarget: Constify GetTransitivePropertyTargets results
6f0951af cmTarget: Drop 'head' target from GetImportInfo
0dc9e88d cmTarget: Remove 'head' argument from GetLinkImplementation
4ac72455 cmTarget: Drop 'head' argument from GetLinkClosure
bcdb7ff9 cmTarget: Remove 'head' argument from GetLinkerLanguage
bd9b667b cmComputeLinkInformation: Remove 'head' argument
06328dd5 cmTarget: Remove 'head' argument from GetLinkInformation
...
This commit is contained in:
Brad King 2014-06-25 13:11:50 -04:00 committed by CMake Topic Stage
commit cbf0107977
17 changed files with 467 additions and 407 deletions

View File

@ -172,12 +172,10 @@ satisfy dependencies.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmComputeLinkDepends cmComputeLinkDepends
::cmComputeLinkDepends(cmTarget const* target, const std::string& config, ::cmComputeLinkDepends(cmTarget const* target, const std::string& config)
cmTarget const* head)
{ {
// Store context information. // Store context information.
this->Target = target; this->Target = target;
this->HeadTarget = head;
this->Makefile = this->Target->GetMakefile(); this->Makefile = this->Target->GetMakefile();
this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->LocalGenerator = this->Makefile->GetLocalGenerator();
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
@ -294,8 +292,7 @@ cmComputeLinkDepends::AllocateLinkEntry(std::string const& item)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int cmComputeLinkDepends::AddLinkEntry(int depender_index, int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
std::string const& item)
{ {
// Check if the item entry has already been added. // Check if the item entry has already been added.
std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item); std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item);
@ -312,7 +309,7 @@ int cmComputeLinkDepends::AddLinkEntry(int depender_index,
int index = lei->second; int index = lei->second;
LinkEntry& entry = this->EntryList[index]; LinkEntry& entry = this->EntryList[index];
entry.Item = item; entry.Item = item;
entry.Target = this->FindTargetToLink(depender_index, entry.Item); entry.Target = item.Target;
entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' && entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
item.substr(0, 10) != "-framework"); item.substr(0, 10) != "-framework");
@ -356,7 +353,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
{ {
// Follow the target dependencies. // Follow the target dependencies.
if(cmTarget::LinkInterface const* iface = if(cmTarget::LinkInterface const* iface =
entry.Target->GetLinkInterface(this->Config, this->HeadTarget)) entry.Target->GetLinkInterface(this->Config, this->Target))
{ {
const bool isIface = const bool isIface =
entry.Target->GetType() == cmTarget::INTERFACE_LIBRARY; entry.Target->GetType() == cmTarget::INTERFACE_LIBRARY;
@ -372,11 +369,11 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
this->FollowSharedDeps(depender_index, iface); this->FollowSharedDeps(depender_index, iface);
// Support for CMP0003. // Support for CMP0003.
for(std::vector<std::string>::const_iterator for(std::vector<cmLinkItem>::const_iterator
oi = iface->WrongConfigLibraries.begin(); oi = iface->WrongConfigLibraries.begin();
oi != iface->WrongConfigLibraries.end(); ++oi) oi != iface->WrongConfigLibraries.end(); ++oi)
{ {
this->CheckWrongConfigItem(depender_index, *oi); this->CheckWrongConfigItem(*oi);
} }
} }
} }
@ -408,9 +405,9 @@ cmComputeLinkDepends
void void
cmComputeLinkDepends cmComputeLinkDepends
::QueueSharedDependencies(int depender_index, ::QueueSharedDependencies(int depender_index,
std::vector<std::string> const& deps) std::vector<cmLinkItem> const& deps)
{ {
for(std::vector<std::string>::const_iterator li = deps.begin(); for(std::vector<cmLinkItem>::const_iterator li = deps.begin();
li != deps.end(); ++li) li != deps.end(); ++li)
{ {
SharedDepEntry qe; SharedDepEntry qe;
@ -434,8 +431,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
// Initialize the item entry. // Initialize the item entry.
LinkEntry& entry = this->EntryList[lei->second]; LinkEntry& entry = this->EntryList[lei->second];
entry.Item = dep.Item; entry.Item = dep.Item;
entry.Target = this->FindTargetToLink(dep.DependerIndex, entry.Target = dep.Item.Target;
dep.Item);
// This item was added specifically because it is a dependent // This item was added specifically because it is a dependent
// shared library. It may get special treatment // shared library. It may get special treatment
@ -455,7 +451,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
if(entry.Target) if(entry.Target)
{ {
if(cmTarget::LinkInterface const* iface = if(cmTarget::LinkInterface const* iface =
entry.Target->GetLinkInterface(this->Config, this->HeadTarget)) entry.Target->GetLinkInterface(this->Config, this->Target))
{ {
// Follow public and private dependencies transitively. // Follow public and private dependencies transitively.
this->FollowSharedDeps(index, iface, true); this->FollowSharedDeps(index, iface, true);
@ -474,7 +470,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
cmSystemTools::ExpandListArgument(value, deplist); cmSystemTools::ExpandListArgument(value, deplist);
// Look for entries meant for this configuration. // Look for entries meant for this configuration.
std::vector<std::string> actual_libs; std::vector<cmLinkItem> actual_libs;
cmTarget::LinkLibraryType llt = cmTarget::GENERAL; cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
bool haveLLT = false; bool haveLLT = false;
for(std::vector<std::string>::const_iterator di = deplist.begin(); for(std::vector<std::string>::const_iterator di = deplist.begin();
@ -522,11 +518,13 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
// If the library is meant for this link type then use it. // If the library is meant for this link type then use it.
if(llt == cmTarget::GENERAL || llt == this->LinkType) if(llt == cmTarget::GENERAL || llt == this->LinkType)
{ {
actual_libs.push_back(*di); cmLinkItem item(*di, this->FindTargetToLink(depender_index, *di));
actual_libs.push_back(item);
} }
else if(this->OldLinkDirMode) else if(this->OldLinkDirMode)
{ {
this->CheckWrongConfigItem(depender_index, *di); cmLinkItem item(*di, this->FindTargetToLink(depender_index, *di));
this->CheckWrongConfigItem(item);
} }
// Reset the link type until another explicit type is given. // Reset the link type until another explicit type is given.
@ -544,38 +542,38 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
{ {
// Add direct link dependencies in this configuration. // Add direct link dependencies in this configuration.
cmTarget::LinkImplementation const* impl = cmTarget::LinkImplementation const* impl =
this->Target->GetLinkImplementation(this->Config, this->HeadTarget); this->Target->GetLinkImplementation(this->Config);
this->AddLinkEntries(-1, impl->Libraries); this->AddLinkEntries(-1, impl->Libraries);
for(std::vector<std::string>::const_iterator for(std::vector<cmLinkItem>::const_iterator
wi = impl->WrongConfigLibraries.begin(); wi = impl->WrongConfigLibraries.begin();
wi != impl->WrongConfigLibraries.end(); ++wi) wi != impl->WrongConfigLibraries.end(); ++wi)
{ {
this->CheckWrongConfigItem(-1, *wi); this->CheckWrongConfigItem(*wi);
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmComputeLinkDepends::AddLinkEntries(int depender_index, cmComputeLinkDepends::AddLinkEntries(
std::vector<std::string> const& libs) int depender_index, std::vector<cmLinkItem> const& libs)
{ {
// Track inferred dependency sets implied by this list. // Track inferred dependency sets implied by this list.
std::map<int, DependSet> dependSets; std::map<int, DependSet> dependSets;
// Loop over the libraries linked directly by the depender. // Loop over the libraries linked directly by the depender.
for(std::vector<std::string>::const_iterator li = libs.begin(); for(std::vector<cmLinkItem>::const_iterator li = libs.begin();
li != libs.end(); ++li) li != libs.end(); ++li)
{ {
// Skip entries that will resolve to the target getting linked or // Skip entries that will resolve to the target getting linked or
// are empty. // are empty.
std::string item = this->Target->CheckCMP0004(*li); cmLinkItem const& item = *li;
if(item == this->Target->GetName() || item.empty()) if(item == this->Target->GetName() || item.empty())
{ {
continue; continue;
} }
// Add a link entry for this item. // Add a link entry for this item.
int dependee_index = this->AddLinkEntry(depender_index, item); int dependee_index = this->AddLinkEntry(*li);
// The dependee must come after the depender. // The dependee must come after the depender.
if(depender_index >= 0) if(depender_index >= 0)
@ -625,40 +623,15 @@ cmTarget const* cmComputeLinkDepends::FindTargetToLink(int depender_index,
const std::string& name) const std::string& name)
{ {
// Look for a target in the scope of the depender. // Look for a target in the scope of the depender.
cmMakefile* mf = this->Makefile; cmTarget const* from = this->Target;
if(depender_index >= 0) if(depender_index >= 0)
{ {
if(cmTarget const* depender = this->EntryList[depender_index].Target) if(cmTarget const* depender = this->EntryList[depender_index].Target)
{ {
mf = depender->GetMakefile(); from = depender;
} }
} }
cmTarget const* tgt = mf->FindTargetToUse(name); return from->FindTargetToLink(name);
// Skip targets that will not really be linked. This is probably a
// name conflict between an external library and an executable
// within the project.
if(tgt && tgt->GetType() == cmTarget::EXECUTABLE &&
!tgt->IsExecutableWithExports())
{
tgt = 0;
}
if(tgt && tgt->GetType() == cmTarget::OBJECT_LIBRARY)
{
cmOStringStream e;
e << "Target \"" << this->Target->GetName() << "\" links to "
"OBJECT library \"" << tgt->GetName() << "\" but this is not "
"allowed. "
"One may link only to STATIC or SHARED libraries, or to executables "
"with the ENABLE_EXPORTS property set.";
this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
this->Target->GetBacktrace());
tgt = 0;
}
// Return the target found, if any.
return tgt;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -955,7 +928,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
if(cmTarget const* target = this->EntryList[*ni].Target) if(cmTarget const* target = this->EntryList[*ni].Target)
{ {
if(cmTarget::LinkInterface const* iface = if(cmTarget::LinkInterface const* iface =
target->GetLinkInterface(this->Config, this->HeadTarget)) target->GetLinkInterface(this->Config, this->Target))
{ {
if(iface->Multiplicity > count) if(iface->Multiplicity > count)
{ {
@ -988,8 +961,7 @@ void cmComputeLinkDepends::DisplayFinalEntries()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmComputeLinkDepends::CheckWrongConfigItem(int depender_index, void cmComputeLinkDepends::CheckWrongConfigItem(cmLinkItem const& item)
std::string const& item)
{ {
if(!this->OldLinkDirMode) if(!this->OldLinkDirMode)
{ {
@ -999,12 +971,8 @@ void cmComputeLinkDepends::CheckWrongConfigItem(int depender_index,
// For CMake 2.4 bug-compatibility we need to consider the output // For CMake 2.4 bug-compatibility we need to consider the output
// directories of targets linked in another configuration as link // directories of targets linked in another configuration as link
// directories. // directories.
if(cmTarget const* tgt if(item.Target && !item.Target->IsImported())
= this->FindTargetToLink(depender_index, item))
{ {
if(!tgt->IsImported()) this->OldWrongConfigItems.insert(item.Target);
{
this->OldWrongConfigItems.insert(tgt);
}
} }
} }

View File

@ -32,8 +32,7 @@ class cmake;
class cmComputeLinkDepends class cmComputeLinkDepends
{ {
public: public:
cmComputeLinkDepends(cmTarget const* target, const std::string& config, cmComputeLinkDepends(cmTarget const* target, const std::string& config);
cmTarget const* head);
~cmComputeLinkDepends(); ~cmComputeLinkDepends();
// Basic information about each link item. // Basic information about each link item.
@ -60,7 +59,6 @@ private:
// Context information. // Context information.
cmTarget const* Target; cmTarget const* Target;
cmTarget const* HeadTarget;
cmMakefile* Makefile; cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator; cmLocalGenerator* LocalGenerator;
cmGlobalGenerator const* GlobalGenerator; cmGlobalGenerator const* GlobalGenerator;
@ -79,11 +77,11 @@ private:
std::map<std::string, int>::iterator std::map<std::string, int>::iterator
AllocateLinkEntry(std::string const& item); AllocateLinkEntry(std::string const& item);
int AddLinkEntry(int depender_index, std::string const& item); int AddLinkEntry(cmLinkItem const& item);
void AddVarLinkEntries(int depender_index, const char* value); void AddVarLinkEntries(int depender_index, const char* value);
void AddDirectLinkEntries(); void AddDirectLinkEntries();
void AddLinkEntries(int depender_index, void AddLinkEntries(int depender_index,
std::vector<std::string> const& libs); std::vector<cmLinkItem> const& libs);
cmTarget const* FindTargetToLink(int depender_index, cmTarget const* FindTargetToLink(int depender_index,
const std::string& name); const std::string& name);
@ -105,7 +103,7 @@ private:
// of the interface. // of the interface.
struct SharedDepEntry struct SharedDepEntry
{ {
std::string Item; cmLinkItem Item;
int DependerIndex; int DependerIndex;
}; };
std::queue<SharedDepEntry> SharedDepQueue; std::queue<SharedDepEntry> SharedDepQueue;
@ -114,7 +112,7 @@ private:
cmTarget::LinkInterface const* iface, cmTarget::LinkInterface const* iface,
bool follow_interface = false); bool follow_interface = false);
void QueueSharedDependencies(int depender_index, void QueueSharedDependencies(int depender_index,
std::vector<std::string> const& deps); std::vector<cmLinkItem> const& deps);
void HandleSharedDependency(SharedDepEntry const& dep); void HandleSharedDependency(SharedDepEntry const& dep);
// Dependency inferral for each link item. // Dependency inferral for each link item.
@ -165,7 +163,7 @@ private:
// Compatibility help. // Compatibility help.
bool OldLinkDirMode; bool OldLinkDirMode;
void CheckWrongConfigItem(int depender_index, std::string const& item); void CheckWrongConfigItem(cmLinkItem const& item);
std::set<cmTarget const*> OldWrongConfigItems; std::set<cmTarget const*> OldWrongConfigItems;
}; };

View File

@ -239,12 +239,10 @@ because this need be done only for shared libraries without soname-s.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmComputeLinkInformation cmComputeLinkInformation
::cmComputeLinkInformation(cmTarget const* target, const std::string& config, ::cmComputeLinkInformation(cmTarget const* target, const std::string& config)
cmTarget const* headTarget)
{ {
// Store context information. // Store context information.
this->Target = target; this->Target = target;
this->HeadTarget = headTarget;
this->Makefile = this->Target->GetMakefile(); this->Makefile = this->Target->GetMakefile();
this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->LocalGenerator = this->Makefile->GetLocalGenerator();
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
@ -267,7 +265,7 @@ cmComputeLinkInformation
this->OrderDependentRPath = 0; this->OrderDependentRPath = 0;
// Get the language used for linking this target. // Get the language used for linking this target.
this->LinkLanguage = this->Target->GetLinkerLanguage(config, headTarget); this->LinkLanguage = this->Target->GetLinkerLanguage(config);
if(this->LinkLanguage.empty()) if(this->LinkLanguage.empty())
{ {
// The Compute method will do nothing, so skip the rest of the // The Compute method will do nothing, so skip the rest of the
@ -505,8 +503,7 @@ bool cmComputeLinkInformation::Compute()
} }
// Compute the ordered link line items. // Compute the ordered link line items.
cmComputeLinkDepends cld(this->Target, this->Config, cmComputeLinkDepends cld(this->Target, this->Config);
this->HeadTarget);
cld.SetOldLinkDirMode(this->OldLinkDirMode); cld.SetOldLinkDirMode(this->OldLinkDirMode);
cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute(); cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute();
@ -572,8 +569,7 @@ bool cmComputeLinkInformation::Compute()
void cmComputeLinkInformation::AddImplicitLinkInfo() void cmComputeLinkInformation::AddImplicitLinkInfo()
{ {
// The link closure lists all languages whose implicit info is needed. // The link closure lists all languages whose implicit info is needed.
cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config, cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config);
this->HeadTarget);
for(std::vector<std::string>::const_iterator li = lc->Languages.begin(); for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
li != lc->Languages.end(); ++li) li != lc->Languages.end(); ++li)
{ {
@ -1972,7 +1968,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
// present. This is done even when skipping rpath support. // present. This is done even when skipping rpath support.
{ {
cmTarget::LinkClosure const* lc = cmTarget::LinkClosure const* lc =
this->Target->GetLinkClosure(this->Config, this->HeadTarget); this->Target->GetLinkClosure(this->Config);
for(std::vector<std::string>::const_iterator li = lc->Languages.begin(); for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
li != lc->Languages.end(); ++li) li != lc->Languages.end(); ++li)
{ {

View File

@ -29,8 +29,7 @@ class cmOrderDirectories;
class cmComputeLinkInformation class cmComputeLinkInformation
{ {
public: public:
cmComputeLinkInformation(cmTarget const* target, const std::string& config, cmComputeLinkInformation(cmTarget const* target, const std::string& config);
cmTarget const* headTarget);
~cmComputeLinkInformation(); ~cmComputeLinkInformation();
bool Compute(); bool Compute();
@ -75,7 +74,6 @@ private:
// Context information. // Context information.
cmTarget const* Target; cmTarget const* Target;
cmTarget const* HeadTarget;
cmMakefile* Makefile; cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator; cmLocalGenerator* LocalGenerator;
cmGlobalGenerator* GlobalGenerator; cmGlobalGenerator* GlobalGenerator;

View File

@ -249,20 +249,21 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
const_cast<cmTarget*>(depender)->AddUtility(objLib); const_cast<cmTarget*>(depender)->AddUtility(objLib);
} }
} }
std::vector<std::string> tlibs;
depender->GetDirectLinkLibraries(*it, tlibs, depender); cmTarget::LinkImplementation const* impl =
depender->GetLinkImplementation(*it);
// A target should not depend on itself. // A target should not depend on itself.
emitted.insert(depender->GetName()); emitted.insert(depender->GetName());
for(std::vector<std::string>::const_iterator lib = tlibs.begin(); for(std::vector<cmLinkItem>::const_iterator
lib != tlibs.end(); ++lib) lib = impl->Libraries.begin();
lib != impl->Libraries.end(); ++lib)
{ {
// Don't emit the same library twice for this target. // Don't emit the same library twice for this target.
if(emitted.insert(*lib).second) if(emitted.insert(*lib).second)
{ {
this->AddTargetDepend(depender_index, *lib, true); this->AddTargetDepend(depender_index, *lib, true);
this->AddInterfaceDepends(depender_index, *lib, this->AddInterfaceDepends(depender_index, *lib, emitted);
true, emitted);
} }
} }
} }
@ -270,11 +271,11 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
// Loop over all utility dependencies. // Loop over all utility dependencies.
{ {
std::set<std::string> const& tutils = depender->GetUtilities(); std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
std::set<std::string> emitted; std::set<std::string> emitted;
// A target should not depend on itself. // A target should not depend on itself.
emitted.insert(depender->GetName()); emitted.insert(depender->GetName());
for(std::set<std::string>::const_iterator util = tutils.begin(); for(std::set<cmLinkItem>::const_iterator util = tutils.begin();
util != tutils.end(); ++util) util != tutils.end(); ++util)
{ {
// Don't emit the same utility twice for this target. // Don't emit the same utility twice for this target.
@ -296,7 +297,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
if(cmTarget::LinkInterface const* iface = if(cmTarget::LinkInterface const* iface =
dependee->GetLinkInterface(config, depender)) dependee->GetLinkInterface(config, depender))
{ {
for(std::vector<std::string>::const_iterator for(std::vector<cmLinkItem>::const_iterator
lib = iface->Libraries.begin(); lib = iface->Libraries.begin();
lib != iface->Libraries.end(); ++lib) lib != iface->Libraries.end(); ++lib)
{ {
@ -304,8 +305,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
if(emitted.insert(*lib).second) if(emitted.insert(*lib).second)
{ {
this->AddTargetDepend(depender_index, *lib, true); this->AddTargetDepend(depender_index, *lib, true);
this->AddInterfaceDepends(depender_index, *lib, this->AddInterfaceDepends(depender_index, *lib, emitted);
true, emitted);
} }
} }
} }
@ -313,17 +313,15 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
const std::string& dependee_name, cmLinkItem const& dependee_name,
bool linking,
std::set<std::string> &emitted) std::set<std::string> &emitted)
{ {
cmTarget const* depender = this->Targets[depender_index]; cmTarget const* depender = this->Targets[depender_index];
cmTarget const* dependee = cmTarget const* dependee = dependee_name.Target;
depender->GetMakefile()->FindTargetToUse(dependee_name);
// Skip targets that will not really be linked. This is probably a // Skip targets that will not really be linked. This is probably a
// name conflict between an external library and an executable // name conflict between an external library and an executable
// within the project. // within the project.
if(linking && dependee && if(dependee &&
dependee->GetType() == cmTarget::EXECUTABLE && dependee->GetType() == cmTarget::EXECUTABLE &&
!dependee->IsExecutableWithExports()) !dependee->IsExecutableWithExports())
{ {
@ -347,16 +345,15 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmComputeTargetDepends::AddTargetDepend(int depender_index, void cmComputeTargetDepends::AddTargetDepend(
const std::string& dependee_name, int depender_index, cmLinkItem const& dependee_name,
bool linking) bool linking)
{ {
// Get the depender. // Get the depender.
cmTarget const* depender = this->Targets[depender_index]; cmTarget const* depender = this->Targets[depender_index];
// Check the target's makefile first. // Check the target's makefile first.
cmTarget const* dependee = cmTarget const* dependee = dependee_name.Target;
depender->GetMakefile()->FindTargetToUse(dependee_name);
if(!dependee && !linking && if(!dependee && !linking &&
(depender->GetType() != cmTarget::GLOBAL_TARGET)) (depender->GetType() != cmTarget::GLOBAL_TARGET))
@ -424,12 +421,11 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
if(dependee->IsImported()) if(dependee->IsImported())
{ {
// Skip imported targets but follow their utility dependencies. // Skip imported targets but follow their utility dependencies.
std::set<std::string> const& utils = dependee->GetUtilities(); std::set<cmLinkItem> const& utils = dependee->GetUtilityItems();
for(std::set<std::string>::const_iterator i = utils.begin(); for(std::set<cmLinkItem>::const_iterator i = utils.begin();
i != utils.end(); ++i) i != utils.end(); ++i)
{ {
if(cmTarget const* transitive_dependee = if(cmTarget const* transitive_dependee = i->Target)
dependee->GetMakefile()->FindTargetToUse(*i))
{ {
this->AddTargetDepend(depender_index, transitive_dependee, false); this->AddTargetDepend(depender_index, transitive_dependee, false);
} }

View File

@ -20,6 +20,7 @@
class cmComputeComponentGraph; class cmComputeComponentGraph;
class cmGlobalGenerator; class cmGlobalGenerator;
class cmLinkItem;
class cmTarget; class cmTarget;
class cmTargetDependSet; class cmTargetDependSet;
@ -46,14 +47,14 @@ private:
void CollectDepends(); void CollectDepends();
void CollectTargetDepends(int depender_index); void CollectTargetDepends(int depender_index);
void AddTargetDepend(int depender_index, void AddTargetDepend(int depender_index,
const std::string& dependee_name, cmLinkItem const& dependee_name,
bool linking); bool linking);
void AddTargetDepend(int depender_index, cmTarget const* dependee, void AddTargetDepend(int depender_index, cmTarget const* dependee,
bool linking); bool linking);
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
void AddInterfaceDepends(int depender_index, void AddInterfaceDepends(int depender_index,
const std::string& dependee_name, cmLinkItem const& dependee_name,
bool linking, std::set<std::string> &emitted); std::set<std::string> &emitted);
void AddInterfaceDepends(int depender_index, cmTarget const* dependee, void AddInterfaceDepends(int depender_index, cmTarget const* dependee,
const std::string& config, const std::string& config,
std::set<std::string> &emitted); std::set<std::string> &emitted);

View File

@ -865,12 +865,13 @@ cmExportFileGenerator
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template <typename T>
void void
cmExportFileGenerator cmExportFileGenerator
::SetImportLinkProperty(std::string const& suffix, ::SetImportLinkProperty(std::string const& suffix,
cmTarget* target, cmTarget* target,
const std::string& propName, const std::string& propName,
std::vector<std::string> const& entries, std::vector<T> const& entries,
ImportPropertyMap& properties, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets std::vector<std::string>& missingTargets
) )
@ -884,7 +885,7 @@ cmExportFileGenerator
// Construct the property value. // Construct the property value.
std::string link_entries; std::string link_entries;
const char* sep = ""; const char* sep = "";
for(std::vector<std::string>::const_iterator li = entries.begin(); for(typename std::vector<T>::const_iterator li = entries.begin();
li != entries.end(); ++li) li != entries.end(); ++li)
{ {
// Separate this from the previous entry. // Separate this from the previous entry.
@ -902,7 +903,6 @@ cmExportFileGenerator
properties[prop] = link_entries; properties[prop] = link_entries;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os, void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
const std::string& config) const std::string& config)

View File

@ -95,9 +95,11 @@ protected:
std::string const& suffix, cmTarget* target, std::string const& suffix, cmTarget* target,
ImportPropertyMap& properties, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets); std::vector<std::string>& missingTargets);
template <typename T>
void SetImportLinkProperty(std::string const& suffix, void SetImportLinkProperty(std::string const& suffix,
cmTarget* target, const std::string& propName, cmTarget* target, const std::string& propName,
std::vector<std::string> const& entries, std::vector<T> const& entries,
ImportPropertyMap& properties, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets); std::vector<std::string>& missingTargets);

View File

@ -799,7 +799,8 @@ static const char* targetPropertyTransitiveWhitelist[] = {
#undef TRANSITIVE_PROPERTY_NAME #undef TRANSITIVE_PROPERTY_NAME
std::string getLinkedTargetsContent(const std::vector<cmTarget*> &targets, std::string getLinkedTargetsContent(
std::vector<cmTarget const*> &targets,
cmTarget const* target, cmTarget const* target,
cmTarget const* headTarget, cmTarget const* headTarget,
cmGeneratorExpressionContext *context, cmGeneratorExpressionContext *context,
@ -810,7 +811,7 @@ std::string getLinkedTargetsContent(const std::vector<cmTarget*> &targets,
std::string sep; std::string sep;
std::string depString; std::string depString;
for (std::vector<cmTarget*>::const_iterator for (std::vector<cmTarget const*>::const_iterator
it = targets.begin(); it = targets.begin();
it != targets.end(); ++it) it != targets.end(); ++it)
{ {
@ -827,7 +828,7 @@ std::string getLinkedTargetsContent(const std::vector<cmTarget*> &targets,
sep = ";"; sep = ";";
} }
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString);
std::string linkedTargetsContent = cge->Evaluate(context->Makefile, std::string linkedTargetsContent = cge->Evaluate(target->GetMakefile(),
context->Config, context->Config,
context->Quiet, context->Quiet,
headTarget, headTarget,
@ -840,21 +841,21 @@ std::string getLinkedTargetsContent(const std::vector<cmTarget*> &targets,
return linkedTargetsContent; return linkedTargetsContent;
} }
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, std::string getLinkedTargetsContent(std::vector<cmLinkItem> const &libraries,
cmTarget const* target, cmTarget const* target,
cmTarget const* headTarget, cmTarget const* headTarget,
cmGeneratorExpressionContext *context, cmGeneratorExpressionContext *context,
cmGeneratorExpressionDAGChecker *dagChecker, cmGeneratorExpressionDAGChecker *dagChecker,
const std::string &interfacePropertyName) const std::string &interfacePropertyName)
{ {
std::vector<cmTarget*> tgts; std::vector<cmTarget const*> tgts;
for (std::vector<std::string>::const_iterator for (std::vector<cmLinkItem>::const_iterator
it = libraries.begin(); it = libraries.begin();
it != libraries.end(); ++it) it != libraries.end(); ++it)
{ {
if (cmTarget *tgt = context->Makefile->FindTargetToUse(*it)) if (it->Target)
{ {
tgts.push_back(tgt); tgts.push_back(it->Target);
} }
} }
return getLinkedTargetsContent(tgts, target, headTarget, context, return getLinkedTargetsContent(tgts, target, headTarget, context,
@ -1082,7 +1083,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
cmStrCmp(propertyName)) != transEnd) cmStrCmp(propertyName)) != transEnd)
{ {
std::vector<cmTarget*> tgts; std::vector<cmTarget const*> tgts;
target->GetTransitivePropertyTargets(context->Config, target->GetTransitivePropertyTargets(context->Config,
headTarget, tgts); headTarget, tgts);
if (!tgts.empty()) if (!tgts.empty())
@ -1098,8 +1099,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
cmStrCmp(interfacePropertyName)) != transEnd) cmStrCmp(interfacePropertyName)) != transEnd)
{ {
const cmTarget::LinkImplementation *impl const cmTarget::LinkImplementation *impl
= target->GetLinkImplementationLibraries(context->Config, = target->GetLinkImplementationLibraries(context->Config);
headTarget);
if(impl) if(impl)
{ {
linkedTargetsContent = linkedTargetsContent =

View File

@ -252,7 +252,7 @@ cmGeneratorTarget::GetSourceDepends(cmSourceFile const* sf) const
return 0; return 0;
} }
static void handleSystemIncludesDep(cmMakefile *mf, cmTarget* depTgt, static void handleSystemIncludesDep(cmMakefile *mf, cmTarget const* depTgt,
const std::string& config, const std::string& config,
cmTarget *headTarget, cmTarget *headTarget,
cmGeneratorExpressionDAGChecker *dagChecker, cmGeneratorExpressionDAGChecker *dagChecker,
@ -449,7 +449,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir,
if (iter == this->SystemIncludesCache.end()) if (iter == this->SystemIncludesCache.end())
{ {
cmTarget::LinkImplementation const* impl cmTarget::LinkImplementation const* impl
= this->Target->GetLinkImplementation(config, this->Target); = this->Target->GetLinkImplementation(config);
if(!impl) if(!impl)
{ {
return false; return false;
@ -474,11 +474,11 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir,
&dagChecker), result); &dagChecker), result);
} }
std::set<cmTarget*> uniqueDeps; std::set<cmTarget const*> uniqueDeps;
for(std::vector<std::string>::const_iterator li = impl->Libraries.begin(); for(std::vector<cmLinkItem>::const_iterator li = impl->Libraries.begin();
li != impl->Libraries.end(); ++li) li != impl->Libraries.end(); ++li)
{ {
cmTarget* tgt = this->Makefile->FindTargetToUse(*li); cmTarget const* tgt = li->Target;
if (!tgt) if (!tgt)
{ {
continue; continue;
@ -489,10 +489,10 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir,
handleSystemIncludesDep(this->Makefile, tgt, config, this->Target, handleSystemIncludesDep(this->Makefile, tgt, config, this->Target,
&dagChecker, result, excludeImported); &dagChecker, result, excludeImported);
std::vector<cmTarget*> deps; std::vector<cmTarget const*> deps;
tgt->GetTransitivePropertyTargets(config, this->Target, deps); tgt->GetTransitivePropertyTargets(config, this->Target, deps);
for(std::vector<cmTarget*>::const_iterator di = deps.begin(); for(std::vector<cmTarget const*>::const_iterator di = deps.begin();
di != deps.end(); ++di) di != deps.end(); ++di)
{ {
if (uniqueDeps.insert(*di).second) if (uniqueDeps.insert(*di).second)

View File

@ -1255,7 +1255,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
// If the language is compiled as a source trust Xcode to link with it. // If the language is compiled as a source trust Xcode to link with it.
cmTarget::LinkImplementation const* impl = cmTarget::LinkImplementation const* impl =
cmtarget.GetLinkImplementation("NOCONFIG", &cmtarget); cmtarget.GetLinkImplementation("NOCONFIG");
for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
li != impl->Languages.end(); ++li) li != impl->Languages.end(); ++li)
{ {

View File

@ -64,11 +64,16 @@ struct cmTarget::OutputInfo
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
struct cmTarget::ImportInfo struct cmTarget::ImportInfo
{ {
ImportInfo(): NoSOName(false), Multiplicity(0) {}
bool NoSOName; bool NoSOName;
int Multiplicity;
std::string Location; std::string Location;
std::string SOName; std::string SOName;
std::string ImportLibrary; std::string ImportLibrary;
cmTarget::LinkInterface LinkInterface; std::string Languages;
std::string Libraries;
std::string LibrariesProp;
std::string SharedDeps;
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -90,11 +95,13 @@ public:
: Backtrace(NULL) : Backtrace(NULL)
{ {
this->PolicyWarnedCMP0022 = false; this->PolicyWarnedCMP0022 = false;
this->UtilityItemsDone = false;
} }
cmTargetInternals(cmTargetInternals const&) cmTargetInternals(cmTargetInternals const&)
: Backtrace(NULL) : Backtrace(NULL)
{ {
this->PolicyWarnedCMP0022 = false; this->PolicyWarnedCMP0022 = false;
this->UtilityItemsDone = false;
} }
~cmTargetInternals(); ~cmTargetInternals();
@ -121,11 +128,14 @@ public:
LinkInterfaceMapType LinkInterfaceMap; LinkInterfaceMapType LinkInterfaceMap;
bool PolicyWarnedCMP0022; bool PolicyWarnedCMP0022;
typedef std::map<TargetConfigPair, cmTarget::LinkInterface>
ImportLinkInterfaceMapType;
ImportLinkInterfaceMapType ImportLinkInterfaceMap;
typedef std::map<std::string, cmTarget::OutputInfo> OutputInfoMapType; typedef std::map<std::string, cmTarget::OutputInfo> OutputInfoMapType;
OutputInfoMapType OutputInfoMap; OutputInfoMapType OutputInfoMap;
typedef std::map<TargetConfigPair, cmTarget::ImportInfo> typedef std::map<std::string, cmTarget::ImportInfo> ImportInfoMapType;
ImportInfoMapType;
ImportInfoMapType ImportInfoMap; ImportInfoMapType ImportInfoMap;
typedef std::map<std::string, cmTarget::CompileInfo> CompileInfoMapType; typedef std::map<std::string, cmTarget::CompileInfo> CompileInfoMapType;
@ -136,14 +146,16 @@ public:
cmTarget::LinkImplementation> LinkImplMapType; cmTarget::LinkImplementation> LinkImplMapType;
LinkImplMapType LinkImplMap; LinkImplMapType LinkImplMap;
typedef std::map<TargetConfigPair, cmTarget::LinkClosure> typedef std::map<std::string, cmTarget::LinkClosure> LinkClosureMapType;
LinkClosureMapType;
LinkClosureMapType LinkClosureMap; LinkClosureMapType LinkClosureMap;
typedef std::map<TargetConfigPair, std::vector<cmSourceFile*> > typedef std::map<TargetConfigPair, std::vector<cmSourceFile*> >
SourceFilesMapType; SourceFilesMapType;
SourceFilesMapType SourceFilesMap; SourceFilesMapType SourceFilesMap;
std::set<cmLinkItem> UtilityItems;
bool UtilityItemsDone;
struct TargetPropertyEntry { struct TargetPropertyEntry {
TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
const std::string &targetName = std::string()) const std::string &targetName = std::string())
@ -170,12 +182,15 @@ public:
CachedLinkInterfaceSourcesEntries; CachedLinkInterfaceSourcesEntries;
mutable std::map<std::string, std::vector<TargetPropertyEntry*> > mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
CachedLinkInterfaceCompileFeaturesEntries; CachedLinkInterfaceCompileFeaturesEntries;
mutable std::map<std::string, std::vector<cmTarget const*> >
CachedLinkImplementationClosure;
mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone; mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone; mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone; mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
mutable std::map<std::string, bool> CacheLinkInterfaceSourcesDone; mutable std::map<std::string, bool> CacheLinkInterfaceSourcesDone;
mutable std::map<std::string, bool> CacheLinkInterfaceCompileFeaturesDone; mutable std::map<std::string, bool> CacheLinkInterfaceCompileFeaturesDone;
mutable std::map<std::string, bool> CacheLinkImplementationClosureDone;
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -460,6 +475,22 @@ cmListFileBacktrace const* cmTarget::GetUtilityBacktrace(
return &i->second; return &i->second;
} }
//----------------------------------------------------------------------------
std::set<cmLinkItem> const& cmTarget::GetUtilityItems() const
{
if(!this->Internal->UtilityItemsDone)
{
this->Internal->UtilityItemsDone = true;
for(std::set<std::string>::const_iterator i = this->Utilities.begin();
i != this->Utilities.end(); ++i)
{
this->Internal->UtilityItems.insert(
cmLinkItem(*i, this->Makefile->FindTargetToUse(*i)));
}
}
return this->Internal->UtilityItems;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::FinishConfigure() void cmTarget::FinishConfigure()
{ {
@ -479,6 +510,7 @@ void cmTarget::ClearLinkMaps()
this->LinkImplementationLanguageIsContextDependent = true; this->LinkImplementationLanguageIsContextDependent = true;
this->Internal->LinkImplMap.clear(); this->Internal->LinkImplMap.clear();
this->Internal->LinkInterfaceMap.clear(); this->Internal->LinkInterfaceMap.clear();
this->Internal->ImportLinkInterfaceMap.clear();
this->Internal->LinkClosureMap.clear(); this->Internal->LinkClosureMap.clear();
for (cmTargetLinkInformationMap::const_iterator it for (cmTargetLinkInformationMap::const_iterator it
= this->LinkInformation.begin(); = this->LinkInformation.begin();
@ -1194,63 +1226,6 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname) const
NameResolvesToFramework(libname); NameResolvesToFramework(libname);
} }
//----------------------------------------------------------------------------
void cmTarget::GetDirectLinkLibraries(const std::string& config,
std::vector<std::string> &libs,
cmTarget const* head) const
{
const char *prop = this->GetProperty("LINK_LIBRARIES");
if (prop)
{
cmGeneratorExpression ge;
const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(),
"LINK_LIBRARIES", 0, 0);
cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
config,
false,
head,
&dagChecker),
libs);
std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
for (std::set<std::string>::const_iterator it = seenProps.begin();
it != seenProps.end(); ++it)
{
if (!this->GetProperty(*it))
{
this->LinkImplicitNullProperties.insert(*it);
}
}
cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards);
}
}
//----------------------------------------------------------------------------
void cmTarget::GetInterfaceLinkLibraries(const std::string& config,
std::vector<std::string> &libs,
cmTarget const* head) const
{
const char *prop = this->GetProperty("INTERFACE_LINK_LIBRARIES");
if (prop)
{
cmGeneratorExpression ge;
const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(),
"INTERFACE_LINK_LIBRARIES", 0, 0);
cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
config,
false,
head,
&dagChecker),
libs);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value, std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value,
cmTarget::LinkLibraryType llt) const cmTarget::LinkLibraryType llt) const
@ -2294,9 +2269,8 @@ cmTarget::GetIncludeDirectories(const std::string& config) const
if(this->Makefile->IsOn("APPLE")) if(this->Makefile->IsOn("APPLE"))
{ {
LinkImplementation const* impl = this->GetLinkImplementation(config, LinkImplementation const* impl = this->GetLinkImplementation(config);
this); for(std::vector<cmLinkItem>::const_iterator
for(std::vector<std::string>::const_iterator
it = impl->Libraries.begin(); it = impl->Libraries.begin();
it != impl->Libraries.end(); ++it) it != impl->Libraries.end(); ++it)
{ {
@ -3498,13 +3472,11 @@ public:
Makefile(target->GetMakefile()), Target(target) Makefile(target->GetMakefile()), Target(target)
{ this->Visited.insert(target); } { this->Visited.insert(target); }
void Visit(const std::string& name) void Visit(cmLinkItem const& item)
{ {
cmTarget *target = this->Makefile->FindTargetToUse(name); if(!item.Target)
if(!target)
{ {
if(name.find("::") != std::string::npos) if(item.find("::") != std::string::npos)
{ {
bool noMessage = false; bool noMessage = false;
cmake::MessageType messageType = cmake::FATAL_ERROR; cmake::MessageType messageType = cmake::FATAL_ERROR;
@ -3530,7 +3502,7 @@ public:
if(!noMessage) if(!noMessage)
{ {
e << "Target \"" << this->Target->GetName() e << "Target \"" << this->Target->GetName()
<< "\" links to target \"" << name << "\" links to target \"" << item
<< "\" but the target was not found. Perhaps a find_package() " << "\" but the target was not found. Perhaps a find_package() "
"call is missing for an IMPORTED target, or an ALIAS target is " "call is missing for an IMPORTED target, or an ALIAS target is "
"missing?"; "missing?";
@ -3541,13 +3513,13 @@ public:
} }
return; return;
} }
if(!this->Visited.insert(target).second) if(!this->Visited.insert(item.Target).second)
{ {
return; return;
} }
cmTarget::LinkInterface const* iface = cmTarget::LinkInterface const* iface =
target->GetLinkInterface(this->Config, this->HeadTarget); item.Target->GetLinkInterface(this->Config, this->HeadTarget);
if(!iface) { return; } if(!iface) { return; }
for(std::vector<std::string>::const_iterator for(std::vector<std::string>::const_iterator
@ -3556,7 +3528,7 @@ public:
this->Languages.insert(*li); this->Languages.insert(*li);
} }
for(std::vector<std::string>::const_iterator for(std::vector<cmLinkItem>::const_iterator
li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li) li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li)
{ {
this->Visit(*li); this->Visit(*li);
@ -3572,25 +3544,22 @@ private:
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::GetLinkerLanguage(const std::string& config, std::string cmTarget::GetLinkerLanguage(const std::string& config) const
cmTarget const* head) const
{ {
cmTarget const* headTarget = head ? head : this; return this->GetLinkClosure(config)->LinkerLanguage;
return this->GetLinkClosure(config, headTarget)->LinkerLanguage;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmTarget::LinkClosure const* cmTarget::GetLinkClosure( cmTarget::LinkClosure const*
const std::string& config, cmTarget::GetLinkClosure(const std::string& config) const
cmTarget const* head) const
{ {
TargetConfigPair key(head, cmSystemTools::UpperCase(config)); std::string key(cmSystemTools::UpperCase(config));
cmTargetInternals::LinkClosureMapType::iterator cmTargetInternals::LinkClosureMapType::iterator
i = this->Internal->LinkClosureMap.find(key); i = this->Internal->LinkClosureMap.find(key);
if(i == this->Internal->LinkClosureMap.end()) if(i == this->Internal->LinkClosureMap.end())
{ {
LinkClosure lc; LinkClosure lc;
this->ComputeLinkClosure(config, lc, head); this->ComputeLinkClosure(config, lc);
cmTargetInternals::LinkClosureMapType::value_type entry(key, lc); cmTargetInternals::LinkClosureMapType::value_type entry(key, lc);
i = this->Internal->LinkClosureMap.insert(entry).first; i = this->Internal->LinkClosureMap.insert(entry).first;
} }
@ -3651,12 +3620,12 @@ public:
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::ComputeLinkClosure(const std::string& config, LinkClosure& lc, void cmTarget::ComputeLinkClosure(const std::string& config,
cmTarget const* head) const LinkClosure& lc) const
{ {
// Get languages built in this target. // Get languages built in this target.
std::set<std::string> languages; std::set<std::string> languages;
LinkImplementation const* impl = this->GetLinkImplementation(config, head); LinkImplementation const* impl = this->GetLinkImplementation(config);
for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
li != impl->Languages.end(); ++li) li != impl->Languages.end(); ++li)
{ {
@ -3664,8 +3633,8 @@ void cmTarget::ComputeLinkClosure(const std::string& config, LinkClosure& lc,
} }
// Add interface languages from linked targets. // Add interface languages from linked targets.
cmTargetCollectLinkLanguages cll(this, config, languages, head); cmTargetCollectLinkLanguages cll(this, config, languages, this);
for(std::vector<std::string>::const_iterator li = impl->Libraries.begin(); for(std::vector<cmLinkItem>::const_iterator li = impl->Libraries.begin();
li != impl->Libraries.end(); ++li) li != impl->Libraries.end(); ++li)
{ {
cll.Visit(*li); cll.Visit(*li);
@ -3714,6 +3683,41 @@ void cmTarget::ComputeLinkClosure(const std::string& config, LinkClosure& lc,
} }
} }
//----------------------------------------------------------------------------
void cmTarget::ExpandLinkItems(std::string const& prop,
std::string const& value,
std::string const& config,
cmTarget const* headTarget,
std::vector<cmLinkItem>& items) const
{
cmGeneratorExpression ge;
cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, 0, 0);
std::vector<std::string> libs;
cmSystemTools::ExpandListArgument(ge.Parse(value)->Evaluate(
this->Makefile,
config,
false,
headTarget,
this, &dagChecker), libs);
this->LookupLinkItems(libs, items);
}
//----------------------------------------------------------------------------
void cmTarget::LookupLinkItems(std::vector<std::string> const& names,
std::vector<cmLinkItem>& items) const
{
for(std::vector<std::string>::const_iterator i = names.begin();
i != names.end(); ++i)
{
std::string name = this->CheckCMP0004(*i);
if(name == this->GetName() || name.empty())
{
continue;
}
items.push_back(cmLinkItem(name, this->FindTargetToLink(name)));
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char* cmTarget::GetSuffixVariableInternal(bool implib) const const char* cmTarget::GetSuffixVariableInternal(bool implib) const
{ {
@ -3845,8 +3849,7 @@ bool cmTarget::HasSOName(const std::string& config) const
return ((this->GetType() == cmTarget::SHARED_LIBRARY || return ((this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY) && this->GetType() == cmTarget::MODULE_LIBRARY) &&
!this->GetPropertyAsBool("NO_SONAME") && !this->GetPropertyAsBool("NO_SONAME") &&
this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config, this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config)));
this)));
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -3855,7 +3858,7 @@ std::string cmTarget::GetSOName(const std::string& config) const
if(this->IsImported()) if(this->IsImported())
{ {
// Lookup the imported soname. // Lookup the imported soname.
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
{ {
if(info->NoSOName) if(info->NoSOName)
{ {
@ -3923,7 +3926,7 @@ bool cmTarget::HasMacOSXRpathInstallNameDir(const std::string& config) const
else else
{ {
// Lookup the imported soname. // Lookup the imported soname.
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
{ {
if(!info->NoSOName && !info->SOName.empty()) if(!info->NoSOName && !info->SOName.empty())
{ {
@ -4009,7 +4012,7 @@ bool cmTarget::IsImportedSharedLibWithoutSOName(
{ {
if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY) if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY)
{ {
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
{ {
return info->NoSOName; return info->NoSOName;
} }
@ -4133,7 +4136,7 @@ std::string
cmTarget::ImportedGetFullPath(const std::string& config, bool implib) const cmTarget::ImportedGetFullPath(const std::string& config, bool implib) const
{ {
std::string result; std::string result;
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
{ {
result = implib? info->ImportLibrary : info->Location; result = implib? info->ImportLibrary : info->Location;
} }
@ -4219,7 +4222,7 @@ void cmTarget::GetFullNameInternal(const std::string& config,
const char* suffixVar = this->GetSuffixVariableInternal(implib); const char* suffixVar = this->GetSuffixVariableInternal(implib);
// Check for language-specific default prefix and suffix. // Check for language-specific default prefix and suffix.
std::string ll = this->GetLinkerLanguage(config, this); std::string ll = this->GetLinkerLanguage(config);
if(!ll.empty()) if(!ll.empty())
{ {
if(!targetSuffix && suffixVar && *suffixVar) if(!targetSuffix && suffixVar && *suffixVar)
@ -4507,9 +4510,12 @@ bool cmTarget::HaveBuildTreeRPATH(const std::string& config) const
{ {
return false; return false;
} }
std::vector<std::string> libs; if(LinkImplementation const* impl =
this->GetDirectLinkLibraries(config, libs, this); this->GetLinkImplementationLibraries(config))
return !libs.empty(); {
return !impl->Libraries.empty();
}
return false;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -4558,7 +4564,7 @@ bool cmTarget::NeedRelinkBeforeInstall(const std::string& config) const
} }
// Check for rpath support on this platform. // Check for rpath support on this platform.
std::string ll = this->GetLinkerLanguage(config, this); std::string ll = this->GetLinkerLanguage(config);
if(!ll.empty()) if(!ll.empty())
{ {
std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
@ -5212,8 +5218,8 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
assert((impliedByUse ^ explicitlySet) assert((impliedByUse ^ explicitlySet)
|| (!impliedByUse && !explicitlySet)); || (!impliedByUse && !explicitlySet));
std::vector<cmTarget*> deps; std::vector<cmTarget const*> const& deps =
tgt->GetTransitiveTargetClosure(config, tgt, deps); tgt->GetLinkImplementationClosure(config);
if(deps.empty()) if(deps.empty())
{ {
@ -5238,7 +5244,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
report += "\" property not set.\n"; report += "\" property not set.\n";
} }
for(std::vector<cmTarget*>::const_iterator li = for(std::vector<cmTarget const*>::const_iterator li =
deps.begin(); deps.begin();
li != deps.end(); ++li) li != deps.end(); ++li)
{ {
@ -5428,16 +5434,15 @@ bool isLinkDependentProperty(cmTarget const* tgt, const std::string &p,
const std::string& interfaceProperty, const std::string& interfaceProperty,
const std::string& config) const std::string& config)
{ {
std::vector<cmTarget*> deps; std::vector<cmTarget const*> const& deps =
tgt->GetTransitiveTargetClosure(config, tgt, deps); tgt->GetLinkImplementationClosure(config);
if(deps.empty()) if(deps.empty())
{ {
return false; return false;
} }
for(std::vector<cmTarget*>::const_iterator li = for(std::vector<cmTarget const*>::const_iterator li = deps.begin();
deps.begin();
li != deps.end(); ++li) li != deps.end(); ++li)
{ {
const char *prop = (*li)->GetProperty(interfaceProperty); const char *prop = (*li)->GetProperty(interfaceProperty);
@ -5647,7 +5652,7 @@ bool cmTarget::IsChrpathUsed(const std::string& config) const
#if defined(CMAKE_USE_ELF_PARSER) #if defined(CMAKE_USE_ELF_PARSER)
// Enable if the rpath flag uses a separator and the target uses ELF // Enable if the rpath flag uses a separator and the target uses ELF
// binaries. // binaries.
std::string ll = this->GetLinkerLanguage(config, this); std::string ll = this->GetLinkerLanguage(config);
if(!ll.empty()) if(!ll.empty())
{ {
std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
@ -5672,8 +5677,7 @@ bool cmTarget::IsChrpathUsed(const std::string& config) const
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmTarget::ImportInfo const* cmTarget::ImportInfo const*
cmTarget::GetImportInfo(const std::string& config, cmTarget::GetImportInfo(const std::string& config) const
cmTarget const* headTarget) const
{ {
// There is no imported information for non-imported targets. // There is no imported information for non-imported targets.
if(!this->IsImported()) if(!this->IsImported())
@ -5692,16 +5696,15 @@ cmTarget::GetImportInfo(const std::string& config,
{ {
config_upper = "NOCONFIG"; config_upper = "NOCONFIG";
} }
TargetConfigPair key(headTarget, config_upper);
typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType; typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType;
ImportInfoMapType::const_iterator i = ImportInfoMapType::const_iterator i =
this->Internal->ImportInfoMap.find(key); this->Internal->ImportInfoMap.find(config_upper);
if(i == this->Internal->ImportInfoMap.end()) if(i == this->Internal->ImportInfoMap.end())
{ {
ImportInfo info; ImportInfo info;
this->ComputeImportInfo(config_upper, info, headTarget); this->ComputeImportInfo(config_upper, info);
ImportInfoMapType::value_type entry(key, info); ImportInfoMapType::value_type entry(config_upper, info);
i = this->Internal->ImportInfoMap.insert(entry).first; i = this->Internal->ImportInfoMap.insert(entry).first;
} }
@ -5853,8 +5856,7 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::ComputeImportInfo(std::string const& desired_config, void cmTarget::ComputeImportInfo(std::string const& desired_config,
ImportInfo& info, ImportInfo& info) const
cmTarget const* headTarget) const
{ {
// This method finds information about an imported target from its // This method finds information about an imported target from its
// properties. The "IMPORTED_" namespace is reserved for properties // properties. The "IMPORTED_" namespace is reserved for properties
@ -5893,19 +5895,8 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
} }
if(propertyLibs) if(propertyLibs)
{ {
cmGeneratorExpression ge; info.LibrariesProp = linkProp;
info.Libraries = propertyLibs;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(),
linkProp, 0, 0);
cmSystemTools::ExpandListArgument(ge.Parse(propertyLibs)
->Evaluate(this->Makefile,
desired_config,
false,
headTarget,
this,
&dagChecker),
info.LinkInterface.Libraries);
} }
} }
if(this->GetType() == INTERFACE_LIBRARY) if(this->GetType() == INTERFACE_LIBRARY)
@ -5991,13 +5982,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
linkProp += suffix; linkProp += suffix;
if(const char* config_libs = this->GetProperty(linkProp)) if(const char* config_libs = this->GetProperty(linkProp))
{ {
cmSystemTools::ExpandListArgument(config_libs, info.SharedDeps = config_libs;
info.LinkInterface.SharedDeps);
} }
else if(const char* libs = else if(const char* libs =
this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES")) this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES"))
{ {
cmSystemTools::ExpandListArgument(libs, info.LinkInterface.SharedDeps); info.SharedDeps = libs;
} }
} }
@ -6008,14 +5998,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
linkProp += suffix; linkProp += suffix;
if(const char* config_libs = this->GetProperty(linkProp)) if(const char* config_libs = this->GetProperty(linkProp))
{ {
cmSystemTools::ExpandListArgument(config_libs, info.Languages = config_libs;
info.LinkInterface.Languages);
} }
else if(const char* libs = else if(const char* libs =
this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES")) this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES"))
{ {
cmSystemTools::ExpandListArgument(libs, info.Languages = libs;
info.LinkInterface.Languages);
} }
} }
@ -6026,12 +6014,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
linkProp += suffix; linkProp += suffix;
if(const char* config_reps = this->GetProperty(linkProp)) if(const char* config_reps = this->GetProperty(linkProp))
{ {
sscanf(config_reps, "%u", &info.LinkInterface.Multiplicity); sscanf(config_reps, "%u", &info.Multiplicity);
} }
else if(const char* reps = else if(const char* reps =
this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY")) this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY"))
{ {
sscanf(reps, "%u", &info.LinkInterface.Multiplicity); sscanf(reps, "%u", &info.Multiplicity);
} }
} }
} }
@ -6044,11 +6032,7 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(
// Imported targets have their own link interface. // Imported targets have their own link interface.
if(this->IsImported()) if(this->IsImported())
{ {
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head)) return this->GetImportLinkInterface(config, head);
{
return &info->LinkInterface;
}
return 0;
} }
// Link interfaces are not supported for executables that do not // Link interfaces are not supported for executables that do not
@ -6097,11 +6081,7 @@ cmTarget::GetLinkInterfaceLibraries(const std::string& config,
// Imported targets have their own link interface. // Imported targets have their own link interface.
if(this->IsImported()) if(this->IsImported())
{ {
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head)) return this->GetImportLinkInterface(config, head);
{
return &info->LinkInterface;
}
return 0;
} }
// Link interfaces are not supported for executables that do not // Link interfaces are not supported for executables that do not
@ -6134,23 +6114,55 @@ cmTarget::GetLinkInterfaceLibraries(const std::string& config,
return i->second.Exists ? &i->second : 0; return i->second.Exists ? &i->second : 0;
} }
//----------------------------------------------------------------------------
cmTarget::LinkInterface const*
cmTarget::GetImportLinkInterface(const std::string& config,
cmTarget const* headTarget) const
{
cmTarget::ImportInfo const* info = this->GetImportInfo(config);
if(!info)
{
return 0;
}
TargetConfigPair key(headTarget, cmSystemTools::UpperCase(config));
cmTargetInternals::ImportLinkInterfaceMapType::iterator i =
this->Internal->ImportLinkInterfaceMap.find(key);
if(i == this->Internal->ImportLinkInterfaceMap.end())
{
LinkInterface iface;
iface.Multiplicity = info->Multiplicity;
cmSystemTools::ExpandListArgument(info->Languages, iface.Languages);
this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
headTarget, iface.Libraries);
{
std::vector<std::string> deps;
cmSystemTools::ExpandListArgument(info->SharedDeps, deps);
this->LookupLinkItems(deps, iface.SharedDeps);
}
cmTargetInternals::ImportLinkInterfaceMapType::value_type
entry(key, iface);
i = this->Internal->ImportLinkInterfaceMap.insert(entry).first;
}
return &i->second;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void processILibs(const std::string& config, void processILibs(const std::string& config,
cmTarget const* headTarget, cmTarget const* headTarget,
std::string const& name, cmLinkItem const& item,
std::vector<cmTarget*>& tgts, std::set<cmTarget*>& emitted) std::vector<cmTarget const*>& tgts,
std::set<cmTarget const*>& emitted)
{ {
if (cmTarget* tgt = headTarget->GetMakefile() if (item.Target && emitted.insert(item.Target).second)
->FindTargetToUse(name))
{ {
if (emitted.insert(tgt).second) tgts.push_back(item.Target);
if(cmTarget::LinkInterface const* iface =
item.Target->GetLinkInterfaceLibraries(config, headTarget))
{ {
tgts.push_back(tgt); for(std::vector<cmLinkItem>::const_iterator
cmTarget::LinkInterface const* iface =
tgt->GetLinkInterfaceLibraries(config, headTarget);
if (iface)
{
for(std::vector<std::string>::const_iterator
it = iface->Libraries.begin(); it = iface->Libraries.begin();
it != iface->Libraries.end(); ++it) it != iface->Libraries.end(); ++it)
{ {
@ -6158,30 +6170,35 @@ void processILibs(const std::string& config,
} }
} }
} }
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::GetTransitiveTargetClosure(const std::string& config, std::vector<cmTarget const*> const&
cmTarget const* headTarget, cmTarget::GetLinkImplementationClosure(const std::string& config) const
std::vector<cmTarget*> &tgts) const
{ {
std::set<cmTarget*> emitted; std::vector<cmTarget const*>& tgts =
this->Internal->CachedLinkImplementationClosure[config];
if(!this->Internal->CacheLinkImplementationClosureDone[config])
{
this->Internal->CacheLinkImplementationClosureDone[config] = true;
std::set<cmTarget const*> emitted;
cmTarget::LinkImplementation const* impl cmTarget::LinkImplementation const* impl
= this->GetLinkImplementationLibraries(config, headTarget); = this->GetLinkImplementationLibraries(config);
for(std::vector<std::string>::const_iterator it = impl->Libraries.begin(); for(std::vector<cmLinkItem>::const_iterator it = impl->Libraries.begin();
it != impl->Libraries.end(); ++it) it != impl->Libraries.end(); ++it)
{ {
processILibs(config, headTarget, *it, tgts, emitted); processILibs(config, this, *it, tgts , emitted);
} }
}
return tgts;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::GetTransitivePropertyTargets(const std::string& config, void cmTarget::GetTransitivePropertyTargets(const std::string& config,
cmTarget const* headTarget, cmTarget const* headTarget,
std::vector<cmTarget*> &tgts) const std::vector<cmTarget const*> &tgts) const
{ {
cmTarget::LinkInterface const* iface cmTarget::LinkInterface const* iface
= this->GetLinkInterfaceLibraries(config, headTarget); = this->GetLinkInterfaceLibraries(config, headTarget);
@ -6193,13 +6210,12 @@ void cmTarget::GetTransitivePropertyTargets(const std::string& config,
|| this->GetPolicyStatusCMP0022() == cmPolicies::WARN || this->GetPolicyStatusCMP0022() == cmPolicies::WARN
|| this->GetPolicyStatusCMP0022() == cmPolicies::OLD) || this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
{ {
for(std::vector<std::string>::const_iterator it = iface->Libraries.begin(); for(std::vector<cmLinkItem>::const_iterator it = iface->Libraries.begin();
it != iface->Libraries.end(); ++it) it != iface->Libraries.end(); ++it)
{ {
if (cmTarget* tgt = headTarget->GetMakefile() if (it->Target)
->FindTargetToUse(*it))
{ {
tgts.push_back(tgt); tgts.push_back(it->Target);
} }
} }
return; return;
@ -6229,8 +6245,7 @@ void cmTarget::GetTransitivePropertyTargets(const std::string& config,
for(std::vector<std::string>::const_iterator it = libs.begin(); for(std::vector<std::string>::const_iterator it = libs.begin();
it != libs.end(); ++it) it != libs.end(); ++it)
{ {
if (cmTarget* tgt = headTarget->GetMakefile() if (cmTarget const* tgt = this->FindTargetToLink(*it))
->FindTargetToUse(*it))
{ {
tgts.push_back(tgt); tgts.push_back(tgt);
} }
@ -6325,15 +6340,8 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config,
if(explicitLibraries) if(explicitLibraries)
{ {
// The interface libraries have been explicitly set. // The interface libraries have been explicitly set.
cmGeneratorExpression ge; this->ExpandLinkItems(linkIfaceProp, explicitLibraries, config,
cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), headTarget, iface.Libraries);
linkIfaceProp, 0, 0);
cmSystemTools::ExpandListArgument(ge.Parse(explicitLibraries)->Evaluate(
this->Makefile,
config,
false,
headTarget,
this, &dagChecker), iface.Libraries);
} }
else if (this->PolicyStatusCMP0022 == cmPolicies::WARN else if (this->PolicyStatusCMP0022 == cmPolicies::WARN
|| this->PolicyStatusCMP0022 == cmPolicies::OLD) || this->PolicyStatusCMP0022 == cmPolicies::OLD)
@ -6344,32 +6352,26 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config,
{ {
// The link implementation is the default link interface. // The link implementation is the default link interface.
LinkImplementation const* impl = LinkImplementation const* impl =
this->GetLinkImplementationLibraries(config, headTarget); this->GetLinkImplementationLibrariesInternal(config, headTarget);
iface.Libraries = impl->Libraries; iface.Libraries = impl->Libraries;
if(this->PolicyStatusCMP0022 == cmPolicies::WARN && if(this->PolicyStatusCMP0022 == cmPolicies::WARN &&
!this->Internal->PolicyWarnedCMP0022) !this->Internal->PolicyWarnedCMP0022)
{ {
// Compare the link implementation fallback link interface to the // Compare the link implementation fallback link interface to the
// preferred new link interface property and warn if different. // preferred new link interface property and warn if different.
cmGeneratorExpression ge; std::vector<cmLinkItem> ifaceLibs;
cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), std::string newProp = "INTERFACE_LINK_LIBRARIES";
"INTERFACE_LINK_LIBRARIES", 0, 0); if(const char* newExplicitLibraries = this->GetProperty(newProp))
std::vector<std::string> ifaceLibs; {
const char* newExplicitLibraries = this->ExpandLinkItems(newProp, newExplicitLibraries, config,
this->GetProperty("INTERFACE_LINK_LIBRARIES"); headTarget, ifaceLibs);
cmSystemTools::ExpandListArgument( }
ge.Parse(newExplicitLibraries)->Evaluate(this->Makefile,
config,
false,
headTarget,
this, &dagChecker),
ifaceLibs);
if (ifaceLibs != impl->Libraries) if (ifaceLibs != impl->Libraries)
{ {
std::string oldLibraries; std::string oldLibraries;
std::string newLibraries; std::string newLibraries;
const char *sep = ""; const char *sep = "";
for(std::vector<std::string>::const_iterator it for(std::vector<cmLinkItem>::const_iterator it
= impl->Libraries.begin(); it != impl->Libraries.end(); ++it) = impl->Libraries.begin(); it != impl->Libraries.end(); ++it)
{ {
oldLibraries += sep; oldLibraries += sep;
@ -6377,7 +6379,7 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config,
sep = ";"; sep = ";";
} }
sep = ""; sep = "";
for(std::vector<std::string>::const_iterator it for(std::vector<cmLinkItem>::const_iterator it
= ifaceLibs.begin(); it != ifaceLibs.end(); ++it) = ifaceLibs.begin(); it != ifaceLibs.end(); ++it)
{ {
newLibraries += sep; newLibraries += sep;
@ -6428,7 +6430,7 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget,
// Shared libraries may have runtime implementation dependencies // Shared libraries may have runtime implementation dependencies
// on other shared libraries that are not in the interface. // on other shared libraries that are not in the interface.
std::set<std::string> emitted; std::set<std::string> emitted;
for(std::vector<std::string>::const_iterator for(std::vector<cmLinkItem>::const_iterator
li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li) li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li)
{ {
emitted.insert(*li); emitted.insert(*li);
@ -6436,16 +6438,16 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget,
if (thisTarget->GetType() != cmTarget::INTERFACE_LIBRARY) if (thisTarget->GetType() != cmTarget::INTERFACE_LIBRARY)
{ {
cmTarget::LinkImplementation const* impl = cmTarget::LinkImplementation const* impl =
thisTarget->GetLinkImplementation(config, headTarget); thisTarget->GetLinkImplementation(config);
for(std::vector<std::string>::const_iterator for(std::vector<cmLinkItem>::const_iterator
li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
{ {
if(emitted.insert(*li).second) if(emitted.insert(*li).second)
{ {
if(cmTarget* tgt = thisTarget->Makefile->FindTargetToUse(*li)) if(li->Target)
{ {
// This is a runtime dependency on another shared library. // This is a runtime dependency on another shared library.
if(tgt->GetType() == cmTarget::SHARED_LIBRARY) if(li->Target->GetType() == cmTarget::SHARED_LIBRARY)
{ {
iface.SharedDeps.push_back(*li); iface.SharedDeps.push_back(*li);
} }
@ -6467,7 +6469,8 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget,
{ {
// The link implementation is the default link interface. // The link implementation is the default link interface.
cmTarget::LinkImplementation const* cmTarget::LinkImplementation const*
impl = thisTarget->GetLinkImplementation(config, headTarget); impl = thisTarget->GetLinkImplementationLibrariesInternal(config,
headTarget);
iface.ImplementationIsInterface = true; iface.ImplementationIsInterface = true;
iface.WrongConfigLibraries = impl->WrongConfigLibraries; iface.WrongConfigLibraries = impl->WrongConfigLibraries;
} }
@ -6476,7 +6479,7 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget,
{ {
// Targets using this archive need its language runtime libraries. // Targets using this archive need its language runtime libraries.
if(cmTarget::LinkImplementation const* impl = if(cmTarget::LinkImplementation const* impl =
thisTarget->GetLinkImplementation(config, headTarget)) thisTarget->GetLinkImplementation(config))
{ {
iface.Languages = impl->Languages; iface.Languages = impl->Languages;
} }
@ -6514,8 +6517,7 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmTarget::LinkImplementation const* cmTarget::LinkImplementation const*
cmTarget::GetLinkImplementation(const std::string& config, cmTarget::GetLinkImplementation(const std::string& config) const
cmTarget const* head) const
{ {
// There is no link implementation for imported targets. // There is no link implementation for imported targets.
if(this->IsImported()) if(this->IsImported())
@ -6524,7 +6526,7 @@ cmTarget::GetLinkImplementation(const std::string& config,
} }
// Lookup any existing link implementation for this configuration. // Lookup any existing link implementation for this configuration.
TargetConfigPair key(head, cmSystemTools::UpperCase(config)); TargetConfigPair key(this, cmSystemTools::UpperCase(config));
cmTargetInternals::LinkImplMapType::iterator cmTargetInternals::LinkImplMapType::iterator
i = this->Internal->LinkImplMap.find(key); i = this->Internal->LinkImplMap.find(key);
@ -6532,8 +6534,8 @@ cmTarget::GetLinkImplementation(const std::string& config,
{ {
// Compute the link implementation for this configuration. // Compute the link implementation for this configuration.
LinkImplementation impl; LinkImplementation impl;
this->ComputeLinkImplementation(config, impl, head); this->ComputeLinkImplementation(config, impl, this);
this->ComputeLinkImplementationLanguages(config, impl, head); this->ComputeLinkImplementationLanguages(config, impl, this);
// Store the information for this configuration. // Store the information for this configuration.
cmTargetInternals::LinkImplMapType::value_type entry(key, impl); cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
@ -6541,7 +6543,7 @@ cmTarget::GetLinkImplementation(const std::string& config,
} }
else if (i->second.Languages.empty()) else if (i->second.Languages.empty())
{ {
this->ComputeLinkImplementationLanguages(config, i->second, head); this->ComputeLinkImplementationLanguages(config, i->second, this);
} }
return &i->second; return &i->second;
@ -6549,7 +6551,14 @@ cmTarget::GetLinkImplementation(const std::string& config,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmTarget::LinkImplementation const* cmTarget::LinkImplementation const*
cmTarget::GetLinkImplementationLibraries(const std::string& config, cmTarget::GetLinkImplementationLibraries(const std::string& config) const
{
return this->GetLinkImplementationLibrariesInternal(config, this);
}
//----------------------------------------------------------------------------
cmTarget::LinkImplementation const*
cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config,
cmTarget const* head) const cmTarget const* head) const
{ {
// There is no link implementation for imported targets. // There is no link implementation for imported targets.
@ -6584,15 +6593,41 @@ void cmTarget::ComputeLinkImplementation(const std::string& config,
{ {
// Collect libraries directly linked in this configuration. // Collect libraries directly linked in this configuration.
std::vector<std::string> llibs; std::vector<std::string> llibs;
this->GetDirectLinkLibraries(config, llibs, head); if(const char *prop = this->GetProperty("LINK_LIBRARIES"))
{
cmGeneratorExpression ge;
const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(),
"LINK_LIBRARIES", 0, 0);
cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
config,
false,
head,
&dagChecker),
llibs);
std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
for (std::set<std::string>::const_iterator it = seenProps.begin();
it != seenProps.end(); ++it)
{
if (!this->GetProperty(*it))
{
this->LinkImplicitNullProperties.insert(*it);
}
}
cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards);
}
for(std::vector<std::string>::const_iterator li = llibs.begin(); for(std::vector<std::string>::const_iterator li = llibs.begin();
li != llibs.end(); ++li) li != llibs.end(); ++li)
{ {
// Skip entries that resolve to the target itself or are empty. // Skip entries that resolve to the target itself or are empty.
std::string item = this->CheckCMP0004(*li); std::string name = this->CheckCMP0004(*li);
if(item == this->GetName() || item.empty()) if(name == this->GetName() || name.empty())
{ {
if(item == this->GetName()) if(name == this->GetName())
{ {
bool noMessage = false; bool noMessage = false;
cmake::MessageType messageType = cmake::FATAL_ERROR; cmake::MessageType messageType = cmake::FATAL_ERROR;
@ -6631,7 +6666,8 @@ void cmTarget::ComputeLinkImplementation(const std::string& config,
} }
// The entry is meant for this configuration. // The entry is meant for this configuration.
impl.Libraries.push_back(item); impl.Libraries.push_back(
cmLinkItem(name, this->FindTargetToLink(name)));
} }
cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
@ -6641,13 +6677,14 @@ void cmTarget::ComputeLinkImplementation(const std::string& config,
{ {
if(li->second != cmTarget::GENERAL && li->second != linkType) if(li->second != cmTarget::GENERAL && li->second != linkType)
{ {
std::string item = this->CheckCMP0004(li->first); std::string name = this->CheckCMP0004(li->first);
if(item == this->GetName() || item.empty()) if(name == this->GetName() || name.empty())
{ {
continue; continue;
} }
// Support OLD behavior for CMP0003. // Support OLD behavior for CMP0003.
impl.WrongConfigLibraries.push_back(item); impl.WrongConfigLibraries.push_back(
cmLinkItem(name, this->FindTargetToLink(name)));
} }
} }
} }
@ -6670,6 +6707,37 @@ cmTarget::ComputeLinkImplementationLanguages(const std::string& config,
} }
} }
//----------------------------------------------------------------------------
cmTarget const* cmTarget::FindTargetToLink(std::string const& name) const
{
cmTarget const* tgt = this->Makefile->FindTargetToUse(name);
// Skip targets that will not really be linked. This is probably a
// name conflict between an external library and an executable
// within the project.
if(tgt && tgt->GetType() == cmTarget::EXECUTABLE &&
!tgt->IsExecutableWithExports())
{
tgt = 0;
}
if(tgt && tgt->GetType() == cmTarget::OBJECT_LIBRARY)
{
cmOStringStream e;
e << "Target \"" << this->GetName() << "\" links to "
"OBJECT library \"" << tgt->GetName() << "\" but this is not "
"allowed. "
"One may link only to STATIC or SHARED libraries, or to executables "
"with the ENABLE_EXPORTS property set.";
cmake* cm = this->Makefile->GetCMakeInstance();
cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
tgt = 0;
}
// Return the target found, if any.
return tgt;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::CheckCMP0004(std::string const& item) const std::string cmTarget::CheckCMP0004(std::string const& item) const
{ {
@ -6967,19 +7035,17 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmComputeLinkInformation* cmComputeLinkInformation*
cmTarget::GetLinkInformation(const std::string& config, cmTarget::GetLinkInformation(const std::string& config) const
cmTarget const* head) const
{ {
cmTarget const* headTarget = head ? head : this;
// Lookup any existing information for this configuration. // Lookup any existing information for this configuration.
TargetConfigPair key(headTarget, cmSystemTools::UpperCase(config)); std::string key(cmSystemTools::UpperCase(config));
cmTargetLinkInformationMap::iterator cmTargetLinkInformationMap::iterator
i = this->LinkInformation.find(key); i = this->LinkInformation.find(key);
if(i == this->LinkInformation.end()) if(i == this->LinkInformation.end())
{ {
// Compute information for this configuration. // Compute information for this configuration.
cmComputeLinkInformation* info = cmComputeLinkInformation* info =
new cmComputeLinkInformation(this, config, headTarget); new cmComputeLinkInformation(this, config);
if(!info || !info->Compute()) if(!info || !info->Compute())
{ {
delete info; delete info;

View File

@ -43,12 +43,22 @@ class cmTarget;
class cmGeneratorTarget; class cmGeneratorTarget;
class cmTargetTraceDependencies; class cmTargetTraceDependencies;
struct cmTargetLinkInformationMap: // Basic information about each link item.
public std::map<std::pair<cmTarget const* , std::string>, class cmLinkItem: public std::string
cmComputeLinkInformation*>
{ {
typedef std::map<std::pair<cmTarget const* , std::string>, typedef std::string std_string;
cmComputeLinkInformation*> derived; public:
cmLinkItem(): std_string(), Target(0) {}
cmLinkItem(const std_string& n,
cmTarget const* t): std_string(n), Target(t) {}
cmLinkItem(cmLinkItem const& r): std_string(r), Target(r.Target) {}
cmTarget const* Target;
};
struct cmTargetLinkInformationMap:
public std::map<std::string, cmComputeLinkInformation*>
{
typedef std::map<std::string, cmComputeLinkInformation*> derived;
cmTargetLinkInformationMap() {} cmTargetLinkInformationMap() {}
cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r); cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r);
~cmTargetLinkInformationMap(); ~cmTargetLinkInformationMap();
@ -159,12 +169,6 @@ public:
return this->LinkLibraries;} return this->LinkLibraries;}
const LinkLibraryVectorType &GetOriginalLinkLibraries() const const LinkLibraryVectorType &GetOriginalLinkLibraries() const
{return this->OriginalLinkLibraries;} {return this->OriginalLinkLibraries;}
void GetDirectLinkLibraries(const std::string& config,
std::vector<std::string> &,
cmTarget const* head) const;
void GetInterfaceLinkLibraries(const std::string& config,
std::vector<std::string> &,
cmTarget const* head) const;
/** Compute the link type to use for the given configuration. */ /** Compute the link type to use for the given configuration. */
LinkLibraryType ComputeLinkType(const std::string& config) const; LinkLibraryType ComputeLinkType(const std::string& config) const;
@ -221,6 +225,7 @@ public:
void AddUtility(const std::string& u, cmMakefile *makefile = 0); void AddUtility(const std::string& u, cmMakefile *makefile = 0);
///! Get the utilities used by this target ///! Get the utilities used by this target
std::set<std::string>const& GetUtilities() const { return this->Utilities; } std::set<std::string>const& GetUtilities() const { return this->Utilities; }
std::set<cmLinkItem>const& GetUtilityItems() const;
cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const; cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const;
/** Finalize the target at the end of the Configure step. */ /** Finalize the target at the end of the Configure step. */
@ -252,10 +257,10 @@ public:
std::vector<std::string> Languages; std::vector<std::string> Languages;
// Libraries listed in the interface. // Libraries listed in the interface.
std::vector<std::string> Libraries; std::vector<cmLinkItem> Libraries;
// Shared library dependencies needed for linking on some platforms. // Shared library dependencies needed for linking on some platforms.
std::vector<std::string> SharedDeps; std::vector<cmLinkItem> SharedDeps;
// Number of repetitions of a strongly connected component of two // Number of repetitions of a strongly connected component of two
// or more static libraries. // or more static libraries.
@ -263,7 +268,7 @@ public:
// Libraries listed for other configurations. // Libraries listed for other configurations.
// Needed only for OLD behavior of CMP0003. // Needed only for OLD behavior of CMP0003.
std::vector<std::string> WrongConfigLibraries; std::vector<cmLinkItem> WrongConfigLibraries;
bool ImplementationIsInterface; bool ImplementationIsInterface;
@ -278,10 +283,9 @@ public:
cmTarget const* headTarget) const; cmTarget const* headTarget) const;
void GetTransitivePropertyTargets(const std::string& config, void GetTransitivePropertyTargets(const std::string& config,
cmTarget const* headTarget, cmTarget const* headTarget,
std::vector<cmTarget*> &libs) const; std::vector<cmTarget const*> &libs) const;
void GetTransitiveTargetClosure(const std::string& config, std::vector<cmTarget const*> const&
cmTarget const* headTarget, GetLinkImplementationClosure(const std::string& config) const;
std::vector<cmTarget*> &libs) const;
/** The link implementation specifies the direct library /** The link implementation specifies the direct library
dependencies needed by the object files of the target. */ dependencies needed by the object files of the target. */
@ -291,18 +295,17 @@ public:
std::vector<std::string> Languages; std::vector<std::string> Languages;
// Libraries linked directly in this configuration. // Libraries linked directly in this configuration.
std::vector<std::string> Libraries; std::vector<cmLinkItem> Libraries;
// Libraries linked directly in other configurations. // Libraries linked directly in other configurations.
// Needed only for OLD behavior of CMP0003. // Needed only for OLD behavior of CMP0003.
std::vector<std::string> WrongConfigLibraries; std::vector<cmLinkItem> WrongConfigLibraries;
}; };
LinkImplementation const* GetLinkImplementation(const std::string& config, LinkImplementation const*
cmTarget const* head) const; GetLinkImplementation(const std::string& config) const;
LinkImplementation const* GetLinkImplementationLibraries( LinkImplementation const*
const std::string& config, GetLinkImplementationLibraries(const std::string& config) const;
cmTarget const* head) const;
/** Link information from the transitive closure of the link /** Link information from the transitive closure of the link
implementation and the interfaces of its dependencies. */ implementation and the interfaces of its dependencies. */
@ -314,8 +317,9 @@ public:
// Languages whose runtime libraries must be linked. // Languages whose runtime libraries must be linked.
std::vector<std::string> Languages; std::vector<std::string> Languages;
}; };
LinkClosure const* GetLinkClosure(const std::string& config, LinkClosure const* GetLinkClosure(const std::string& config) const;
cmTarget const* head) const;
cmTarget const* FindTargetToLink(std::string const& name) const;
/** Strip off leading and trailing whitespace from an item named in /** Strip off leading and trailing whitespace from an item named in
the link dependencies of this target. */ the link dependencies of this target. */
@ -361,8 +365,7 @@ public:
GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const; GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const;
///! Return the preferred linker language for this target ///! Return the preferred linker language for this target
std::string GetLinkerLanguage(const std::string& config = "", std::string GetLinkerLanguage(const std::string& config = "") const;
cmTarget const* head = 0) const;
/** Get the full name of the target according to the settings in its /** Get the full name of the target according to the settings in its
makefile. */ makefile. */
@ -446,8 +449,8 @@ public:
* install tree. For example: "\@rpath/" or "\@loader_path/". */ * install tree. For example: "\@rpath/" or "\@loader_path/". */
std::string GetInstallNameDirForInstallTree() const; std::string GetInstallNameDirForInstallTree() const;
cmComputeLinkInformation* GetLinkInformation(const std::string& config, cmComputeLinkInformation*
cmTarget const* head = 0) const; GetLinkInformation(const std::string& config) const;
// Get the properties // Get the properties
cmPropertyMap &GetProperties() const { return this->Properties; } cmPropertyMap &GetProperties() const { return this->Properties; }
@ -740,10 +743,9 @@ private:
// Cache import information from properties for each configuration. // Cache import information from properties for each configuration.
struct ImportInfo; struct ImportInfo;
ImportInfo const* GetImportInfo(const std::string& config, ImportInfo const* GetImportInfo(const std::string& config) const;
cmTarget const* workingTarget) const; void ComputeImportInfo(std::string const& desired_config,
void ComputeImportInfo(std::string const& desired_config, ImportInfo& info, ImportInfo& info) const;
cmTarget const* head) const;
// Cache target compile paths for each configuration. // Cache target compile paths for each configuration.
struct CompileInfo; struct CompileInfo;
@ -753,19 +755,31 @@ private:
void CheckPropertyCompatibility(cmComputeLinkInformation *info, void CheckPropertyCompatibility(cmComputeLinkInformation *info,
const std::string& config) const; const std::string& config) const;
LinkInterface const*
GetImportLinkInterface(const std::string& config,
cmTarget const* head) const;
const char* ComputeLinkInterfaceLibraries(const std::string& config, const char* ComputeLinkInterfaceLibraries(const std::string& config,
LinkInterface& iface, LinkInterface& iface,
cmTarget const* head, cmTarget const* head,
bool &exists) const; bool &exists) const;
LinkImplementation const*
GetLinkImplementationLibrariesInternal(const std::string& config,
cmTarget const* head) const;
void ComputeLinkImplementation(const std::string& config, void ComputeLinkImplementation(const std::string& config,
LinkImplementation& impl, LinkImplementation& impl,
cmTarget const* head) const; cmTarget const* head) const;
void ComputeLinkImplementationLanguages(const std::string& config, void ComputeLinkImplementationLanguages(const std::string& config,
LinkImplementation& impl, LinkImplementation& impl,
cmTarget const* head) const; cmTarget const* head) const;
void ComputeLinkClosure(const std::string& config, LinkClosure& lc, void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
cmTarget const* head) const;
void ExpandLinkItems(std::string const& prop, std::string const& value,
std::string const& config, cmTarget const* headTarget,
std::vector<cmLinkItem>& items) const;
void LookupLinkItems(std::vector<std::string> const& names,
std::vector<cmLinkItem>& items) const;
std::string ProcessSourceItemCMP0049(const std::string& s); std::string ProcessSourceItemCMP0049(const std::string& s);

View File

@ -8,8 +8,18 @@ target_compile_definitions(iface_nodepends INTERFACE IFACE_DEFINE)
add_subdirectory(headerdir) add_subdirectory(headerdir)
# Add an interface target in a subdirectory that uses an imported interface.
add_subdirectory(ifacedir)
# Poison an imported interface with the same name as that in the subdir
# to ensure that the transitive lookup occurs in the subdir.
add_library(imp::iface INTERFACE IMPORTED)
set_property(TARGET imp::iface APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SOMEPROP)
set_property(TARGET imp::iface PROPERTY INTERFACE_SOMEPROP OFF)
set_property(TARGET imp::iface PROPERTY INTERFACE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/does_not_exist.cpp)
add_executable(InterfaceLibrary definetestexe.cpp) add_executable(InterfaceLibrary definetestexe.cpp)
target_link_libraries(InterfaceLibrary iface_nodepends headeriface) target_link_libraries(InterfaceLibrary iface_nodepends headeriface subiface)
add_subdirectory(libsdir) add_subdirectory(libsdir)

View File

@ -15,7 +15,9 @@
#error Expected IFACE_HEADER_BUILDDIR #error Expected IFACE_HEADER_BUILDDIR
#endif #endif
extern int sub();
int main(int,char**) int main(int,char**)
{ {
return 0; return sub();
} }

View File

@ -0,0 +1,8 @@
add_library(imp::iface INTERFACE IMPORTED)
set_property(TARGET imp::iface APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SOMEPROP)
set_property(TARGET imp::iface PROPERTY INTERFACE_SOMEPROP ON)
set_property(TARGET imp::iface PROPERTY INTERFACE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sub.cpp)
add_library(subiface INTERFACE)
target_link_libraries(subiface INTERFACE imp::iface)
set_property(TARGET subiface PROPERTY INTERFACE_SOMEPROP ON)

View File

@ -0,0 +1 @@
int sub() { return 0; }