Commit d912220e authored by Brad King's avatar Brad King
Browse files

cmTarget: Lookup targets in LinkInterface and LinkImplementation

Instead of storing just the string names in these structures, lookup any
target associated with each item and store its cmTarget pointer.  Use
the cmLinkItem class to hold the name and pointer together.  Update
client sites to use the pre-stored lookup result instead of looking up
the target name again.

Create a cmTarget::LookupLinkItems helper method to handle the lookup.
Since lookups are now moving from cmComputeLinkDepends::AddLinkEntries
to cmTarget::LookupLinkItems, move use of CheckCMP0004 to the latter.
This drops use of CheckCMP0004 from entries added for _LIB_DEPENDS
variables by cmComputeLinkDepends::AddVarLinkEntries, but I do not
think that use was intentional originally anyway.
parent edce4351
......@@ -292,8 +292,7 @@ cmComputeLinkDepends::AllocateLinkEntry(std::string const& item)
}
//----------------------------------------------------------------------------
int cmComputeLinkDepends::AddLinkEntry(int depender_index,
std::string const& item)
int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
{
// Check if the item entry has already been added.
std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item);
......@@ -310,7 +309,7 @@ int cmComputeLinkDepends::AddLinkEntry(int depender_index,
int index = lei->second;
LinkEntry& entry = this->EntryList[index];
entry.Item = item;
entry.Target = this->FindTargetToLink(depender_index, entry.Item);
entry.Target = item.Target;
entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
item.substr(0, 10) != "-framework");
......@@ -370,11 +369,11 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
this->FollowSharedDeps(depender_index, iface);
// Support for CMP0003.
for(std::vector<std::string>::const_iterator
for(std::vector<cmLinkItem>::const_iterator
oi = iface->WrongConfigLibraries.begin();
oi != iface->WrongConfigLibraries.end(); ++oi)
{
this->CheckWrongConfigItem(depender_index, *oi);
this->CheckWrongConfigItem(*oi);
}
}
}
......@@ -406,9 +405,9 @@ cmComputeLinkDepends
void
cmComputeLinkDepends
::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)
{
SharedDepEntry qe;
......@@ -432,8 +431,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
// Initialize the item entry.
LinkEntry& entry = this->EntryList[lei->second];
entry.Item = dep.Item;
entry.Target = this->FindTargetToLink(dep.DependerIndex,
dep.Item);
entry.Target = dep.Item.Target;
// This item was added specifically because it is a dependent
// shared library. It may get special treatment
......@@ -472,7 +470,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
cmSystemTools::ExpandListArgument(value, deplist);
// Look for entries meant for this configuration.
std::vector<std::string> actual_libs;
std::vector<cmLinkItem> actual_libs;
cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
bool haveLLT = false;
for(std::vector<std::string>::const_iterator di = deplist.begin();
......@@ -520,11 +518,13 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
// If the library is meant for this link type then use it.
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)
{
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.
......@@ -544,36 +544,36 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
cmTarget::LinkImplementation const* impl =
this->Target->GetLinkImplementation(this->Config);
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.end(); ++wi)
{
this->CheckWrongConfigItem(-1, *wi);
this->CheckWrongConfigItem(*wi);
}
}
//----------------------------------------------------------------------------
void
cmComputeLinkDepends::AddLinkEntries(int depender_index,
std::vector<std::string> const& libs)
cmComputeLinkDepends::AddLinkEntries(
int depender_index, std::vector<cmLinkItem> const& libs)
{
// Track inferred dependency sets implied by this list.
std::map<int, DependSet> dependSets;
// 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)
{
// Skip entries that will resolve to the target getting linked or
// are empty.
std::string item = this->Target->CheckCMP0004(*li);
cmLinkItem const& item = *li;
if(item == this->Target->GetName() || item.empty())
{
continue;
}
// 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.
if(depender_index >= 0)
......@@ -961,8 +961,7 @@ void cmComputeLinkDepends::DisplayFinalEntries()
}
//----------------------------------------------------------------------------
void cmComputeLinkDepends::CheckWrongConfigItem(int depender_index,
std::string const& item)
void cmComputeLinkDepends::CheckWrongConfigItem(cmLinkItem const& item)
{
if(!this->OldLinkDirMode)
{
......@@ -972,9 +971,8 @@ void cmComputeLinkDepends::CheckWrongConfigItem(int depender_index,
// For CMake 2.4 bug-compatibility we need to consider the output
// directories of targets linked in another configuration as link
// directories.
cmTarget const* tgt = this->FindTargetToLink(depender_index, item);
if(tgt && !tgt->IsImported())
if(item.Target && !item.Target->IsImported())
{
this->OldWrongConfigItems.insert(tgt);
this->OldWrongConfigItems.insert(item.Target);
}
}
......@@ -77,11 +77,11 @@ private:
std::map<std::string, int>::iterator
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 AddDirectLinkEntries();
void AddLinkEntries(int depender_index,
std::vector<std::string> const& libs);
std::vector<cmLinkItem> const& libs);
cmTarget const* FindTargetToLink(int depender_index,
const std::string& name);
......@@ -103,7 +103,7 @@ private:
// of the interface.
struct SharedDepEntry
{
std::string Item;
cmLinkItem Item;
int DependerIndex;
};
std::queue<SharedDepEntry> SharedDepQueue;
......@@ -112,7 +112,7 @@ private:
cmTarget::LinkInterface const* iface,
bool follow_interface = false);
void QueueSharedDependencies(int depender_index,
std::vector<std::string> const& deps);
std::vector<cmLinkItem> const& deps);
void HandleSharedDependency(SharedDepEntry const& dep);
// Dependency inferral for each link item.
......@@ -163,7 +163,7 @@ private:
// Compatibility help.
bool OldLinkDirMode;
void CheckWrongConfigItem(int depender_index, std::string const& item);
void CheckWrongConfigItem(cmLinkItem const& item);
std::set<cmTarget const*> OldWrongConfigItems;
};
......
......@@ -249,13 +249,15 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
const_cast<cmTarget*>(depender)->AddUtility(objLib);
}
}
std::vector<std::string> tlibs;
depender->GetDirectLinkLibraries(*it, tlibs);
cmTarget::LinkImplementation const* impl =
depender->GetLinkImplementation(*it);
// A target should not depend on itself.
emitted.insert(depender->GetName());
for(std::vector<std::string>::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
for(std::vector<cmLinkItem>::const_iterator
lib = impl->Libraries.begin();
lib != impl->Libraries.end(); ++lib)
{
// Don't emit the same library twice for this target.
if(emitted.insert(*lib).second)
......@@ -269,11 +271,11 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
// 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;
// A target should not depend on itself.
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)
{
// Don't emit the same utility twice for this target.
......@@ -295,7 +297,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
if(cmTarget::LinkInterface const* iface =
dependee->GetLinkInterface(config, depender))
{
for(std::vector<std::string>::const_iterator
for(std::vector<cmLinkItem>::const_iterator
lib = iface->Libraries.begin();
lib != iface->Libraries.end(); ++lib)
{
......@@ -311,12 +313,11 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
const std::string& dependee_name,
cmLinkItem const& dependee_name,
std::set<std::string> &emitted)
{
cmTarget const* depender = this->Targets[depender_index];
cmTarget const* dependee =
depender->GetMakefile()->FindTargetToUse(dependee_name);
cmTarget const* dependee = dependee_name.Target;
// Skip targets that will not really be linked. This is probably a
// name conflict between an external library and an executable
// within the project.
......@@ -344,16 +345,15 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
}
//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddTargetDepend(int depender_index,
const std::string& dependee_name,
bool linking)
void cmComputeTargetDepends::AddTargetDepend(
int depender_index, cmLinkItem const& dependee_name,
bool linking)
{
// Get the depender.
cmTarget const* depender = this->Targets[depender_index];
// Check the target's makefile first.
cmTarget const* dependee =
depender->GetMakefile()->FindTargetToUse(dependee_name);
cmTarget const* dependee = dependee_name.Target;
if(!dependee && !linking &&
(depender->GetType() != cmTarget::GLOBAL_TARGET))
......
......@@ -20,6 +20,7 @@
class cmComputeComponentGraph;
class cmGlobalGenerator;
class cmLinkItem;
class cmTarget;
class cmTargetDependSet;
......@@ -46,13 +47,13 @@ private:
void CollectDepends();
void CollectTargetDepends(int depender_index);
void AddTargetDepend(int depender_index,
const std::string& dependee_name,
cmLinkItem const& dependee_name,
bool linking);
void AddTargetDepend(int depender_index, cmTarget const* dependee,
bool linking);
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
void AddInterfaceDepends(int depender_index,
const std::string& dependee_name,
cmLinkItem const& dependee_name,
std::set<std::string> &emitted);
void AddInterfaceDepends(int depender_index, cmTarget const* dependee,
const std::string& config,
......
......@@ -800,7 +800,7 @@ static const char* targetPropertyTransitiveWhitelist[] = {
#undef TRANSITIVE_PROPERTY_NAME
std::string getLinkedTargetsContent(
const std::vector<cmTarget const*> &targets,
std::vector<cmTarget const*> &targets,
cmTarget const* target,
cmTarget const* headTarget,
cmGeneratorExpressionContext *context,
......@@ -841,7 +841,7 @@ std::string getLinkedTargetsContent(
return linkedTargetsContent;
}
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
std::string getLinkedTargetsContent(std::vector<cmLinkItem> const &libraries,
cmTarget const* target,
cmTarget const* headTarget,
cmGeneratorExpressionContext *context,
......@@ -849,13 +849,13 @@ std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
const std::string &interfacePropertyName)
{
std::vector<cmTarget const*> tgts;
for (std::vector<std::string>::const_iterator
for (std::vector<cmLinkItem>::const_iterator
it = libraries.begin();
it != libraries.end(); ++it)
{
if (cmTarget const *tgt = target->FindTargetToLink(*it))
if (it->Target)
{
tgts.push_back(tgt);
tgts.push_back(it->Target);
}
}
return getLinkedTargetsContent(tgts, target, headTarget, context,
......
......@@ -475,10 +475,10 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir,
}
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)
{
cmTarget const* tgt = this->Target->FindTargetToLink(*li);
cmTarget const* tgt = li->Target;
if (!tgt)
{
continue;
......
......@@ -2311,7 +2311,7 @@ cmTarget::GetIncludeDirectories(const std::string& config) const
if(this->Makefile->IsOn("APPLE"))
{
LinkImplementation const* impl = this->GetLinkImplementation(config);
for(std::vector<std::string>::const_iterator
for(std::vector<cmLinkItem>::const_iterator
it = impl->Libraries.begin();
it != impl->Libraries.end(); ++it)
{
......@@ -3513,13 +3513,11 @@ public:
Makefile(target->GetMakefile()), Target(target)
{ this->Visited.insert(target); }
void Visit(cmTarget const* from, const std::string& name)
void Visit(cmLinkItem const& item)
{
cmTarget const *target = from->FindTargetToLink(name);
if(!target)
if(!item.Target)
{
if(name.find("::") != std::string::npos)
if(item.find("::") != std::string::npos)
{
bool noMessage = false;
cmake::MessageType messageType = cmake::FATAL_ERROR;
......@@ -3545,7 +3543,7 @@ public:
if(!noMessage)
{
e << "Target \"" << this->Target->GetName()
<< "\" links to target \"" << name
<< "\" links to target \"" << item
<< "\" but the target was not found. Perhaps a find_package() "
"call is missing for an IMPORTED target, or an ALIAS target is "
"missing?";
......@@ -3556,13 +3554,13 @@ public:
}
return;
}
if(!this->Visited.insert(target).second)
if(!this->Visited.insert(item.Target).second)
{
return;
}
cmTarget::LinkInterface const* iface =
target->GetLinkInterface(this->Config, this->HeadTarget);
item.Target->GetLinkInterface(this->Config, this->HeadTarget);
if(!iface) { return; }
for(std::vector<std::string>::const_iterator
......@@ -3571,10 +3569,10 @@ public:
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)
{
this->Visit(target, *li);
this->Visit(*li);
}
}
private:
......@@ -3677,10 +3675,10 @@ void cmTarget::ComputeLinkClosure(const std::string& config,
// Add interface languages from linked targets.
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)
{
cll.Visit(this, *li);
cll.Visit(*li);
}
// Store the transitive closure of languages.
......@@ -3731,16 +3729,34 @@ void cmTarget::ExpandLinkItems(std::string const& prop,
std::string const& value,
std::string const& config,
cmTarget const* headTarget,
std::vector<std::string>& libs) const
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)));
}
}
//----------------------------------------------------------------------------
......@@ -6158,7 +6174,11 @@ cmTarget::GetImportLinkInterface(const std::string& config,
cmSystemTools::ExpandListArgument(info->Languages, iface.Languages);
this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
headTarget, iface.Libraries);
cmSystemTools::ExpandListArgument(info->SharedDeps, iface.SharedDeps);
{
std::vector<std::string> deps;
cmSystemTools::ExpandListArgument(info->SharedDeps, deps);
this->LookupLinkItems(deps, iface.SharedDeps);
}
cmTargetInternals::ImportLinkInterfaceMapType::value_type
entry(key, iface);
......@@ -6170,22 +6190,21 @@ cmTarget::GetImportLinkInterface(const std::string& config,
//----------------------------------------------------------------------------
void processILibs(const std::string& config,
cmTarget const* headTarget,
cmTarget const* curTarget,
std::string const& name,
cmLinkItem const& item,
std::vector<cmTarget const*>& tgts,
std::set<cmTarget const*>& emitted)
{
if (cmTarget const* tgt = curTarget->FindTargetToLink(name))
if (item.Target && emitted.insert(item.Target).second)
{
tgts.push_back(tgt);
tgts.push_back(item.Target);
if(cmTarget::LinkInterface const* iface =
tgt->GetLinkInterfaceLibraries(config, headTarget))
item.Target->GetLinkInterfaceLibraries(config, headTarget))
{
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)
{
processILibs(config, headTarget, tgt, *it, tgts, emitted);
processILibs(config, headTarget, *it, tgts, emitted);
}
}
}
......@@ -6205,10 +6224,10 @@ cmTarget::GetLinkImplementationClosure(const std::string& config) const
cmTarget::LinkImplementation const* impl
= 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)
{
processILibs(config, this, this, *it, tgts , emitted);
processILibs(config, this, *it, tgts , emitted);
}
}
return tgts;
......@@ -6229,12 +6248,12 @@ void cmTarget::GetTransitivePropertyTargets(const std::string& config,
|| this->GetPolicyStatusCMP0022() == cmPolicies::WARN
|| 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)
{
if (cmTarget const* tgt = this->FindTargetToLink(*it))
if (it->Target)
{
tgts.push_back(tgt);
tgts.push_back(it->Target);
}
}
return;
......@@ -6378,7 +6397,7 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config,
{
// Compare the link implementation fallback link interface to the
// preferred new link interface property and warn if different.
std::vector<std::string> ifaceLibs;
std::vector<cmLinkItem> ifaceLibs;
std::string newProp = "INTERFACE_LINK_LIBRARIES";
if(const char* newExplicitLibraries = this->GetProperty(newProp))
{
......@@ -6390,7 +6409,7 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config,
std::string oldLibraries;
std::string newLibraries;
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)
{
oldLibraries += sep;
......@@ -6398,7 +6417,7 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config,
sep = ";";
}
sep = "";
for(std::vector<std::string>::const_iterator it
for(std::vector<cmLinkItem>::const_iterator it
= ifaceLibs.begin(); it != ifaceLibs.end(); ++it)
{
newLibraries += sep;
......@@ -6449,7 +6468,7 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget,
// Shared libraries may have runtime implementation dependencies
// on other shared libraries that are not in the interface.
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)
{
emitted.insert(*li);
......@@ -6458,15 +6477,15 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget,
{
cmTarget::LinkImplementation const* impl =
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)
{
if(emitted.insert(*li).second)
{
if(cmTarget* tgt = thisTarget->Makefile->FindTargetToUse(*li))
if(li->Target)
{
// 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);
}
......@@ -6617,10 +6636,10 @@ void cmTarget::ComputeLinkImplementation(const std::string& config,
li != llibs.end(); ++li)
{
// Skip entries that resolve to the target itself or are empty.
std::string item = this->CheckCMP0004(*li);
if(item == this->GetName() || item.empty())
std::string name = this->CheckCMP0004(*li);
if(name == this->GetName() || name.empty())
{
if(item == this->GetName())
if(name == this->GetName())
{
bool noMessage = false;
cmake::MessageType messageType = cmake::FATAL_ERROR;
......@@ -6659,7 +6678,8 @@ void cmTarget::ComputeLinkImplementation(const std::string& config,
}
// 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);
......@@ -6669,13 +6689,14 @@ void cmTarget::ComputeLinkImplementation(const std::string& config,
{
if(li->second != cmTarget::GENERAL && li->second != linkType)
{
std::string item = this->CheckCMP0004(li->first);
if(item == this->GetName() || item.empty())
std::string name = this->CheckCMP0004(li->first);
if(name == this->GetName() || name.empty())