mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-07 22:30:13 -06:00
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`.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <memory> // IWYU pragma: keep
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -40,6 +41,15 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CompilerFeatures
|
||||
{
|
||||
public:
|
||||
bool Evaluated = false;
|
||||
std::string HelpOutput;
|
||||
std::vector<std::string> ListOptions;
|
||||
};
|
||||
typedef std::shared_ptr<CompilerFeatures> CompilerFeaturesHandle;
|
||||
|
||||
/// @brief AutoGen generator type
|
||||
enum class GenT
|
||||
{
|
||||
|
||||
@@ -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<std::string> 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<cmQtAutoGen::CompilerFeatures>();
|
||||
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()
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include "cmQtAutoGen.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory> // IWYU pragma: keep
|
||||
#include <string>
|
||||
@@ -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<std::unique_ptr<cmQtAutoGenInitializer>> Initializers_;
|
||||
std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_;
|
||||
std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_;
|
||||
std::unordered_map<std::string, std::string> ExecutableTestOutputs_;
|
||||
std::unordered_map<std::string, cmQtAutoGen::CompilerFeaturesHandle>
|
||||
CompilerFeatures_;
|
||||
Keywords const Keywords_;
|
||||
};
|
||||
|
||||
|
||||
@@ -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<cmQtAutoGen::CompilerFeatures>();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1664,6 +1670,9 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
|
||||
}
|
||||
} else {
|
||||
if (ignoreMissingTarget) {
|
||||
// Create empty compiler features.
|
||||
genVars.ExecutableFeatures =
|
||||
std::make_shared<cmQtAutoGen::CompilerFeatures>();
|
||||
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;
|
||||
|
||||
@@ -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<std::string> ListOptions;
|
||||
std::vector<Qrc> Qrcs;
|
||||
|
||||
/// @brief Constructor
|
||||
|
||||
Reference in New Issue
Block a user