From c83a834d29965e245e1e93fcda0e98e58e775f9f Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 24 Jan 2011 10:00:45 -0500 Subject: [PATCH] try_compile: Allow only languages loaded in caller (#11469) During a try_compile cmGlobalGenerator::EnableLanguage uses results from the outer project. Reject attempts to enable languages in the test project that are not "ready" in the outer project. Mark a language as "ready" when all its information has been loaded and we are ready to generate build rules. This also avoids infinite recursion introduced by commit 295b5b60 (Honor CMAKE_USER_MAKE_RULES_OVERRIDE in try_compile, 2010-06-29) for projects that set CMAKE_USER_MAKE_RULES_OVERRIDE to a file that uses try_compile. The file is loaded along with the information for a given langauge so the language is not yet "ready". --- Source/cmGlobalGenerator.cxx | 44 ++++++++++++++++++++++++++++-------- Source/cmGlobalGenerator.h | 5 +++- Source/cmMakefile.cxx | 2 +- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index bd26b5fca..376d25cd3 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -56,6 +56,7 @@ cmGlobalGenerator::cmGlobalGenerator() this->ExtraGenerator = 0; this->CurrentLocalGenerator = 0; + this->TryCompileOuterMakefile = 0; } cmGlobalGenerator::~cmGlobalGenerator() @@ -199,6 +200,34 @@ cmGlobalGenerator::EnableLanguage(std::vectorconst& languages, cmSystemTools::SetFatalErrorOccured(); return; } + + if(this->TryCompileOuterMakefile) + { + // In a try-compile we can only enable languages provided by caller. + for(std::vector::const_iterator li = languages.begin(); + li != languages.end(); ++li) + { + if(*li == "NONE") + { + this->SetLanguageEnabled("NONE", mf); + } + else + { + const char* lang = li->c_str(); + if(this->LanguagesReady.find(lang) == this->LanguagesReady.end()) + { + cmOStringStream e; + e << "The test project needs language " + << lang << " which is not enabled."; + this->TryCompileOuterMakefile + ->IssueMessage(cmake::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return; + } + } + } + } + mf->AddDefinition("RUN_CONFIGURE", true); std::string rootBin = mf->GetHomeOutputDirectory(); rootBin += cmake::GetCMakeFilesDirectory(); @@ -208,15 +237,6 @@ cmGlobalGenerator::EnableLanguage(std::vectorconst& languages, // files from the parent cmake bin dir, into the try compile bin dir if(this->ConfiguredFilesPath.size()) { - for(std::vector::const_iterator l = languages.begin(); - l != languages.end(); ++l) - { - if(*l == "NONE") - { - this->SetLanguageEnabled("NONE", mf); - break; - } - } rootBin = this->ConfiguredFilesPath; } @@ -421,6 +441,7 @@ cmGlobalGenerator::EnableLanguage(std::vectorconst& languages, { this->SetLanguageEnabledMaps(lang, mf); } + this->LanguagesReady.insert(lang); std::string compilerName = "CMAKE_"; compilerName += lang; @@ -1339,9 +1360,11 @@ cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator() return lg; } -void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen ) +void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen, + cmMakefile* mf) { this->SetConfiguredFilesPath(gen); + this->TryCompileOuterMakefile = mf; const char* make = gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make, @@ -1349,6 +1372,7 @@ void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen ) cmCacheManager::FILEPATH); // copy the enabled languages this->LanguageEnabled = gen->LanguageEnabled; + this->LanguagesReady = gen->LanguagesReady; this->ExtensionToLanguage = gen->ExtensionToLanguage; this->IgnoreExtensions = gen->IgnoreExtensions; this->LanguageToOutputExtension = gen->LanguageToOutputExtension; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 878be1143..26690af1d 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -78,7 +78,8 @@ public: /** * Try to determine system infomation, get it from another generator */ - virtual void EnableLanguagesFromGenerator(cmGlobalGenerator *gen); + virtual void EnableLanguagesFromGenerator(cmGlobalGenerator *gen, + cmMakefile* mf); /** * Try running cmake and building a file. This is used for dynalically @@ -321,11 +322,13 @@ protected: std::map TotalTargets; private: + cmMakefile* TryCompileOuterMakefile; float FirstTimeProgress; // If you add a new map here, make sure it is copied // in EnableLanguagesFromGenerator std::map IgnoreExtensions; std::map LanguageEnabled; + std::set LanguagesReady; // Ready for try_compile std::map OutputExtensions; std::map LanguageToOutputExtension; std::map ExtensionToLanguage; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 8eece6b5a..c438011e0 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2691,7 +2691,7 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir, } // to save time we pass the EnableLanguage info directly gg->EnableLanguagesFromGenerator - (this->LocalGenerator->GetGlobalGenerator()); + (this->LocalGenerator->GetGlobalGenerator(), this); if(this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS",