Make linking APIs aware of 'head' target

The 'head' is the dependent target to be linked with the current target.
It will be used to evaluate generator expressions with proper handling
of mapped configurations and is used as the source target of properties.

This requires that memoization is done with a key of a pair of target
and config, instead of just config, because now the result also depends
on the target.  Removing the memoization entirely is not an option
because it slows cmake down considerably.
This commit is contained in:
Stephen Kelly 2013-01-04 13:31:01 +01:00 committed by Brad King
parent 894f52f32d
commit 40cf3fb95b
9 changed files with 119 additions and 70 deletions

View File

@ -172,10 +172,11 @@ satisfy dependencies.
//----------------------------------------------------------------------------
cmComputeLinkDepends
::cmComputeLinkDepends(cmTarget* target, const char* config)
::cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget* head)
{
// Store context information.
this->Target = target;
this->HeadTarget = head;
this->Makefile = this->Target->GetMakefile();
this->LocalGenerator = this->Makefile->GetLocalGenerator();
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
@ -352,7 +353,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
{
// Follow the target dependencies.
if(cmTarget::LinkInterface const* iface =
entry.Target->GetLinkInterface(this->Config))
entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
{
// This target provides its own link interface information.
this->AddLinkEntries(depender_index, iface->Libraries);
@ -444,7 +445,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
if(entry.Target)
{
if(cmTarget::LinkInterface const* iface =
entry.Target->GetLinkInterface(this->Config))
entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
{
// Follow public and private dependencies transitively.
this->FollowSharedDeps(index, iface, true);
@ -533,7 +534,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
{
// Add direct link dependencies in this configuration.
cmTarget::LinkImplementation const* impl =
this->Target->GetLinkImplementation(this->Config);
this->Target->GetLinkImplementation(this->Config, this->HeadTarget);
this->AddLinkEntries(-1, impl->Libraries);
for(std::vector<std::string>::const_iterator
wi = impl->WrongConfigLibraries.begin();
@ -944,7 +945,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
if(cmTarget* target = this->EntryList[*ni].Target)
{
if(cmTarget::LinkInterface const* iface =
target->GetLinkInterface(this->Config))
target->GetLinkInterface(this->Config, this->HeadTarget))
{
if(iface->Multiplicity > count)
{

View File

@ -32,7 +32,7 @@ class cmake;
class cmComputeLinkDepends
{
public:
cmComputeLinkDepends(cmTarget* target, const char* config);
cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget *head);
~cmComputeLinkDepends();
// Basic information about each link item.
@ -59,6 +59,7 @@ private:
// Context information.
cmTarget* Target;
cmTarget* HeadTarget;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
cmGlobalGenerator* GlobalGenerator;

View File

@ -239,10 +239,12 @@ because this need be done only for shared libraries without soname-s.
//----------------------------------------------------------------------------
cmComputeLinkInformation
::cmComputeLinkInformation(cmTarget* target, const char* config)
::cmComputeLinkInformation(cmTarget* target, const char* config,
cmTarget *headTarget)
{
// Store context information.
this->Target = target;
this->HeadTarget = headTarget;
this->Makefile = this->Target->GetMakefile();
this->LocalGenerator = this->Makefile->GetLocalGenerator();
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
@ -265,7 +267,7 @@ cmComputeLinkInformation
this->OrderDependentRPath = 0;
// Get the language used for linking this target.
this->LinkLanguage = this->Target->GetLinkerLanguage(config);
this->LinkLanguage = this->Target->GetLinkerLanguage(config, headTarget);
if(!this->LinkLanguage)
{
// The Compute method will do nothing, so skip the rest of the
@ -503,7 +505,7 @@ bool cmComputeLinkInformation::Compute()
}
// Compute the ordered link line items.
cmComputeLinkDepends cld(this->Target, this->Config);
cmComputeLinkDepends cld(this->Target, this->Config, this->HeadTarget);
cld.SetOldLinkDirMode(this->OldLinkDirMode);
cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute();
@ -569,7 +571,8 @@ bool cmComputeLinkInformation::Compute()
void cmComputeLinkInformation::AddImplicitLinkInfo()
{
// 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();
li != lc->Languages.end(); ++li)
{

View File

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

View File

@ -244,8 +244,9 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
const char *config,
std::set<cmStdString> &emitted)
{
cmTarget* depender = this->Targets[depender_index];
if(cmTarget::LinkInterface const* iface =
dependee->GetLinkInterface(config))
dependee->GetLinkInterface(config, depender))
{
for(std::vector<std::string>::const_iterator
lib = iface->Libraries.begin();

View File

@ -357,7 +357,8 @@ cmExportFileGenerator
}
// Add the transitive link dependencies for this configuration.
if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config))
if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
target))
{
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES",

View File

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

View File

@ -72,6 +72,11 @@ struct cmTarget::ImportInfo
cmTarget::LinkInterface LinkInterface;
};
struct TargetConfigPair : public std::pair<cmTarget*, std::string> {
TargetConfigPair(cmTarget* tgt, const std::string &config)
: std::pair<cmTarget*, std::string>(tgt, config) {}
};
//----------------------------------------------------------------------------
class cmTargetInternals
{
@ -100,20 +105,24 @@ public:
OptionalLinkInterface(): Exists(false) {}
bool Exists;
};
typedef std::map<cmStdString, OptionalLinkInterface> LinkInterfaceMapType;
typedef std::map<TargetConfigPair, OptionalLinkInterface>
LinkInterfaceMapType;
LinkInterfaceMapType LinkInterfaceMap;
typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType;
OutputInfoMapType OutputInfoMap;
typedef std::map<cmStdString, cmTarget::ImportInfo> ImportInfoMapType;
typedef std::map<TargetConfigPair, cmTarget::ImportInfo>
ImportInfoMapType;
ImportInfoMapType ImportInfoMap;
// Cache link implementation computation from each configuration.
typedef std::map<cmStdString, cmTarget::LinkImplementation> LinkImplMapType;
typedef std::map<TargetConfigPair,
cmTarget::LinkImplementation> LinkImplMapType;
LinkImplMapType LinkImplMap;
typedef std::map<cmStdString, cmTarget::LinkClosure> LinkClosureMapType;
typedef std::map<TargetConfigPair, cmTarget::LinkClosure>
LinkClosureMapType;
LinkClosureMapType LinkClosureMap;
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
@ -3024,8 +3033,11 @@ class cmTargetCollectLinkLanguages
{
public:
cmTargetCollectLinkLanguages(cmTarget* target, const char* config,
std::set<cmStdString>& languages):
Config(config), Languages(languages) { this->Visited.insert(target); }
std::set<cmStdString>& languages,
cmTarget* head):
Config(config), Languages(languages), HeadTarget(head)
{ this->Visited.insert(target); }
void Visit(cmTarget* target)
{
if(!target || !this->Visited.insert(target).second)
@ -3034,7 +3046,7 @@ public:
}
cmTarget::LinkInterface const* iface =
target->GetLinkInterface(this->Config);
target->GetLinkInterface(this->Config, this->HeadTarget);
if(!iface) { return; }
for(std::vector<std::string>::const_iterator
@ -3053,26 +3065,30 @@ public:
private:
const char* Config;
std::set<cmStdString>& Languages;
cmTarget* HeadTarget;
std::set<cmTarget*> Visited;
};
//----------------------------------------------------------------------------
const char* cmTarget::GetLinkerLanguage(const char* config)
const char* cmTarget::GetLinkerLanguage(const char* config, cmTarget *head)
{
const char* lang = this->GetLinkClosure(config)->LinkerLanguage.c_str();
cmTarget *headTarget = head ? head : this;
const char* lang = this->GetLinkClosure(config, headTarget)
->LinkerLanguage.c_str();
return *lang? lang : 0;
}
//----------------------------------------------------------------------------
cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config)
cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config,
cmTarget *head)
{
std::string key = cmSystemTools::UpperCase(config? config : "");
TargetConfigPair key(head, cmSystemTools::UpperCase(config ? config : ""));
cmTargetInternals::LinkClosureMapType::iterator
i = this->Internal->LinkClosureMap.find(key);
if(i == this->Internal->LinkClosureMap.end())
{
LinkClosure lc;
this->ComputeLinkClosure(config, lc);
this->ComputeLinkClosure(config, lc, head);
cmTargetInternals::LinkClosureMapType::value_type entry(key, lc);
i = this->Internal->LinkClosureMap.insert(entry).first;
}
@ -3133,11 +3149,12 @@ public:
};
//----------------------------------------------------------------------------
void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc,
cmTarget *head)
{
// Get languages built in this target.
std::set<cmStdString> languages;
LinkImplementation const* impl = this->GetLinkImplementation(config);
LinkImplementation const* impl = this->GetLinkImplementation(config, head);
for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
li != impl->Languages.end(); ++li)
{
@ -3145,7 +3162,7 @@ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
}
// Add interface languages from linked targets.
cmTargetCollectLinkLanguages cll(this, config, languages);
cmTargetCollectLinkLanguages cll(this, config, languages, head);
for(std::vector<std::string>::const_iterator li = impl->Libraries.begin();
li != impl->Libraries.end(); ++li)
{
@ -3284,7 +3301,8 @@ bool cmTarget::HasSOName(const char* config)
return ((this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY) &&
!this->GetPropertyAsBool("NO_SONAME") &&
this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config)));
this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config,
this)));
}
//----------------------------------------------------------------------------
@ -3293,7 +3311,7 @@ std::string cmTarget::GetSOName(const char* config)
if(this->IsImported())
{
// Lookup the imported soname.
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
if(info->NoSOName)
{
@ -3330,7 +3348,7 @@ bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config)
{
if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY)
{
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
return info->NoSOName;
}
@ -3444,7 +3462,7 @@ std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
{
std::string result;
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
result = implib? info->ImportLibrary : info->Location;
}
@ -3529,7 +3547,7 @@ void cmTarget::GetFullNameInternal(const char* config,
const char* suffixVar = this->GetSuffixVariableInternal(implib);
// Check for language-specific default prefix and suffix.
if(const char* ll = this->GetLinkerLanguage(config))
if(const char* ll = this->GetLinkerLanguage(config, this))
{
if(!targetSuffix && suffixVar && *suffixVar)
{
@ -3900,7 +3918,7 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config)
}
// Check for rpath support on this platform.
if(const char* ll = this->GetLinkerLanguage(config))
if(const char* ll = this->GetLinkerLanguage(config, this))
{
std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
flagVar += ll;
@ -4322,7 +4340,7 @@ bool cmTarget::IsChrpathUsed(const char* config)
// Enable if the rpath flag uses a separator and the target uses ELF
// binaries.
if(const char* ll = this->GetLinkerLanguage(config))
if(const char* ll = this->GetLinkerLanguage(config, this))
{
std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
sepVar += ll;
@ -4346,7 +4364,7 @@ bool cmTarget::IsChrpathUsed(const char* config)
//----------------------------------------------------------------------------
cmTarget::ImportInfo const*
cmTarget::GetImportInfo(const char* config)
cmTarget::GetImportInfo(const char* config, cmTarget *headTarget)
{
// There is no imported information for non-imported targets.
if(!this->IsImported())
@ -4365,14 +4383,16 @@ cmTarget::GetImportInfo(const char* config)
{
config_upper = "NOCONFIG";
}
TargetConfigPair key(headTarget, config_upper);
typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType;
ImportInfoMapType::const_iterator i =
this->Internal->ImportInfoMap.find(config_upper);
this->Internal->ImportInfoMap.find(key);
if(i == this->Internal->ImportInfoMap.end())
{
ImportInfo info;
this->ComputeImportInfo(config_upper, info);
ImportInfoMapType::value_type entry(config_upper, info);
this->ComputeImportInfo(config_upper, info, headTarget);
ImportInfoMapType::value_type entry(key, info);
i = this->Internal->ImportInfoMap.insert(entry).first;
}
@ -4511,8 +4531,10 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
//----------------------------------------------------------------------------
void cmTarget::ComputeImportInfo(std::string const& desired_config,
ImportInfo& info)
ImportInfo& info,
cmTarget *headTarget)
{
(void)headTarget;
// This method finds information about an imported target from its
// properties. The "IMPORTED_" namespace is reserved for properties
// defined by the project exporting the target.
@ -4669,12 +4691,13 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
//----------------------------------------------------------------------------
cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config,
cmTarget *head)
{
// Imported targets have their own link interface.
if(this->IsImported())
{
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head))
{
return &info->LinkInterface;
}
@ -4690,14 +4713,15 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
}
// Lookup any existing link interface for this configuration.
std::string key = cmSystemTools::UpperCase(config? config : "");
TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
cmTargetInternals::LinkInterfaceMapType::iterator
i = this->Internal->LinkInterfaceMap.find(key);
if(i == this->Internal->LinkInterfaceMap.end())
{
// Compute the link interface for this configuration.
cmTargetInternals::OptionalLinkInterface iface;
iface.Exists = this->ComputeLinkInterface(config, iface);
iface.Exists = this->ComputeLinkInterface(config, iface, head);
// Store the information for this configuration.
cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface);
@ -4708,7 +4732,8 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
}
//----------------------------------------------------------------------------
bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
cmTarget *headTarget)
{
// Construct the property name suffix for this configuration.
std::string suffix = "_";
@ -4765,7 +4790,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
{
emitted.insert(*li);
}
LinkImplementation const* impl = this->GetLinkImplementation(config);
LinkImplementation const* impl = this->GetLinkImplementation(config,
headTarget);
for(std::vector<std::string>::const_iterator
li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
{
@ -4793,7 +4819,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
else
{
// The link implementation is the default link interface.
LinkImplementation const* impl = this->GetLinkImplementation(config);
LinkImplementation const* impl = this->GetLinkImplementation(config,
headTarget);
iface.Libraries = impl->Libraries;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
if(this->GetType() == cmTarget::STATIC_LIBRARY)
@ -4825,7 +4852,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
//----------------------------------------------------------------------------
cmTarget::LinkImplementation const*
cmTarget::GetLinkImplementation(const char* config)
cmTarget::GetLinkImplementation(const char* config, cmTarget *head)
{
// There is no link implementation for imported targets.
if(this->IsImported())
@ -4834,14 +4861,15 @@ cmTarget::GetLinkImplementation(const char* config)
}
// Lookup any existing link implementation for this configuration.
std::string key = cmSystemTools::UpperCase(config? config : "");
TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
cmTargetInternals::LinkImplMapType::iterator
i = this->Internal->LinkImplMap.find(key);
if(i == this->Internal->LinkImplMap.end())
{
// Compute the link implementation for this configuration.
LinkImplementation impl;
this->ComputeLinkImplementation(config, impl);
this->ComputeLinkImplementation(config, impl, head);
// Store the information for this configuration.
cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
@ -4853,8 +4881,10 @@ cmTarget::GetLinkImplementation(const char* config)
//----------------------------------------------------------------------------
void cmTarget::ComputeLinkImplementation(const char* config,
LinkImplementation& impl)
LinkImplementation& impl,
cmTarget *head)
{
(void)head;
// Compute which library configuration to link.
cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
@ -4977,16 +5007,19 @@ std::string cmTarget::CheckCMP0004(std::string const& item)
//----------------------------------------------------------------------------
cmComputeLinkInformation*
cmTarget::GetLinkInformation(const char* config)
cmTarget::GetLinkInformation(const char* config, cmTarget *head)
{
cmTarget *headTarget = head ? head : this;
// Lookup any existing information for this configuration.
std::map<cmStdString, cmComputeLinkInformation*>::iterator
i = this->LinkInformation.find(config?config:"");
TargetConfigPair key(headTarget,
cmSystemTools::UpperCase(config?config:""));
cmTargetLinkInformationMap::iterator
i = this->LinkInformation.find(key);
if(i == this->LinkInformation.end())
{
// Compute information for this configuration.
cmComputeLinkInformation* info =
new cmComputeLinkInformation(this, config);
new cmComputeLinkInformation(this, config, headTarget);
if(!info || !info->Compute())
{
delete info;
@ -4994,8 +5027,7 @@ cmTarget::GetLinkInformation(const char* config)
}
// Store the information for this configuration.
std::map<cmStdString, cmComputeLinkInformation*>::value_type
entry(config?config:"", info);
cmTargetLinkInformationMap::value_type entry(key, info);
i = this->LinkInformation.insert(entry).first;
}
return i->second;

View File

@ -25,11 +25,13 @@ class cmSourceFile;
class cmGlobalGenerator;
class cmComputeLinkInformation;
class cmListFileBacktrace;
class cmTarget;
struct cmTargetLinkInformationMap:
public std::map<cmStdString, cmComputeLinkInformation*>
public std::map<std::pair<cmTarget*, std::string>, cmComputeLinkInformation*>
{
typedef std::map<cmStdString, cmComputeLinkInformation*> derived;
typedef std::map<std::pair<cmTarget*, std::string>,
cmComputeLinkInformation*> derived;
cmTargetLinkInformationMap() {}
cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r);
~cmTargetLinkInformationMap();
@ -258,7 +260,8 @@ public:
/** Get the link interface for the given configuration. Returns 0
if the target cannot be linked. */
LinkInterface const* GetLinkInterface(const char* config);
LinkInterface const* GetLinkInterface(const char* config,
cmTarget *headTarget);
/** The link implementation specifies the direct library
dependencies needed by the object files of the target. */
@ -274,7 +277,8 @@ public:
// Needed only for OLD behavior of CMP0003.
std::vector<std::string> WrongConfigLibraries;
};
LinkImplementation const* GetLinkImplementation(const char* config);
LinkImplementation const* GetLinkImplementation(const char* config,
cmTarget *head);
/** Link information from the transitive closure of the link
implementation and the interfaces of its dependencies. */
@ -286,7 +290,7 @@ public:
// Languages whose runtime libraries must be linked.
std::vector<std::string> Languages;
};
LinkClosure const* GetLinkClosure(const char* config);
LinkClosure const* GetLinkClosure(const char* config, cmTarget *head);
/** Strip off leading and trailing whitespace from an item named in
the link dependencies of this target. */
@ -331,7 +335,7 @@ public:
bool FindSourceFiles();
///! Return the preferred linker language for this target
const char* GetLinkerLanguage(const char* config = 0);
const char* GetLinkerLanguage(const char* config = 0, cmTarget *head = 0);
/** Get the full name of the target according to the settings in its
makefile. */
@ -399,7 +403,8 @@ public:
std::string GetInstallNameDirForInstallTree(const char* config,
bool for_xcode = false);
cmComputeLinkInformation* GetLinkInformation(const char* config);
cmComputeLinkInformation* GetLinkInformation(const char* config,
cmTarget *head = 0);
// Get the properties
cmPropertyMap &GetProperties() { return this->Properties; };
@ -597,16 +602,19 @@ private:
// Cache import information from properties for each configuration.
struct ImportInfo;
ImportInfo const* GetImportInfo(const char* config);
void ComputeImportInfo(std::string const& desired_config, ImportInfo& info);
ImportInfo const* GetImportInfo(const char* config,
cmTarget *workingTarget);
void ComputeImportInfo(std::string const& desired_config, ImportInfo& info,
cmTarget *head);
cmTargetLinkInformationMap LinkInformation;
bool ComputeLinkInterface(const char* config, LinkInterface& iface);
bool ComputeLinkInterface(const char* config, LinkInterface& iface,
cmTarget *head);
void ComputeLinkImplementation(const char* config,
LinkImplementation& impl);
void ComputeLinkClosure(const char* config, LinkClosure& lc);
LinkImplementation& impl, cmTarget *head);
void ComputeLinkClosure(const char* config, LinkClosure& lc, cmTarget *head);
void ClearLinkMaps();