From 71d6a1455e402755023b509629971afd1ed98922 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 22 May 2019 12:09:31 +0200 Subject: Autogen: Evaluate compiler features for the same exectuable only once To speed up the `AUTOGEN` configuration process, evaluate the compiler features only once. The feature evaluation result is stored in the new class `cmQtAutoGen::CompilerFeatures`, and the instance is shared by using `std::shared_ptr`. --- Source/cmQtAutoGen.h | 10 +++++++ Source/cmQtAutoGenGlobalInitializer.cxx | 37 +++++++++++------------- Source/cmQtAutoGenGlobalInitializer.h | 11 ++++--- Source/cmQtAutoGenInitializer.cxx | 51 +++++++++++++++++++-------------- Source/cmQtAutoGenInitializer.h | 5 ++-- 5 files changed, 66 insertions(+), 48 deletions(-) diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 3a346b5..9c52129 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include // IWYU pragma: keep #include #include @@ -40,6 +41,15 @@ public: } }; + class CompilerFeatures + { + public: + bool Evaluated = false; + std::string HelpOutput; + std::vector ListOptions; + }; + typedef std::shared_ptr CompilerFeaturesHandle; + /// @brief AutoGen generator type enum class GenT { diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index 59e17d7..ef8a56b 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -203,19 +203,16 @@ void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc( } } -bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( +cmQtAutoGen::CompilerFeaturesHandle +cmQtAutoGenGlobalInitializer::GetCompilerFeatures( std::string const& generator, std::string const& executable, - std::string& error, std::string* output) + std::string& error) { - // Check if we have cached output + // Check if we have cached features { - auto it = this->ExecutableTestOutputs_.find(executable); - if (it != this->ExecutableTestOutputs_.end()) { - // Return output on demand - if (output != nullptr) { - *output = it->second; - } - return true; + auto it = this->CompilerFeatures_.find(executable); + if (it != this->CompilerFeatures_.end()) { + return it->second; } } @@ -226,7 +223,7 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( error += "\" executable "; error += cmQtAutoGen::Quoted(executable); error += " does not exist."; - return false; + return cmQtAutoGen::CompilerFeaturesHandle(); } // Test the executable @@ -234,7 +231,7 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( { std::string stdErr; std::vector command; - command.push_back(executable); + command.emplace_back(executable); command.emplace_back("-h"); int retVal = 0; const bool runResult = cmSystemTools::RunSingleCommand( @@ -250,19 +247,19 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( error += stdOut; error += "\n"; error += stdErr; - return false; + return cmQtAutoGen::CompilerFeaturesHandle(); } } - // Return executable output on demand - if (output != nullptr) { - *output = stdOut; - } + // Create valid handle + cmQtAutoGen::CompilerFeaturesHandle res = + std::make_shared(); + res->HelpOutput = std::move(stdOut); - // Register executable and output - this->ExecutableTestOutputs_.emplace(executable, std::move(stdOut)); + // Register compiler features + this->CompilerFeatures_.emplace(executable, res); - return true; + return res; } bool cmQtAutoGenGlobalInitializer::generate() diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h index 77429b7..d56153a 100644 --- a/Source/cmQtAutoGenGlobalInitializer.h +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmQtAutoGen.h" + #include #include // IWYU pragma: keep #include @@ -68,15 +70,16 @@ private: void AddToGlobalAutoRcc(cmLocalGenerator* localGen, std::string const& targetName); - bool GetExecutableTestOutput(std::string const& generator, - std::string const& executable, - std::string& error, std::string* output); + cmQtAutoGen::CompilerFeaturesHandle GetCompilerFeatures( + std::string const& generator, std::string const& executable, + std::string& error); private: std::vector> Initializers_; std::map GlobalAutoGenTargets_; std::map GlobalAutoRccTargets_; - std::unordered_map ExecutableTestOutputs_; + std::unordered_map + CompilerFeatures_; Keywords const Keywords_; }; diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index a5e0f32..2d12964 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -511,7 +511,7 @@ bool cmQtAutoGenInitializer::InitMoc() // Moc executable { - if (!this->GetQtExecutable(this->Moc, "moc", false, nullptr)) { + if (!this->GetQtExecutable(this->Moc, "moc", false)) { return false; } // Let the _autogen target depend on the moc executable @@ -565,7 +565,7 @@ bool cmQtAutoGenInitializer::InitUic() // Uic executable { - if (!this->GetQtExecutable(this->Uic, "uic", true, nullptr)) { + if (!this->GetQtExecutable(this->Uic, "uic", true)) { return false; } // Let the _autogen target depend on the uic executable @@ -582,17 +582,22 @@ bool cmQtAutoGenInitializer::InitRcc() { // Rcc executable { - std::string stdOut; - if (!this->GetQtExecutable(this->Rcc, "rcc", false, &stdOut)) { + if (!this->GetQtExecutable(this->Rcc, "rcc", false)) { return false; } - // Evaluate test output - if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { - if (stdOut.find("--list") != std::string::npos) { - this->Rcc.ListOptions.emplace_back("--list"); - } else if (stdOut.find("-list") != std::string::npos) { - this->Rcc.ListOptions.emplace_back("-list"); + // Evaluate test output on demand + CompilerFeatures& features = *this->Rcc.ExecutableFeatures; + if (!features.Evaluated) { + // Look for list options + if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { + if (features.HelpOutput.find("--list") != std::string::npos) { + features.ListOptions.emplace_back("--list"); + } else if (features.HelpOutput.find("-list") != std::string::npos) { + features.ListOptions.emplace_back("-list"); + } } + // Evaluation finished + features.Evaluated = true; } } @@ -931,7 +936,8 @@ bool cmQtAutoGenInitializer::InitScanFiles() for (Qrc& qrc : this->Rcc.Qrcs) { if (!qrc.Generated) { std::string error; - RccLister const lister(this->Rcc.Executable, this->Rcc.ListOptions); + RccLister const lister(this->Rcc.Executable, + this->Rcc.ExecutableFeatures->ListOptions); if (!lister.list(qrc.QrcFile, qrc.Resources, error)) { cmSystemTools::Error(error); return false; @@ -1437,7 +1443,8 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() ofs.Write("# Rcc executable\n"); ofs.Write("ARCC_RCC_EXECUTABLE", this->Rcc.Executable); - ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS", this->Rcc.ListOptions); + ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS", + this->Rcc.ExecutableFeatures->ListOptions); ofs.Write("# Rcc job\n"); ofs.Write("ARCC_LOCK_FILE", qrc.LockFile); @@ -1600,8 +1607,7 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, const std::string& executable, - bool ignoreMissingTarget, - std::string* output) const + bool ignoreMissingTarget) const { auto print_err = [this, &genVars](std::string const& err) { std::string msg = genVars.GenNameUpper; @@ -1631,9 +1637,9 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, return false; } - // Check if the provided executable already exists (it's possible for it - // not to exist when building Qt itself). - genVars.ExecutableExists = cmSystemTools::FileExists(genVars.Executable); + // Create empty compiler features. + genVars.ExecutableFeatures = + std::make_shared(); return true; } } @@ -1664,6 +1670,9 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, } } else { if (ignoreMissingTarget) { + // Create empty compiler features. + genVars.ExecutableFeatures = + std::make_shared(); return true; } std::string err = "Could not find "; @@ -1675,15 +1684,15 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, } } - // Test executable + // Get executable features { std::string err; - if (!this->GlobalInitializer->GetExecutableTestOutput( - executable, genVars.Executable, err, output)) { + genVars.ExecutableFeatures = this->GlobalInitializer->GetCompilerFeatures( + executable, genVars.Executable, err); + if (!genVars.ExecutableFeatures) { print_err(err); return false; } - genVars.ExecutableExists = true; } return true; diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 6d2dcb6..aa073d1 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -67,7 +67,7 @@ public: std::string ExecutableTargetName; cmGeneratorTarget* ExecutableTarget = nullptr; std::string Executable; - bool ExecutableExists = false; + CompilerFeaturesHandle ExecutableFeatures; /// @brief Constructor GenVarsT(GenT gen) @@ -148,7 +148,7 @@ private: void AddCleanFile(std::string const& fileName); bool GetQtExecutable(GenVarsT& genVars, const std::string& executable, - bool ignoreMissingTarget, std::string* output) const; + bool ignoreMissingTarget) const; private: cmQtAutoGenGlobalInitializer* GlobalInitializer; @@ -230,7 +230,6 @@ private: struct RccT : public GenVarsT { bool GlobalTarget = false; - std::vector ListOptions; std::vector Qrcs; /// @brief Constructor -- cgit v0.12