diff options
author | Brad King <brad.king@kitware.com> | 2009-07-10 20:51:44 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2009-07-10 20:51:44 (GMT) |
commit | a232dbe8d23729e4aeeb3e27fe0a807903e82a62 (patch) | |
tree | cb0e83679ce19a02b87c5b1a4e2857cb9206cde4 | |
parent | bb2228ea1a2596c7068620a094e2ded3b4e5c8df (diff) | |
download | CMake-a232dbe8d23729e4aeeb3e27fe0a807903e82a62.zip CMake-a232dbe8d23729e4aeeb3e27fe0a807903e82a62.tar.gz CMake-a232dbe8d23729e4aeeb3e27fe0a807903e82a62.tar.bz2 |
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.
-rw-r--r-- | Source/cmGlobalGenerator.h | 6 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 57 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.h | 2 |
3 files changed, 62 insertions, 3 deletions
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 0eb27e4..4df2d39 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -317,6 +317,9 @@ protected: // This is computed just before local generators generate. cmTargetManifest TargetManifest; + // All targets in the entire project. + std::map<cmStdString,cmTarget *> TotalTargets; + private: float FirstTimeProgress; // 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, int> LanguageToLinkerPreference; - // this is used to improve performance - std::map<cmStdString,cmTarget *> TotalTargets; - // Record hashes for rules and outputs. struct RuleHash { char Data[32]; }; std::map<cmStdString, RuleHash> RuleHashes; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 5f22946..353fa6e 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -239,6 +239,7 @@ void cmGlobalXCodeGenerator::Generate() // add ALL_BUILD, INSTALL, etc this->AddExtraTargets(root, it->second); } + this->ForceLinkerLanguages(); this->cmGlobalGenerator::Generate(); for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it) { @@ -969,6 +970,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) { const std::vector<std::string>& hdrExts = diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index ba1529d..e7bb20c 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -128,6 +128,8 @@ private: cmXCodeObject* CreateObjectReference(cmXCodeObject*); cmXCodeObject* CreateXCodeTarget(cmTarget& target, cmXCodeObject* buildPhases); + void ForceLinkerLanguages(); + void ForceLinkerLanguage(cmTarget& cmtarget); const char* GetTargetFileType(cmTarget& cmtarget); const char* GetTargetProductType(cmTarget& cmtarget); std::string AddConfigurations(cmXCodeObject* target, cmTarget& cmtarget); |