Refactor target linker language selection
This factors the decision logic out of cmTarget::ComputeLinkClosure into dedicated class cmTargetSelectLinker. We replace several local variables with a single object instance, and organize code into methods.
This commit is contained in:
parent
ace4d5d31d
commit
fd633b33cf
|
@ -2413,6 +2413,59 @@ cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config)
|
|||
return &i->second;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class cmTargetSelectLinker
|
||||
{
|
||||
int Preference;
|
||||
cmTarget* Target;
|
||||
cmMakefile* Makefile;
|
||||
cmGlobalGenerator* GG;
|
||||
std::set<cmStdString> Preferred;
|
||||
public:
|
||||
cmTargetSelectLinker(cmTarget* target): Preference(0), Target(target)
|
||||
{
|
||||
this->Makefile = this->Target->GetMakefile();
|
||||
this->GG = this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
|
||||
}
|
||||
void Consider(const char* lang)
|
||||
{
|
||||
int preference = this->GG->GetLinkerPreference(lang);
|
||||
if(preference > this->Preference)
|
||||
{
|
||||
this->Preference = preference;
|
||||
this->Preferred.clear();
|
||||
}
|
||||
if(preference == this->Preference)
|
||||
{
|
||||
this->Preferred.insert(lang);
|
||||
}
|
||||
}
|
||||
std::string Choose()
|
||||
{
|
||||
if(this->Preferred.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
else if(this->Preferred.size() > 1)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "Target " << this->Target->GetName()
|
||||
<< " contains multiple languages with the highest linker preference"
|
||||
<< " (" << this->Preference << "):\n";
|
||||
for(std::set<cmStdString>::const_iterator
|
||||
li = this->Preferred.begin(); li != this->Preferred.end(); ++li)
|
||||
{
|
||||
e << " " << *li << "\n";
|
||||
}
|
||||
e << "Set the LINKER_LANGUAGE property for this target.";
|
||||
cmake* cm = this->Makefile->GetCMakeInstance();
|
||||
cm->IssueMessage(cmake::FATAL_ERROR, e.str(),
|
||||
this->Target->GetBacktrace());
|
||||
}
|
||||
return *this->Preferred.begin();
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
|
||||
{
|
||||
|
@ -2452,39 +2505,13 @@ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
|
|||
else
|
||||
{
|
||||
// Find the language with the highest preference value.
|
||||
cmGlobalGenerator* gg =
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
|
||||
std::string linkerLangList; // only used for the error message
|
||||
int maxLinkerPref = 0;
|
||||
bool multiplePreferedLanguages = false;
|
||||
cmTargetSelectLinker tsl(this);
|
||||
for(std::set<cmStdString>::const_iterator sit = languages.begin();
|
||||
sit != languages.end(); ++sit)
|
||||
{
|
||||
int linkerPref = gg->GetLinkerPreference(sit->c_str());
|
||||
if (lc.LinkerLanguage.empty() || (linkerPref > maxLinkerPref))
|
||||
{
|
||||
maxLinkerPref = linkerPref;
|
||||
lc.LinkerLanguage = *sit;
|
||||
linkerLangList = *sit;
|
||||
multiplePreferedLanguages = false;
|
||||
}
|
||||
else if (linkerPref == maxLinkerPref)
|
||||
{
|
||||
linkerLangList += "; ";
|
||||
linkerLangList += *sit;
|
||||
multiplePreferedLanguages = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (multiplePreferedLanguages)
|
||||
{
|
||||
cmOStringStream err;
|
||||
err << "Error: Target " << this->Name << " contains multiple languages "
|
||||
<< "with the highest linker preference (" << maxLinkerPref << "): "
|
||||
<< linkerLangList << "\n"
|
||||
<< "You must set the LINKER_LANGUAGE property for this target.";
|
||||
cmSystemTools::Error(err.str().c_str());
|
||||
tsl.Consider(sit->c_str());
|
||||
}
|
||||
lc.LinkerLanguage = tsl.Choose();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue