ENH: Centralize default link interface computation
When LINK_INTERFACE_LIBRARIES is not set we use the link implementation to implicitly define the link interface. These changes centralize the decision so that all linkable targets internally have a link interface.
This commit is contained in:
parent
26df00f83a
commit
06b0a692f4
|
@ -223,7 +223,7 @@ std::vector<cmComputeLinkDepends::LinkEntry> const&
|
||||||
cmComputeLinkDepends::Compute()
|
cmComputeLinkDepends::Compute()
|
||||||
{
|
{
|
||||||
// Follow the link dependencies of the target to be linked.
|
// Follow the link dependencies of the target to be linked.
|
||||||
this->AddTargetLinkEntries(-1, this->Target->GetOriginalLinkLibraries());
|
this->AddDirectLinkEntries();
|
||||||
|
|
||||||
// Complete the breadth-first search of dependencies.
|
// Complete the breadth-first search of dependencies.
|
||||||
while(!this->BFSQueue.empty())
|
while(!this->BFSQueue.empty())
|
||||||
|
@ -364,13 +364,14 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
|
||||||
|
|
||||||
// Handle dependent shared libraries.
|
// Handle dependent shared libraries.
|
||||||
this->QueueSharedDependencies(depender_index, iface->SharedDeps);
|
this->QueueSharedDependencies(depender_index, iface->SharedDeps);
|
||||||
}
|
|
||||||
else if(!entry.Target->IsImported() &&
|
// Support for CMP0003.
|
||||||
entry.Target->GetType() != cmTarget::EXECUTABLE)
|
for(std::vector<std::string>::const_iterator
|
||||||
{
|
oi = iface->WrongConfigLibraries.begin();
|
||||||
// Use the target's link implementation as the interface.
|
oi != iface->WrongConfigLibraries.end(); ++oi)
|
||||||
this->AddTargetLinkEntries(depender_index,
|
{
|
||||||
entry.Target->GetOriginalLinkLibraries());
|
this->CheckWrongConfigItem(depender_index, *oi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -516,11 +517,11 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void
|
void cmComputeLinkDepends::AddDirectLinkEntries()
|
||||||
cmComputeLinkDepends::AddTargetLinkEntries(int depender_index,
|
|
||||||
LinkLibraryVectorType const& libs)
|
|
||||||
{
|
{
|
||||||
// Look for entries meant for this configuration.
|
// Add direct link dependencies in this configuration.
|
||||||
|
int depender_index = -1;
|
||||||
|
LinkLibraryVectorType const& libs=this->Target->GetOriginalLinkLibraries();
|
||||||
std::vector<std::string> actual_libs;
|
std::vector<std::string> actual_libs;
|
||||||
for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
|
for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
|
||||||
li != libs.end(); ++li)
|
li != libs.end(); ++li)
|
||||||
|
@ -534,8 +535,6 @@ cmComputeLinkDepends::AddTargetLinkEntries(int depender_index,
|
||||||
this->CheckWrongConfigItem(depender_index, li->first);
|
this->CheckWrongConfigItem(depender_index, li->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add these entries.
|
|
||||||
this->AddLinkEntries(depender_index, actual_libs);
|
this->AddLinkEntries(depender_index, actual_libs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,8 +83,7 @@ private:
|
||||||
AllocateLinkEntry(std::string const& item);
|
AllocateLinkEntry(std::string const& item);
|
||||||
int AddLinkEntry(int depender_index, std::string const& item);
|
int AddLinkEntry(int depender_index, std::string const& item);
|
||||||
void AddVarLinkEntries(int depender_index, const char* value);
|
void AddVarLinkEntries(int depender_index, const char* value);
|
||||||
void AddTargetLinkEntries(int depender_index,
|
void AddDirectLinkEntries();
|
||||||
LinkLibraryVectorType const& libs);
|
|
||||||
void AddLinkEntries(int depender_index,
|
void AddLinkEntries(int depender_index,
|
||||||
std::vector<std::string> const& libs);
|
std::vector<std::string> const& libs);
|
||||||
cmTarget* FindTargetToLink(int depender_index, const char* name);
|
cmTarget* FindTargetToLink(int depender_index, const char* name);
|
||||||
|
|
|
@ -150,10 +150,8 @@ cmExportFileGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the transitive link dependencies for this configuration.
|
// Add the transitive link dependencies for this configuration.
|
||||||
if(cmTargetLinkInterface const* iface =
|
if(cmTargetLinkInterface const* iface = target->GetLinkInterface(config))
|
||||||
target->GetLinkInterface(config))
|
|
||||||
{
|
{
|
||||||
// This target provides a link interface, so use it.
|
|
||||||
this->SetImportLinkProperty(suffix, target,
|
this->SetImportLinkProperty(suffix, target,
|
||||||
"IMPORTED_LINK_INTERFACE_LIBRARIES",
|
"IMPORTED_LINK_INTERFACE_LIBRARIES",
|
||||||
iface->Libraries, properties);
|
iface->Libraries, properties);
|
||||||
|
@ -161,47 +159,6 @@ cmExportFileGenerator
|
||||||
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
|
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
|
||||||
iface->SharedDeps, properties);
|
iface->SharedDeps, properties);
|
||||||
}
|
}
|
||||||
else if(target->GetType() == cmTarget::STATIC_LIBRARY ||
|
|
||||||
target->GetType() == cmTarget::SHARED_LIBRARY)
|
|
||||||
{
|
|
||||||
// The default link interface for static and shared libraries is
|
|
||||||
// their link implementation library list.
|
|
||||||
this->SetImportLinkProperties(config, suffix, target, properties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
cmExportFileGenerator
|
|
||||||
::SetImportLinkProperties(const char* config, std::string const& suffix,
|
|
||||||
cmTarget* target, ImportPropertyMap& properties)
|
|
||||||
{
|
|
||||||
// Compute which library configuration to link.
|
|
||||||
cmTarget::LinkLibraryType linkType = target->ComputeLinkType(config);
|
|
||||||
|
|
||||||
// Construct the list of libs linked for this configuration.
|
|
||||||
std::vector<std::string> actual_libs;
|
|
||||||
cmTarget::LinkLibraryVectorType const& libs =
|
|
||||||
target->GetOriginalLinkLibraries();
|
|
||||||
for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
|
|
||||||
li != libs.end(); ++li)
|
|
||||||
{
|
|
||||||
// Skip entries that will resolve to the target itself, are empty,
|
|
||||||
// or are not meant for this configuration.
|
|
||||||
if(li->first == target->GetName() || li->first.empty() ||
|
|
||||||
!(li->second == cmTarget::GENERAL || li->second == linkType))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store this entry.
|
|
||||||
actual_libs.push_back(li->first);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the entries in the property.
|
|
||||||
this->SetImportLinkProperty(suffix, target,
|
|
||||||
"IMPORTED_LINK_INTERFACE_LIBRARIES",
|
|
||||||
actual_libs, properties);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
|
@ -67,9 +67,6 @@ protected:
|
||||||
void SetImportDetailProperties(const char* config,
|
void SetImportDetailProperties(const char* config,
|
||||||
std::string const& suffix, cmTarget* target,
|
std::string const& suffix, cmTarget* target,
|
||||||
ImportPropertyMap& properties);
|
ImportPropertyMap& properties);
|
||||||
void SetImportLinkProperties(const char* config,
|
|
||||||
std::string const& suffix, cmTarget* target,
|
|
||||||
ImportPropertyMap& properties);
|
|
||||||
void SetImportLinkProperty(std::string const& suffix,
|
void SetImportLinkProperty(std::string const& suffix,
|
||||||
cmTarget* target, const char* propName,
|
cmTarget* target, const char* propName,
|
||||||
std::vector<std::string> const& libs,
|
std::vector<std::string> const& libs,
|
||||||
|
|
|
@ -3682,10 +3682,10 @@ cmTargetLinkInterface const* cmTarget::GetLinkInterface(const char* config)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link interfaces are supported only for shared libraries and
|
// Link interfaces are not supported for executables that do not
|
||||||
// executables that export symbols.
|
// export symbols.
|
||||||
if((this->GetType() != cmTarget::SHARED_LIBRARY &&
|
if(this->GetType() == cmTarget::EXECUTABLE &&
|
||||||
!this->IsExecutableWithExports()))
|
!this->IsExecutableWithExports())
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3724,23 +3724,27 @@ cmTarget::ComputeLinkInterface(const char* config)
|
||||||
suffix += "NOCONFIG";
|
suffix += "NOCONFIG";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup the link interface libraries.
|
// An explicit list of interface libraries may be set for shared
|
||||||
const char* libs = 0;
|
// libraries and executables that export symbols.
|
||||||
{
|
const char* explicitLibraries = 0;
|
||||||
// Lookup the per-configuration property.
|
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||||
std::string propName = "LINK_INTERFACE_LIBRARIES";
|
this->IsExecutableWithExports())
|
||||||
propName += suffix;
|
|
||||||
libs = this->GetProperty(propName.c_str());
|
|
||||||
|
|
||||||
// If not set, try the generic property.
|
|
||||||
if(!libs)
|
|
||||||
{
|
{
|
||||||
libs = this->GetProperty("LINK_INTERFACE_LIBRARIES");
|
// Lookup the per-configuration property.
|
||||||
}
|
std::string propName = "LINK_INTERFACE_LIBRARIES";
|
||||||
}
|
propName += suffix;
|
||||||
|
explicitLibraries = this->GetProperty(propName.c_str());
|
||||||
|
|
||||||
// If still not set, there is no link interface.
|
// If not set, try the generic property.
|
||||||
if(!libs)
|
if(!explicitLibraries)
|
||||||
|
{
|
||||||
|
explicitLibraries = this->GetProperty("LINK_INTERFACE_LIBRARIES");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is no implicit link interface for executables, so if none
|
||||||
|
// was explicitly set, there is no link interface.
|
||||||
|
if(!explicitLibraries && this->GetType() == cmTarget::EXECUTABLE)
|
||||||
{
|
{
|
||||||
return cmsys::auto_ptr<cmTargetLinkInterface>();
|
return cmsys::auto_ptr<cmTargetLinkInterface>();
|
||||||
}
|
}
|
||||||
|
@ -3752,23 +3756,31 @@ cmTarget::ComputeLinkInterface(const char* config)
|
||||||
return cmsys::auto_ptr<cmTargetLinkInterface>();
|
return cmsys::auto_ptr<cmTargetLinkInterface>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand the list of libraries in the interface.
|
// Is the link interface just the link implementation?
|
||||||
cmSystemTools::ExpandListArgument(libs, iface->Libraries);
|
bool doLibraries = !explicitLibraries;
|
||||||
|
|
||||||
// Now we need to construct a list of shared library dependencies
|
// Do we need to construct a list of shared library dependencies not
|
||||||
// not included in the interface.
|
// included in the interface?
|
||||||
if(this->GetType() == cmTarget::SHARED_LIBRARY)
|
bool doSharedDeps = (explicitLibraries &&
|
||||||
|
this->GetType() == cmTarget::SHARED_LIBRARY);
|
||||||
|
|
||||||
|
// Keep track of what libraries have been emitted.
|
||||||
|
std::set<cmStdString> emitted;
|
||||||
|
std::set<cmStdString> emittedWrongConfig;
|
||||||
|
|
||||||
|
if(explicitLibraries)
|
||||||
{
|
{
|
||||||
// Use a set to keep track of what libraries have been emitted to
|
// The interface libraries have been explicitly set.
|
||||||
// either list.
|
cmSystemTools::ExpandListArgument(explicitLibraries, iface->Libraries);
|
||||||
std::set<cmStdString> emitted;
|
|
||||||
for(std::vector<std::string>::const_iterator
|
for(std::vector<std::string>::const_iterator
|
||||||
li = iface->Libraries.begin();
|
li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li)
|
||||||
li != iface->Libraries.end(); ++li)
|
|
||||||
{
|
{
|
||||||
emitted.insert(*li);
|
emitted.insert(*li);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doLibraries || doSharedDeps)
|
||||||
|
{
|
||||||
// Compute which library configuration to link.
|
// Compute which library configuration to link.
|
||||||
cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
|
cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
|
||||||
|
|
||||||
|
@ -3778,26 +3790,42 @@ cmTarget::ComputeLinkInterface(const char* config)
|
||||||
for(cmTarget::LinkLibraryVectorType::const_iterator li = llibs.begin();
|
for(cmTarget::LinkLibraryVectorType::const_iterator li = llibs.begin();
|
||||||
li != llibs.end(); ++li)
|
li != llibs.end(); ++li)
|
||||||
{
|
{
|
||||||
// Skip entries that will resolve to the target itself, are empty,
|
// Skip entries that resolve to the target itself or are empty.
|
||||||
// or are not meant for this configuration.
|
std::string item = this->CheckCMP0004(li->first);
|
||||||
if(li->first == this->GetName() || li->first.empty() ||
|
if(item == this->GetName() || item.empty())
|
||||||
!(li->second == cmTarget::GENERAL || li->second == linkType))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip entries that have already been emitted into either list.
|
// Skip entries not meant for this configuration.
|
||||||
if(!emitted.insert(li->first).second)
|
if(li->second != cmTarget::GENERAL && li->second != linkType)
|
||||||
|
{
|
||||||
|
// Support OLD behavior for CMP0003.
|
||||||
|
if(doLibraries && !emittedWrongConfig.insert(item).second)
|
||||||
|
{
|
||||||
|
iface->WrongConfigLibraries.push_back(item);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip entries that have already been emitted.
|
||||||
|
if(!emitted.insert(item).second)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this entry if it is a shared library.
|
// Emit this item.
|
||||||
if(cmTarget* tgt = this->Makefile->FindTargetToUse(li->first.c_str()))
|
if(doLibraries)
|
||||||
{
|
{
|
||||||
|
// This implementation dependency goes in the implicit interface.
|
||||||
|
iface->Libraries.push_back(item);
|
||||||
|
}
|
||||||
|
else if(cmTarget* tgt = this->Makefile->FindTargetToUse(item.c_str()))
|
||||||
|
{
|
||||||
|
// This is a runtime dependency on another shared library.
|
||||||
if(tgt->GetType() == cmTarget::SHARED_LIBRARY)
|
if(tgt->GetType() == cmTarget::SHARED_LIBRARY)
|
||||||
{
|
{
|
||||||
iface->SharedDeps.push_back(li->first);
|
iface->SharedDeps.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -46,6 +46,10 @@ struct cmTargetLinkInterface
|
||||||
|
|
||||||
// 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<std::string> SharedDeps;
|
||||||
|
|
||||||
|
// Libraries listed for other configurations.
|
||||||
|
// Needed only for OLD behavior of CMP0003.
|
||||||
|
std::vector<std::string> WrongConfigLibraries;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmTargetLinkInterfaceMap:
|
struct cmTargetLinkInterfaceMap:
|
||||||
|
|
Loading…
Reference in New Issue