BUG: Fix Xcode linker language
Xcode does not seem to support direct requests for using the linker for a particular language. It always infers the linker using the languages in the source files. When no user source files compile with target's linker language we add one to help Xcode pick the linker. A typical use case is when a C executable links to a C++ archive. The executable has no C++ source files but we need to use the C++ linker.
This commit is contained in:
parent
bb2228ea1a
commit
a232dbe8d2
|
@ -317,6 +317,9 @@ protected:
|
||||||
// This is computed just before local generators generate.
|
// This is computed just before local generators generate.
|
||||||
cmTargetManifest TargetManifest;
|
cmTargetManifest TargetManifest;
|
||||||
|
|
||||||
|
// All targets in the entire project.
|
||||||
|
std::map<cmStdString,cmTarget *> TotalTargets;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float FirstTimeProgress;
|
float FirstTimeProgress;
|
||||||
// If you add a new map here, make sure it is copied
|
// If you add a new map here, make sure it is copied
|
||||||
|
@ -328,9 +331,6 @@ private:
|
||||||
std::map<cmStdString, cmStdString> ExtensionToLanguage;
|
std::map<cmStdString, cmStdString> ExtensionToLanguage;
|
||||||
std::map<cmStdString, int> LanguageToLinkerPreference;
|
std::map<cmStdString, int> LanguageToLinkerPreference;
|
||||||
|
|
||||||
// this is used to improve performance
|
|
||||||
std::map<cmStdString,cmTarget *> TotalTargets;
|
|
||||||
|
|
||||||
// Record hashes for rules and outputs.
|
// Record hashes for rules and outputs.
|
||||||
struct RuleHash { char Data[32]; };
|
struct RuleHash { char Data[32]; };
|
||||||
std::map<cmStdString, RuleHash> RuleHashes;
|
std::map<cmStdString, RuleHash> RuleHashes;
|
||||||
|
|
|
@ -239,6 +239,7 @@ void cmGlobalXCodeGenerator::Generate()
|
||||||
// add ALL_BUILD, INSTALL, etc
|
// add ALL_BUILD, INSTALL, etc
|
||||||
this->AddExtraTargets(root, it->second);
|
this->AddExtraTargets(root, it->second);
|
||||||
}
|
}
|
||||||
|
this->ForceLinkerLanguages();
|
||||||
this->cmGlobalGenerator::Generate();
|
this->cmGlobalGenerator::Generate();
|
||||||
for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
|
for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -968,6 +969,62 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmGlobalXCodeGenerator::ForceLinkerLanguages()
|
||||||
|
{
|
||||||
|
// This makes sure all targets link using the proper language.
|
||||||
|
for(std::map<cmStdString, cmTarget*>::const_iterator
|
||||||
|
ti = this->TotalTargets.begin(); ti != this->TotalTargets.end(); ++ti)
|
||||||
|
{
|
||||||
|
this->ForceLinkerLanguage(*ti->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
|
||||||
|
{
|
||||||
|
// This matters only for targets that link.
|
||||||
|
if(cmtarget.GetType() != cmTarget::EXECUTABLE &&
|
||||||
|
cmtarget.GetType() != cmTarget::SHARED_LIBRARY &&
|
||||||
|
cmtarget.GetType() != cmTarget::MODULE_LIBRARY)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* llang = cmtarget.GetLinkerLanguage("NOCONFIG");
|
||||||
|
if(!llang) { return; }
|
||||||
|
|
||||||
|
// If the language is compiled as a source trust Xcode to link with it.
|
||||||
|
cmTarget::LinkImplementation const* impl =
|
||||||
|
cmtarget.GetLinkImplementation("NOCONFIG");
|
||||||
|
for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
|
||||||
|
li != impl->Languages.end(); ++li)
|
||||||
|
{
|
||||||
|
if(*li == llang) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an empty source file to the target that compiles with the
|
||||||
|
// linker language. This should convince Xcode to choose the proper
|
||||||
|
// language.
|
||||||
|
cmMakefile* mf = cmtarget.GetMakefile();
|
||||||
|
std::string fname = mf->GetCurrentOutputDirectory();
|
||||||
|
fname += cmake::GetCMakeFilesDirectory();
|
||||||
|
fname += "/";
|
||||||
|
fname += cmtarget.GetName();
|
||||||
|
fname += "-CMakeForceLinker";
|
||||||
|
fname += ".";
|
||||||
|
fname += cmSystemTools::LowerCase(llang);
|
||||||
|
{
|
||||||
|
cmGeneratedFileStream fout(fname.c_str());
|
||||||
|
fout << "\n";
|
||||||
|
}
|
||||||
|
if(cmSourceFile* sf = mf->GetOrCreateSource(fname.c_str()))
|
||||||
|
{
|
||||||
|
sf->SetProperty("LANGUAGE", llang);
|
||||||
|
cmtarget.AddSourceFile(sf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile* sf)
|
bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile* sf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -128,6 +128,8 @@ private:
|
||||||
cmXCodeObject* CreateObjectReference(cmXCodeObject*);
|
cmXCodeObject* CreateObjectReference(cmXCodeObject*);
|
||||||
cmXCodeObject* CreateXCodeTarget(cmTarget& target,
|
cmXCodeObject* CreateXCodeTarget(cmTarget& target,
|
||||||
cmXCodeObject* buildPhases);
|
cmXCodeObject* buildPhases);
|
||||||
|
void ForceLinkerLanguages();
|
||||||
|
void ForceLinkerLanguage(cmTarget& cmtarget);
|
||||||
const char* GetTargetFileType(cmTarget& cmtarget);
|
const char* GetTargetFileType(cmTarget& cmtarget);
|
||||||
const char* GetTargetProductType(cmTarget& cmtarget);
|
const char* GetTargetProductType(cmTarget& cmtarget);
|
||||||
std::string AddConfigurations(cmXCodeObject* target, cmTarget& cmtarget);
|
std::string AddConfigurations(cmXCodeObject* target, cmTarget& cmtarget);
|
||||||
|
|
Loading…
Reference in New Issue