mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-06 05:40:54 -06:00
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.
This commit is contained in:
@@ -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(), "");
|
||||
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);
|
||||
};
|
||||
|
||||
return std::make_pair(true, result);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
std::string err;
|
||||
|
||||
// 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("");
|
||||
}
|
||||
} else {
|
||||
if (ignoreMissingTarget) {
|
||||
return std::make_pair(true, "");
|
||||
}
|
||||
// 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;
|
||||
|
||||
err = "Could not find target " + targetName;
|
||||
// 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 {
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user