Commit 40cf3fb9 authored by Stephen Kelly's avatar Stephen Kelly Committed by Brad King

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.
parent 894f52f3
......@@ -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)
{
......
......@@ -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;
......
......@@ -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)
{
......
......@@ -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;
......
......@@ -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();
......
......@@ -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",
......
......@@ -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)
{
......
This diff is collapsed.
......@@ -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();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment