Commit d9893fb5 authored by Sebastian Holtermann's avatar Sebastian Holtermann
Browse files

Autogen: Refactor Qt executable name computation

In AUTOGEN a common new  base class cmQtAutoGenInitializer::GenVarsT for
mo/uic/rcc generator variables allows to generalize variable computation
functions.
parent 5e36209f
......@@ -36,25 +36,9 @@
#include <set>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
std::string GetQtExecutableTargetName(
const cmQtAutoGen::IntegerVersion& qtVersion, std::string const& executable)
{
if (qtVersion.Major == 6) {
return ("Qt6::" + executable);
}
if (qtVersion.Major == 5) {
return ("Qt5::" + executable);
}
if (qtVersion.Major == 4) {
return ("Qt4::" + executable);
}
return ("");
}
static std::size_t GetParallelCPUCount()
{
static std::size_t count = 0;
......@@ -399,16 +383,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
// Init uic specific settings
if (this->Uic.Enabled) {
if (InitUic()) {
auto* uicTarget = makefile->FindTargetToUse(
GetQtExecutableTargetName(this->QtVersion, "uic"));
if (uicTarget != nullptr) {
this->AutogenTarget.DependTargets.insert(uicTarget);
}
} else {
return false;
}
if (this->Uic.Enabled && !InitUic()) {
return false;
}
// Autogen target name
......@@ -449,12 +425,6 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
this->AutogenTarget.DependOrigin =
this->Target->GetPropertyAsBool("AUTOGEN_ORIGIN_DEPENDS");
auto* mocTarget = makefile->FindTargetToUse(
GetQtExecutableTargetName(this->QtVersion, "moc"));
if (mocTarget != nullptr) {
this->AutogenTarget.DependTargets.insert(mocTarget);
}
std::string const deps =
this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
if (!deps.empty()) {
......@@ -575,7 +545,18 @@ bool cmQtAutoGenInitializer::InitMoc()
}
// Moc executable
return GetMocExecutable();
{
if (!this->GetQtExecutable(this->Moc, "moc", false, nullptr)) {
return false;
}
// Let the _autogen target depend on the moc executable
if (this->Moc.ExecutableTarget != nullptr) {
this->AutogenTarget.DependTargets.insert(
this->Moc.ExecutableTarget->Target);
}
}
return true;
}
bool cmQtAutoGenInitializer::InitUic()
......@@ -618,12 +599,39 @@ bool cmQtAutoGenInitializer::InitUic()
}
// Uic executable
return GetUicExecutable();
{
if (!this->GetQtExecutable(this->Uic, "uic", true, nullptr)) {
return false;
}
// Let the _autogen target depend on the uic executable
if (this->Uic.ExecutableTarget != nullptr) {
this->AutogenTarget.DependTargets.insert(
this->Uic.ExecutableTarget->Target);
}
}
return true;
}
bool cmQtAutoGenInitializer::InitRcc()
{
return GetRccExecutable();
// Rcc executable
{
std::string stdOut;
if (!this->GetQtExecutable(this->Rcc, "rcc", false, &stdOut)) {
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 {
this->Rcc.ListOptions.emplace_back("-list");
}
}
}
return true;
}
bool cmQtAutoGenInitializer::InitScanFiles()
......@@ -1109,7 +1117,6 @@ bool cmQtAutoGenInitializer::InitRccTargets()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
auto rccTargetName = GetQtExecutableTargetName(this->QtVersion, "rcc");
for (Qrc const& qrc : this->Rcc.Qrcs) {
// Register info file as generated by CMake
......@@ -1174,8 +1181,8 @@ bool cmQtAutoGenInitializer::InitRccTargets()
if (!this->TargetsFolder.empty()) {
autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
}
if (!rccTargetName.empty()) {
autoRccTarget->AddUtility(rccTargetName, makefile);
if (!this->Rcc.ExecutableTargetName.empty()) {
autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName, makefile);
}
}
// Add autogen target to the origin target dependencies
......@@ -1195,8 +1202,8 @@ bool cmQtAutoGenInitializer::InitRccTargets()
// Add resource file to the custom command dependencies
ccDepends.push_back(fileName);
}
if (!rccTargetName.empty()) {
ccDepends.push_back(rccTargetName);
if (!this->Rcc.ExecutableTargetName.empty()) {
ccDepends.push_back(this->Rcc.ExecutableTargetName);
}
makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
/*main_dependency*/ std::string(),
......@@ -1383,8 +1390,12 @@ static unsigned int CharPtrToUInt(const char* const input)
static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
cmGeneratorTarget const* target)
{
cmMakefile* makefile = target->Target->GetMakefile();
// Qt version variable prefixes
static std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core",
"QT" } };
std::vector<cmQtAutoGen::IntegerVersion> result;
result.reserve(prefixes.size() * 2);
// Adds a version to the result (nullptr safe)
auto addVersion = [&result](const char* major, const char* minor) {
cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major),
......@@ -1393,8 +1404,7 @@ static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
result.emplace_back(ver);
}
};
// Qt version variable prefixes
std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core", "QT" } };
cmMakefile* makefile = target->Target->GetMakefile();
// Read versions from variables
for (const std::string& prefix : prefixes) {
......@@ -1438,99 +1448,89 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
return res;
}
std::pair<bool, std::string> cmQtAutoGenInitializer::GetQtExecutable(
const std::string& executable, bool ignoreMissingTarget, std::string* output)
bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
const std::string& executable,
bool ignoreMissingTarget,
std::string* output) const
{
const std::string upperExecutable = cmSystemTools::UpperCase(executable);
std::string result = this->Target->Target->GetSafeProperty(
"AUTO" + upperExecutable + "_EXECUTABLE");
if (!result.empty()) {
cmListFileBacktrace lfbt =
this->Target->Target->GetMakefile()->GetBacktrace();
cmGeneratorExpression ge(lfbt);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(result);
result = cge->Evaluate(this->Target->GetLocalGenerator(), "");
return std::make_pair(true, result);
}
auto print_err = [this, &genVars](std::string const& err) {
std::string msg = genVars.GenNameUpper;
msg += " for target ";
msg += this->Target->GetName();
msg += ": ";
msg += err;
cmSystemTools::Error(msg);
};
std::string err;
// Custom executable
{
std::string const prop = genVars.GenNameUpper + "_EXECUTABLE";
std::string const val = this->Target->Target->GetSafeProperty(prop);
if (!val.empty()) {
// Evaluate generator expression
{
cmListFileBacktrace lfbt =
this->Target->Target->GetMakefile()->GetBacktrace();
cmGeneratorExpression ge(lfbt);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(val);
genVars.Executable =
cge->Evaluate(this->Target->GetLocalGenerator(), "");
}
if (genVars.Executable.empty() && !ignoreMissingTarget) {
print_err(prop + " evaluates to an empty value");
return false;
}
return true;
}
}
// Find executable
// Find executable target
{
const std::string targetName =
GetQtExecutableTargetName(this->QtVersion, executable);
if (targetName.empty()) {
err = "The AUTO" + upperExecutable + " feature ";
err += "supports only Qt 4, Qt 5 and Qt 6.";
} else {
cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
if (tgt != nullptr) {
if (tgt->IsImported()) {
result = tgt->ImportedGetLocation("");
} else {
result = tgt->GetLocation("");
}
// Find executable target name
std::string targetName;
if (this->QtVersion.Major == 4) {
targetName = "Qt4::";
} else if (this->QtVersion.Major == 5) {
targetName = "Qt5::";
} else if (this->QtVersion.Major == 6) {
targetName = "Qt6::";
}
targetName += executable;
// Find target
cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(targetName);
if (target != nullptr) {
genVars.ExecutableTargetName = targetName;
genVars.ExecutableTarget = target;
if (target->IsImported()) {
genVars.Executable = target->ImportedGetLocation("");
} else {
if (ignoreMissingTarget) {
return std::make_pair(true, "");
}
err = "Could not find target " + targetName;
genVars.Executable = target->GetLocation("");
}
} else {
if (ignoreMissingTarget) {
return true;
}
std::string err = "Could not find ";
err += executable;
err += " executable target ";
err += targetName;
print_err(err);
return false;
}
}
// Test executable
if (err.empty()) {
this->GlobalInitializer->GetExecutableTestOutput(executable, result, err,
output);
}
// Print error
if (!err.empty()) {
std::string msg = "AutoGen (";
msg += this->Target->GetName();
msg += "): ";
msg += err;
cmSystemTools::Error(msg);
return std::make_pair(false, "");
}
return std::make_pair(true, result);
}
bool cmQtAutoGenInitializer::GetMocExecutable()
{
const auto result = this->GetQtExecutable("moc", false, nullptr);
this->Moc.Executable = result.second;
return result.first;
}
bool cmQtAutoGenInitializer::GetUicExecutable()
{
const auto result = this->GetQtExecutable("uic", true, nullptr);
this->Uic.Executable = result.second;
return result.first;
}
bool cmQtAutoGenInitializer::GetRccExecutable()
{
std::string stdOut;
const auto result = this->GetQtExecutable("rcc", false, &stdOut);
this->Rcc.Executable = result.second;
if (!result.first) {
return false;
}
if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) {
if (stdOut.find("--list") != std::string::npos) {
this->Rcc.ListOptions.emplace_back("--list");
} else {
this->Rcc.ListOptions.emplace_back("-list");
{
std::string err;
if (!this->GlobalInitializer->GetExecutableTestOutput(
executable, genVars.Executable, err, output)) {
print_err(err);
return false;
}
}
return true;
}
......
......@@ -40,6 +40,27 @@ public:
std::vector<std::string> Resources;
};
/// @brief Abstract moc/uic/rcc generator variables base class
struct GenVarsT
{
bool Enabled = false;
// Generator type/name
GenT Gen;
std::string const& GenName;
std::string const& GenNameUpper;
// Executable
std::string ExecutableTargetName;
cmGeneratorTarget* ExecutableTarget = nullptr;
std::string Executable;
/// @brief Constructor
GenVarsT(GenT gen, std::string const& genName,
std::string const& genNameUpper)
: Gen(gen)
, GenName(genName)
, GenNameUpper(genNameUpper){};
};
/// @brief Writes a CMake info file
class InfoWriter
{
......@@ -102,18 +123,13 @@ private:
void AddGeneratedSource(std::string const& filename, GenT genType,
bool prepend = false);
bool GetMocExecutable();
bool GetUicExecutable();
bool GetRccExecutable();
bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
bool ignoreMissingTarget, std::string* output) const;
bool RccListInputs(std::string const& fileName,
std::vector<std::string>& files,
std::string& errorMessage);
std::pair<bool, std::string> GetQtExecutable(const std::string& executable,
bool ignoreMissingTarget,
std::string* output);
private:
cmQtAutoGenGlobalInitializer* GlobalInitializer;
cmGeneratorTarget* Target;
......@@ -159,10 +175,8 @@ private:
} AutogenTarget;
/// @brief Moc only variables
struct
struct MocT : public GenVarsT
{
bool Enabled = false;
std::string Executable;
std::string PredefsCmd;
std::set<std::string> Skip;
std::vector<std::string> Includes;
......@@ -170,29 +184,40 @@ private:
std::set<std::string> Defines;
std::map<std::string, std::set<std::string>> ConfigDefines;
std::string MocsCompilation;
/// @brief Constructor
MocT()
: GenVarsT(cmQtAutoGen::GenT::MOC, cmQtAutoGen::GenNameMoc,
cmQtAutoGen::GenNameMocUpper){};
} Moc;
///@brief Uic only variables
struct
/// @brief Uic only variables
struct UicT : public GenVarsT
{
bool Enabled = false;
std::string Executable;
std::set<std::string> Skip;
std::vector<std::string> SearchPaths;
std::vector<std::string> Options;
std::map<std::string, std::vector<std::string>> ConfigOptions;
std::vector<std::string> FileFiles;
std::vector<std::vector<std::string>> FileOptions;
/// @brief Constructor
UicT()
: GenVarsT(cmQtAutoGen::GenT::UIC, cmQtAutoGen::GenNameUic,
cmQtAutoGen::GenNameUicUpper){};
} Uic;
/// @brief Rcc only variables
struct
struct RccT : public GenVarsT
{
bool Enabled = false;
bool GlobalTarget = false;
std::string Executable;
std::vector<std::string> ListOptions;
std::vector<Qrc> Qrcs;
/// @brief Constructor
RccT()
: GenVarsT(cmQtAutoGen::GenT::RCC, cmQtAutoGen::GenNameRcc,
cmQtAutoGen::GenNameRccUpper){};
} Rcc;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment