From c6a8002827e0d23d27906ea5760a67981660f453 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 11 Jul 2018 13:29:49 +0200 Subject: Autogen: Improve error detection during configuration cmQtAutoGenInitializer::InitCustomTargets and cmQtAutoGenInitializer::SetupCustomTargets now return their success value which gets evaluated and passed on by the caller (cmGlobalGenerator). Checks for the existance of the moc/uic/rcc binaries have been introduces in cmQtAutoGenInitializer. Additionally they get called once with a "-h" argument to determine if they're functional. This way any binary-not-found problem is caught during the configuration phase. --- Source/cmGlobalGenerator.cxx | 8 +- Source/cmQtAutoGenInitializer.cxx | 340 +++++++++++++++++++++++++------------- Source/cmQtAutoGenInitializer.h | 12 +- 3 files changed, 239 insertions(+), 121 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 2872831..c401844 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1318,7 +1318,9 @@ bool cmGlobalGenerator::Compute() // the AUTOMOC, AUTOUIC or AUTORCC property set auto autogenInits = this->CreateQtAutoGenInitializers(); for (auto& autoGen : autogenInits) { - autoGen->InitCustomTargets(); + if (!autoGen->InitCustomTargets()) { + return false; + } } #endif @@ -1341,7 +1343,9 @@ bool cmGlobalGenerator::Compute() #ifdef CMAKE_BUILD_WITH_CMAKE for (auto& autoGen : autogenInits) { - autoGen->SetupCustomTargets(); + if (!autoGen->SetupCustomTargets()) { + return false; + } autoGen.reset(nullptr); } autogenInits.clear(); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 8ede960..11ffe71 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -192,7 +192,7 @@ cmQtAutoGenInitializer::cmQtAutoGenInitializer( cmQtAutoGenInitializer::GetQtMinorVersion(target, this->QtVersionMajor); } -void cmQtAutoGenInitializer::InitCustomTargets() +bool cmQtAutoGenInitializer::InitCustomTargets() { cmMakefile* makefile = this->Target->Target->GetMakefile(); cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); @@ -319,51 +319,8 @@ void cmQtAutoGenInitializer::InitCustomTargets() // Acquire rcc executable and features if (this->RccEnabled) { - { - std::string err; - if (this->QtVersionMajor == "5") { - cmGeneratorTarget* tgt = - localGen->FindGeneratorTargetToUse("Qt5::rcc"); - if (tgt != nullptr) { - this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTORCC: Qt5::rcc target not found"; - } - } else if (QtVersionMajor == "4") { - cmGeneratorTarget* tgt = - localGen->FindGeneratorTargetToUse("Qt4::rcc"); - if (tgt != nullptr) { - this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTORCC: Qt4::rcc target not found"; - } - } else { - err = "The AUTORCC feature supports only Qt 4 and Qt 5"; - } - if (!err.empty()) { - err += " ("; - err += this->Target->GetName(); - err += ")"; - cmSystemTools::Error(err.c_str()); - } - } - // Detect if rcc supports (-)-list - if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) { - std::vector command; - command.push_back(this->RccExecutable); - command.push_back("--help"); - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = cmSystemTools::RunSingleCommand( - command, &rccStdOut, &rccStdErr, &retVal, nullptr, - cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); - if (result && retVal == 0 && - rccStdOut.find("--list") != std::string::npos) { - this->RccListOptions.push_back("--list"); - } else { - this->RccListOptions.push_back("-list"); - } + if (!GetRccExecutable()) { + return false; } } @@ -704,6 +661,7 @@ void cmQtAutoGenInitializer::InitCustomTargets() } } else { cmSystemTools::Error(error.c_str()); + return false; } } makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends, @@ -863,17 +821,20 @@ void cmQtAutoGenInitializer::InitCustomTargets() this->Target->Target->AddUtility(this->AutogenTargetName, makefile); } } + + return true; } -void cmQtAutoGenInitializer::SetupCustomTargets() +bool cmQtAutoGenInitializer::SetupCustomTargets() { cmMakefile* makefile = this->Target->Target->GetMakefile(); // Create info directory on demand if (!cmSystemTools::MakeDirectory(this->DirInfo)) { - std::string emsg = ("Could not create directory: "); + std::string emsg = ("AutoGen: Could not create directory: "); emsg += Quoted(this->DirInfo); cmSystemTools::Error(emsg.c_str()); + return false; } // Configuration include directories @@ -1007,7 +968,10 @@ void cmQtAutoGenInitializer::SetupCustomTargets() CWriteList("AM_UIC_SEARCH_PATHS", this->UicSearchPaths); } } else { - return; + std::string err = "AutoGen: Could not write file "; + err += this->AutogenInfoFile; + cmSystemTools::Error(err.c_str()); + return false; } } @@ -1072,13 +1036,18 @@ void cmQtAutoGenInitializer::SetupCustomTargets() CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); } else { - return; + std::string err = "AutoRcc: Could not write file "; + err += qrc.InfoFile; + cmSystemTools::Error(err.c_str()); + return false; } } } + + return true; } -void cmQtAutoGenInitializer::SetupCustomTargetsMoc() +bool cmQtAutoGenInitializer::SetupCustomTargetsMoc() { cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); cmMakefile* makefile = this->Target->Target->GetMakefile(); @@ -1129,41 +1098,14 @@ void cmQtAutoGenInitializer::SetupCustomTargetsMoc() } } - // Moc executable - { - std::string mocExec; - std::string err; - - if (this->QtVersionMajor == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc"); - if (tgt != nullptr) { - mocExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOMOC: Qt5::moc target not found"; - } - } else if (this->QtVersionMajor == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc"); - if (tgt != nullptr) { - mocExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOMOC: Qt4::moc target not found"; - } - } else { - err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; - } - - if (err.empty()) { - this->MocExecutable = mocExec; - } else { - err += " ("; - err += this->Target->GetName(); - err += ")"; - cmSystemTools::Error(err.c_str()); - } + if (!GetMocExecutable()) { + return false; } + + return true; } -void cmQtAutoGenInitializer::SetupCustomTargetsUic() +bool cmQtAutoGenInitializer::SetupCustomTargetsUic() { cmMakefile* makefile = this->Target->Target->GetMakefile(); @@ -1233,39 +1175,11 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic() } } - // Uic executable - { - std::string err; - std::string uicExec; - - cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); - if (this->QtVersionMajor == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic"); - if (tgt != nullptr) { - uicExec = SafeString(tgt->ImportedGetLocation("")); - } else { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway - } - } else if (this->QtVersionMajor == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic"); - if (tgt != nullptr) { - uicExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOUIC: Qt4::uic target not found"; - } - } else { - err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; - } - - if (err.empty()) { - this->UicExecutable = uicExec; - } else { - err += " ("; - err += this->Target->GetName(); - err += ")"; - cmSystemTools::Error(err.c_str()); - } + if (!GetUicExecutable()) { + return false; } + + return true; } void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, @@ -1335,6 +1249,202 @@ bool cmQtAutoGenInitializer::QtVersionGreaterOrEqual( return false; } +bool cmQtAutoGenInitializer::GetMocExecutable() +{ + std::string err; + + // Find moc executable + { + std::string targetName; + if (this->QtVersionMajor == "5") { + targetName = "Qt5::moc"; + } else if (QtVersionMajor == "4") { + targetName = "Qt4::moc"; + } else { + err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; + } + if (!targetName.empty()) { + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); + if (tgt != nullptr) { + this->MocExecutable = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "Could not find target " + targetName; + } + } + } + + // Test moc command + if (err.empty()) { + if (cmSystemTools::FileExists(this->MocExecutable, true)) { + std::vector command; + command.push_back(this->MocExecutable); + command.push_back("-h"); + std::string stdOut; + std::string stdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &stdOut, &stdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); + if (!result) { + err = "The moc test command failed: "; + err += QuotedCommand(command); + } + } else { + err = "The moc executable "; + err += Quoted(this->MocExecutable); + err += " does not exist"; + } + } + + // Print error + if (!err.empty()) { + std::string msg = "AutoMoc ("; + msg += this->Target->GetName(); + msg += "): "; + msg += err; + cmSystemTools::Error(msg.c_str()); + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::GetUicExecutable() +{ + std::string err; + + // Find uic executable + { + std::string targetName; + if (this->QtVersionMajor == "5") { + targetName = "Qt5::uic"; + } else if (QtVersionMajor == "4") { + targetName = "Qt4::uic"; + } else { + err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; + } + if (!targetName.empty()) { + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); + if (tgt != nullptr) { + this->UicExecutable = SafeString(tgt->ImportedGetLocation("")); + } else { + if (this->QtVersionMajor == "5") { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } else { + err = "Could not find target " + targetName; + } + } + } + } + + // Test uic command + if (err.empty()) { + if (cmSystemTools::FileExists(this->UicExecutable, true)) { + std::vector command; + command.push_back(this->UicExecutable); + command.push_back("-h"); + std::string stdOut; + std::string stdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &stdOut, &stdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); + if (!result) { + err = "The uic test command failed: "; + err += QuotedCommand(command); + } + } else { + err = "The uic executable "; + err += Quoted(this->UicExecutable); + err += " does not exist"; + } + } + + // Print error + if (!err.empty()) { + std::string msg = "AutoUic ("; + msg += this->Target->GetName(); + msg += "): "; + msg += err; + cmSystemTools::Error(msg.c_str()); + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::GetRccExecutable() +{ + std::string err; + + // Find rcc executable + { + std::string targetName; + if (this->QtVersionMajor == "5") { + targetName = "Qt5::rcc"; + } else if (QtVersionMajor == "4") { + targetName = "Qt4::rcc"; + } else { + err = "The AUTORCC feature supports only Qt 4 and Qt 5"; + } + if (!targetName.empty()) { + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); + if (tgt != nullptr) { + this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "Could not find target " + targetName; + } + } + } + + // Test rcc command + if (err.empty()) { + if (cmSystemTools::FileExists(this->RccExecutable, true)) { + std::vector command; + command.push_back(this->RccExecutable); + command.push_back("-h"); + std::string stdOut; + std::string stdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &stdOut, &stdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); + if (result) { + // Detect if rcc supports (-)-list + if (this->QtVersionMajor == "5") { + if (stdOut.find("--list") != std::string::npos) { + this->RccListOptions.push_back("--list"); + } else { + this->RccListOptions.push_back("-list"); + } + } + } else { + err = "The rcc test command failed: "; + err += QuotedCommand(command); + } + } else { + err = "The rcc executable "; + err += Quoted(this->RccExecutable); + err += " does not exist"; + } + } + + // Print error + if (!err.empty()) { + std::string msg = "AutoRcc ("; + msg += this->Target->GetName(); + msg += "): "; + msg += err; + cmSystemTools::Error(msg.c_str()); + return false; + } + + return true; +} + /// @brief Reads the resource files list from from a .qrc file /// @arg fileName Must be the absolute path of the .qrc file /// @return True if the rcc file was successfully read diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 813c680..bc78a03 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -50,18 +50,22 @@ public: bool uicEnabled, bool rccEnabled, std::string const& qtVersionMajor); - void InitCustomTargets(); - void SetupCustomTargets(); + bool InitCustomTargets(); + bool SetupCustomTargets(); private: - void SetupCustomTargetsMoc(); - void SetupCustomTargetsUic(); + bool SetupCustomTargetsMoc(); + bool SetupCustomTargetsUic(); void AddGeneratedSource(std::string const& filename, GeneratorT genType); bool QtVersionGreaterOrEqual(unsigned long requestMajor, unsigned long requestMinor) const; + bool GetMocExecutable(); + bool GetUicExecutable(); + bool GetRccExecutable(); + bool RccListInputs(std::string const& fileName, std::vector& files, std::string& errorMessage); -- cgit v0.12