diff options
author | Brad King <brad.king@kitware.com> | 2019-04-08 11:58:48 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2019-04-08 11:58:58 (GMT) |
commit | 7e60e77c3c2a09eb11750616db50d2dc149a9c54 (patch) | |
tree | 52c860bbe7b64c54965f07fe12670e8b236dd97c | |
parent | 14270eab369c3b700d89ef385af2cb94a6497b1e (diff) | |
parent | 7b98a6eb68e6a2c9a422e42c8eeb78dfa4038364 (diff) | |
download | CMake-7e60e77c3c2a09eb11750616db50d2dc149a9c54.zip CMake-7e60e77c3c2a09eb11750616db50d2dc149a9c54.tar.gz CMake-7e60e77c3c2a09eb11750616db50d2dc149a9c54.tar.bz2 |
Merge topic 'autogen_autorcc_no_libuv'
7b98a6eb68 Autogen: Rename cmQtAutoGeneratorRcc to cmQtAutoRcc
9710d4aacf Autogen: Move libuv loop from cmQtAutoGenerator to cmQtAutoGeneratorMocUic
95e72c0157 Autogen: Make cmQtAutoGenerator::FileSystem Logger free
f161cfe5a8 Autogen: Move Logger and FileSystem member variables to generator classes
7baec5e94b AutoRcc: Don't use cmQtAutoGenerator::FileSystem methods
191269d247 AutoRcc: Remove libuv event loop from cmQtAutoGeneratorRcc
95de172b68 AutoRcc: Make rcc parsing function private
521475b41b AutoRcc: Use cmQtAutoGen::RccLister in initializer and generator
...
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3202
-rw-r--r-- | Source/CMakeLists.txt | 4 | ||||
-rw-r--r-- | Source/cmQtAutoGen.cxx | 118 | ||||
-rw-r--r-- | Source/cmQtAutoGen.h | 53 | ||||
-rw-r--r-- | Source/cmQtAutoGenInitializer.cxx | 90 | ||||
-rw-r--r-- | Source/cmQtAutoGenInitializer.h | 4 | ||||
-rw-r--r-- | Source/cmQtAutoGenerator.cxx | 265 | ||||
-rw-r--r-- | Source/cmQtAutoGenerator.h | 51 | ||||
-rw-r--r-- | Source/cmQtAutoGeneratorMocUic.cxx | 50 | ||||
-rw-r--r-- | Source/cmQtAutoGeneratorMocUic.h | 17 | ||||
-rw-r--r-- | Source/cmQtAutoGeneratorRcc.cxx | 666 | ||||
-rw-r--r-- | Source/cmQtAutoRcc.cxx | 516 | ||||
-rw-r--r-- | Source/cmQtAutoRcc.h (renamed from Source/cmQtAutoGeneratorRcc.h) | 71 | ||||
-rw-r--r-- | Source/cmcmd.cxx | 4 |
13 files changed, 878 insertions, 1031 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 52f6742..3a12120 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -350,8 +350,8 @@ set(SRCS cmQtAutoGenInitializer.h cmQtAutoGeneratorMocUic.cxx cmQtAutoGeneratorMocUic.h - cmQtAutoGeneratorRcc.cxx - cmQtAutoGeneratorRcc.h + cmQtAutoRcc.cxx + cmQtAutoRcc.h cmRST.cxx cmRST.h cmScriptGenerator.h diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index d71d82f..9918c35 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -1,9 +1,12 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGen.h" + #include "cmAlgorithms.h" +#include "cmDuration.h" +#include "cmProcessOutput.h" #include "cmSystemTools.h" - +#include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" #include <algorithm> @@ -237,8 +240,8 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts, MergeOptions(baseOpts, newOpts, valueOpts, isQt5); } -void cmQtAutoGen::RccListParseContent(std::string const& content, - std::vector<std::string>& files) +static void RccListParseContent(std::string const& content, + std::vector<std::string>& files) { cmsys::RegularExpression fileMatchRegex("(<file[^<]+)"); cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)"); @@ -255,10 +258,10 @@ void cmQtAutoGen::RccListParseContent(std::string const& content, } } -bool cmQtAutoGen::RccListParseOutput(std::string const& rccStdOut, - std::string const& rccStdErr, - std::vector<std::string>& files, - std::string& error) +static bool RccListParseOutput(std::string const& rccStdOut, + std::string const& rccStdErr, + std::vector<std::string>& files, + std::string& error) { // Lambda to strip CR characters auto StripCR = [](std::string& line) { @@ -305,11 +308,104 @@ bool cmQtAutoGen::RccListParseOutput(std::string const& rccStdOut, return true; } -void cmQtAutoGen::RccListConvertFullPath(std::string const& qrcFileDir, - std::vector<std::string>& files) +cmQtAutoGen::RccLister::RccLister() = default; + +cmQtAutoGen::RccLister::RccLister(std::string rccExecutable, + std::vector<std::string> listOptions) + : RccExcutable_(std::move(rccExecutable)) + , ListOptions_(std::move(listOptions)) +{ +} + +bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, + std::vector<std::string>& files, + std::string& error, bool verbose) const { + error.clear(); + + if (!cmSystemTools::FileExists(qrcFile, true)) { + error = "The resource file "; + error += Quoted(qrcFile); + error += " does not exist."; + return false; + } + + // Run rcc list command in the directory of the qrc file with the pathless + // qrc file name argument. This way rcc prints relative paths. + // This avoids issues on Windows when the qrc file is in a path that + // contains non-ASCII characters. + std::string const fileDir = cmSystemTools::GetFilenamePath(qrcFile); + + if (!this->RccExcutable_.empty() && + cmSystemTools::FileExists(this->RccExcutable_, true) && + !this->ListOptions_.empty()) { + + bool result = false; + int retVal = 0; + std::string rccStdOut; + std::string rccStdErr; + { + std::vector<std::string> cmd; + cmd.emplace_back(this->RccExcutable_); + cmd.insert(cmd.end(), this->ListOptions_.begin(), + this->ListOptions_.end()); + cmd.emplace_back(cmSystemTools::GetFilenameName(qrcFile)); + + // Log command + if (verbose) { + std::string msg = "Running command:\n"; + msg += QuotedCommand(cmd); + msg += '\n'; + cmSystemTools::Stdout(msg); + } + + result = cmSystemTools::RunSingleCommand( + cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(), + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); + } + if (!result || retVal) { + error = "The rcc list process failed for "; + error += Quoted(qrcFile); + error += "\n"; + if (!rccStdOut.empty()) { + error += rccStdOut; + error += "\n"; + } + if (!rccStdErr.empty()) { + error += rccStdErr; + error += "\n"; + } + return false; + } + if (!RccListParseOutput(rccStdOut, rccStdErr, files, error)) { + return false; + } + } else { + // We can't use rcc for the file listing. + // Read the qrc file content into string and parse it. + { + std::string qrcContents; + { + cmsys::ifstream ifs(qrcFile.c_str()); + if (ifs) { + std::ostringstream osst; + osst << ifs.rdbuf(); + qrcContents = osst.str(); + } else { + error = "The resource file "; + error += Quoted(qrcFile); + error += " is not readable\n"; + return false; + } + } + // Parse string content + RccListParseContent(qrcContents, files); + } + } + + // Convert relative paths to absolute paths for (std::string& entry : files) { - std::string tmp = cmSystemTools::CollapseFullPath(entry, qrcFileDir); - entry = std::move(tmp); + entry = cmSystemTools::CollapseFullPath(entry, fileDir); } + return true; } diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index d127a71..3a346b5 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -85,21 +85,44 @@ public: std::vector<std::string> const& newOpts, bool isQt5); - /// @brief Parses the content of a qrc file - /// - /// Use when rcc does not support the "--list" option - static void RccListParseContent(std::string const& content, - std::vector<std::string>& files); - - /// @brief Parses the output of the "rcc --list ..." command - static bool RccListParseOutput(std::string const& rccStdOut, - std::string const& rccStdErr, - std::vector<std::string>& files, - std::string& error); - - /// @brief Converts relative qrc entry paths to full paths - static void RccListConvertFullPath(std::string const& qrcFileDir, - std::vector<std::string>& files); + /** @class RccLister + * @brief Lists files in qrc resource files + */ + class RccLister + { + public: + RccLister(); + RccLister(std::string rccExecutable, std::vector<std::string> listOptions); + + //! The rcc executable + std::string const& RccExcutable() const { return RccExcutable_; } + void SetRccExecutable(std::string const& rccExecutable) + { + RccExcutable_ = rccExecutable; + } + + //! The rcc executable list options + std::vector<std::string> const& ListOptions() const + { + return ListOptions_; + } + void SetListOptions(std::vector<std::string> const& listOptions) + { + ListOptions_ = listOptions; + } + + /** + * @brief Lists a files in the qrcFile + * @arg files The file names are appended to this list + * @arg error contains the error message when the function fails + */ + bool list(std::string const& qrcFile, std::vector<std::string>& files, + std::string& error, bool verbose = false) const; + + private: + std::string RccExcutable_; + std::vector<std::string> ListOptions_; + }; }; #endif diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index d80aaa2..be96f1a 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -7,7 +7,6 @@ #include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" -#include "cmDuration.h" #include "cmFilePathChecksum.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -19,7 +18,6 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProcessOutput.h" #include "cmSourceFile.h" #include "cmSourceFileLocationKind.h" #include "cmSourceGroup.h" @@ -28,7 +26,6 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" -#include "cmsys/FStream.hxx" #include "cmsys/SystemInformation.hxx" #include <algorithm> @@ -36,7 +33,6 @@ #include <deque> #include <map> #include <set> -#include <sstream> #include <string> #include <utility> #include <vector> @@ -935,7 +931,8 @@ bool cmQtAutoGenInitializer::InitScanFiles() for (Qrc& qrc : this->Rcc.Qrcs) { if (!qrc.Generated) { std::string error; - if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) { + RccLister const lister(this->Rcc.Executable, this->Rcc.ListOptions); + if (!lister.list(qrc.QrcFile, qrc.Resources, error)) { cmSystemTools::Error(error); return false; } @@ -1630,86 +1627,3 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, 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 -bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName, - std::vector<std::string>& files, - std::string& error) -{ - if (!cmSystemTools::FileExists(fileName)) { - error = "rcc resource file does not exist:\n "; - error += Quoted(fileName); - error += "\n"; - return false; - } - if (this->Rcc.ExecutableExists && !this->Rcc.ListOptions.empty()) { - // Use rcc for file listing - if (this->Rcc.Executable.empty()) { - error = "rcc executable not available"; - return false; - } - - // Run rcc list command in the directory of the qrc file with the - // pathless - // qrc file name argument. This way rcc prints relative paths. - // This avoids issues on Windows when the qrc file is in a path that - // contains non-ASCII characters. - std::string const fileDir = cmSystemTools::GetFilenamePath(fileName); - std::string const fileNameName = cmSystemTools::GetFilenameName(fileName); - - bool result = false; - int retVal = 0; - std::string rccStdOut; - std::string rccStdErr; - { - std::vector<std::string> cmd; - cmd.push_back(this->Rcc.Executable); - cmd.insert(cmd.end(), this->Rcc.ListOptions.begin(), - this->Rcc.ListOptions.end()); - cmd.push_back(fileNameName); - result = cmSystemTools::RunSingleCommand( - cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(), - cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); - } - if (!result || retVal) { - error = "rcc list process failed for:\n "; - error += Quoted(fileName); - error += "\n"; - error += rccStdOut; - error += "\n"; - error += rccStdErr; - error += "\n"; - return false; - } - if (!RccListParseOutput(rccStdOut, rccStdErr, files, error)) { - return false; - } - } else { - // We can't use rcc for the file listing. - // Read the qrc file content into string and parse it. - { - std::string qrcContents; - { - cmsys::ifstream ifs(fileName.c_str()); - if (ifs) { - std::ostringstream osst; - osst << ifs.rdbuf(); - qrcContents = osst.str(); - } else { - error = "rcc file not readable:\n "; - error += Quoted(fileName); - error += "\n"; - return false; - } - } - // Parse string content - RccListParseContent(qrcContents, files); - } - } - - // Convert relative paths to absolute paths - RccListConvertFullPath(cmSystemTools::GetFilenamePath(fileName), files); - return true; -} diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index e7e5db2..7ff33c3 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -149,10 +149,6 @@ private: 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); - private: cmQtAutoGenGlobalInitializer* GlobalInitializer; cmGeneratorTarget* Target; diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 27afe48..f115016 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -20,6 +20,34 @@ // -- Class methods +cmQtAutoGenerator::Logger::Logger() +{ + // Initialize logger + { + std::string verbose; + if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) { + unsigned long iVerbose = 0; + if (cmSystemTools::StringToULong(verbose.c_str(), &iVerbose)) { + SetVerbosity(static_cast<unsigned int>(iVerbose)); + } else { + // Non numeric verbosity + SetVerbose(cmSystemTools::IsOn(verbose)); + } + } + } + { + std::string colorEnv; + cmSystemTools::GetEnv("COLOR", colorEnv); + if (!colorEnv.empty()) { + SetColorOutput(cmSystemTools::IsOn(colorEnv)); + } else { + SetColorOutput(true); + } + } +} + +cmQtAutoGenerator::Logger::~Logger() = default; + void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value) { unsigned long verbosity = 0; @@ -152,6 +180,91 @@ void cmQtAutoGenerator::Logger::ErrorCommand( } } +bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename) +{ + bool success = true; + std::string const dirName = cmSystemTools::GetFilenamePath(filename); + if (!dirName.empty()) { + success = cmSystemTools::MakeDirectory(dirName); + } + return success; +} + +bool cmQtAutoGenerator::FileRead(std::string& content, + std::string const& filename, + std::string* error) +{ + content.clear(); + if (!cmSystemTools::FileExists(filename, true)) { + if (error != nullptr) { + error->append("Not a file."); + } + return false; + } + + unsigned long const length = cmSystemTools::FileLength(filename); + cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); + + // Use lambda to save destructor calls of ifs + return [&ifs, length, &content, error]() -> bool { + if (!ifs) { + if (error != nullptr) { + error->append("Opening the file for reading failed."); + } + return false; + } + content.reserve(length); + typedef std::istreambuf_iterator<char> IsIt; + content.assign(IsIt{ ifs }, IsIt{}); + if (!ifs) { + content.clear(); + if (error != nullptr) { + error->append("Reading from the file failed."); + } + return false; + } + return true; + }(); +} + +bool cmQtAutoGenerator::FileWrite(std::string const& filename, + std::string const& content, + std::string* error) +{ + // Make sure the parent directory exists + if (!cmQtAutoGenerator::MakeParentDirectory(filename)) { + if (error != nullptr) { + error->assign("Could not create parent directory."); + } + return false; + } + cmsys::ofstream ofs; + ofs.open(filename.c_str(), + (std::ios::out | std::ios::binary | std::ios::trunc)); + + // Use lambda to save destructor calls of ofs + return [&ofs, &content, error]() -> bool { + if (!ofs) { + if (error != nullptr) { + error->assign("Opening file for writing failed."); + } + return false; + } + ofs << content; + if (!ofs.good()) { + if (error != nullptr) { + error->assign("File writing failed."); + } + return false; + } + return true; + }(); +} + +cmQtAutoGenerator::FileSystem::FileSystem() = default; + +cmQtAutoGenerator::FileSystem::~FileSystem() = default; + std::string cmQtAutoGenerator::FileSystem::GetRealPath( std::string const& filename) { @@ -267,91 +380,16 @@ bool cmQtAutoGenerator::FileSystem::FileRead(std::string& content, std::string const& filename, std::string* error) { - bool success = false; - if (FileExists(filename, true)) { - unsigned long const length = FileLength(filename); - { - std::lock_guard<std::mutex> lock(Mutex_); - cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); - if (ifs) { - content.reserve(length); - content.assign(std::istreambuf_iterator<char>{ ifs }, - std::istreambuf_iterator<char>{}); - if (ifs) { - success = true; - } else { - content.clear(); - if (error != nullptr) { - error->append("Reading from the file failed."); - } - } - } else if (error != nullptr) { - error->append("Opening the file for reading failed."); - } - } - } else if (error != nullptr) { - error->append( - "The file does not exist, is not readable or is a directory."); - } - return success; -} - -bool cmQtAutoGenerator::FileSystem::FileRead(GenT genType, - std::string& content, - std::string const& filename) -{ - std::string error; - if (!FileRead(content, filename, &error)) { - Log()->ErrorFile(genType, filename, error); - return false; - } - return true; + std::lock_guard<std::mutex> lock(Mutex_); + return cmQtAutoGenerator::FileRead(content, filename, error); } bool cmQtAutoGenerator::FileSystem::FileWrite(std::string const& filename, std::string const& content, std::string* error) { - bool success = false; - // Make sure the parent directory exists - if (MakeParentDirectory(filename)) { - std::lock_guard<std::mutex> lock(Mutex_); - cmsys::ofstream outfile; - outfile.open(filename.c_str(), - (std::ios::out | std::ios::binary | std::ios::trunc)); - if (outfile) { - outfile << content; - // Check for write errors - if (outfile.good()) { - success = true; - } else { - if (error != nullptr) { - error->assign("File writing failed"); - } - } - } else { - if (error != nullptr) { - error->assign("Opening file for writing failed"); - } - } - } else { - if (error != nullptr) { - error->assign("Could not create parent directory"); - } - } - return success; -} - -bool cmQtAutoGenerator::FileSystem::FileWrite(GenT genType, - std::string const& filename, - std::string const& content) -{ - std::string error; - if (!FileWrite(filename, content, &error)) { - Log()->ErrorFile(genType, filename, error); - return false; - } - return true; + std::lock_guard<std::mutex> lock(Mutex_); + return cmQtAutoGenerator::FileWrite(filename, content, error); } bool cmQtAutoGenerator::FileSystem::FileDiffers(std::string const& filename, @@ -386,35 +424,11 @@ bool cmQtAutoGenerator::FileSystem::MakeDirectory(std::string const& dirname) return cmSystemTools::MakeDirectory(dirname); } -bool cmQtAutoGenerator::FileSystem::MakeDirectory(GenT genType, - std::string const& dirname) -{ - if (!MakeDirectory(dirname)) { - Log()->ErrorFile(genType, dirname, "Could not create directory"); - return false; - } - return true; -} - bool cmQtAutoGenerator::FileSystem::MakeParentDirectory( std::string const& filename) { - bool success = true; - std::string const dirName = cmSystemTools::GetFilenamePath(filename); - if (!dirName.empty()) { - success = MakeDirectory(dirName); - } - return success; -} - -bool cmQtAutoGenerator::FileSystem::MakeParentDirectory( - GenT genType, std::string const& filename) -{ - if (!MakeParentDirectory(filename)) { - Log()->ErrorFile(genType, filename, "Could not create parent directory"); - return false; - } - return true; + std::lock_guard<std::mutex> lock(Mutex_); + return cmQtAutoGenerator::MakeParentDirectory(filename); } int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::init(uv_loop_t* uv_loop, @@ -643,46 +657,9 @@ void cmQtAutoGenerator::ReadOnlyProcessT::UVTryFinish() } } -cmQtAutoGenerator::cmQtAutoGenerator() - : FileSys_(&Logger_) -{ - // Initialize logger - { - std::string verbose; - if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) { - unsigned long iVerbose = 0; - if (cmSystemTools::StringToULong(verbose.c_str(), &iVerbose)) { - Logger_.SetVerbosity(static_cast<unsigned int>(iVerbose)); - } else { - // Non numeric verbosity - Logger_.SetVerbose(cmSystemTools::IsOn(verbose)); - } - } - } - { - std::string colorEnv; - cmSystemTools::GetEnv("COLOR", colorEnv); - if (!colorEnv.empty()) { - Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv)); - } else { - Logger_.SetColorOutput(true); - } - } +cmQtAutoGenerator::cmQtAutoGenerator() = default; - // Initialize libuv loop - uv_disable_stdio_inheritance(); -#ifdef CMAKE_UV_SIGNAL_HACK - UVHackRAII_ = cm::make_unique<cmUVSignalHackRAII>(); -#endif - UVLoop_ = cm::make_unique<uv_loop_t>(); - uv_loop_init(UVLoop()); -} - -cmQtAutoGenerator::~cmQtAutoGenerator() -{ - // Close libuv loop - uv_loop_close(UVLoop()); -} +cmQtAutoGenerator::~cmQtAutoGenerator() = default; bool cmQtAutoGenerator::Run(std::string const& infoFile, std::string const& config) diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index b55bebc..479d357 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -8,7 +8,6 @@ #include "cmFilePathChecksum.h" #include "cmQtAutoGen.h" #include "cmUVHandlePtr.h" -#include "cmUVSignalHackRAII.h" // IWYU pragma: keep #include "cm_uv.h" #include <array> @@ -31,12 +30,16 @@ public: class Logger { public: + // -- Construction + Logger(); + ~Logger(); // -- Verbosity unsigned int Verbosity() const { return this->Verbosity_; } void SetVerbosity(unsigned int value) { this->Verbosity_ = value; } void RaiseVerbosity(std::string const& value); bool Verbose() const { return (this->Verbosity_ != 0); } void SetVerbose(bool value) { this->Verbosity_ = value ? 1 : 0; } + // -- Color output bool ColorOutput() const { return this->ColorOutput_; } void SetColorOutput(bool value); // -- Log info @@ -62,17 +65,20 @@ public: bool ColorOutput_ = false; }; + // -- File system methods + static bool MakeParentDirectory(std::string const& filename); + static bool FileRead(std::string& content, std::string const& filename, + std::string* error = nullptr); + static bool FileWrite(std::string const& filename, + std::string const& content, + std::string* error = nullptr); + /// @brief Thread safe file system interface class FileSystem { public: - FileSystem(Logger* log) - : Log_(log) - { - } - - /// @brief Logger - Logger* Log() const { return Log_; } + FileSystem(); + ~FileSystem(); // -- Paths /// @brief Wrapper for cmSystemTools::GetRealPath @@ -113,15 +119,9 @@ public: bool FileRead(std::string& content, std::string const& filename, std::string* error = nullptr); - /// @brief Error logging version - bool FileRead(GenT genType, std::string& content, - std::string const& filename); bool FileWrite(std::string const& filename, std::string const& content, std::string* error = nullptr); - /// @brief Error logging version - bool FileWrite(GenT genType, std::string const& filename, - std::string const& content); bool FileDiffers(std::string const& filename, std::string const& content); @@ -130,17 +130,11 @@ public: // -- Directory access bool MakeDirectory(std::string const& dirname); - /// @brief Error logging version - bool MakeDirectory(GenT genType, std::string const& dirname); - bool MakeParentDirectory(std::string const& filename); - /// @brief Error logging version - bool MakeParentDirectory(GenT genType, std::string const& filename); private: std::mutex Mutex_; cmFilePathChecksum FilePathChecksum_; - Logger* Log_; }; /// @brief Return value and output of an external process @@ -250,18 +244,10 @@ public: // -- Run bool Run(std::string const& infoFile, std::string const& config); - // -- Accessors - // Logging - Logger& Log() { return Logger_; } - // File System - FileSystem& FileSys() { return FileSys_; } // InfoFile std::string const& InfoFile() const { return InfoFile_; } std::string const& InfoDir() const { return InfoDir_; } std::string const& InfoConfig() const { return InfoConfig_; } - // libuv loop - uv_loop_t* UVLoop() { return UVLoop_.get(); } - cm::uv_async_ptr& UVRequest() { return UVRequest_; } // -- Utility static std::string SettingsFind(std::string const& content, const char* key); @@ -272,19 +258,10 @@ protected: virtual bool Process() = 0; private: - // -- Logging - Logger Logger_; - FileSystem FileSys_; // -- Info settings std::string InfoFile_; std::string InfoDir_; std::string InfoConfig_; -// -- libuv loop -#ifdef CMAKE_UV_SIGNAL_HACK - std::unique_ptr<cmUVSignalHackRAII> UVHackRAII_; -#endif - std::unique_ptr<uv_loop_t> UVLoop_; - cm::uv_async_ptr UVRequest_; }; #endif diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index 0982473..ec1a1aa 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -638,13 +638,15 @@ void cmQtAutoGeneratorMocUic::JobMocPredefsT::Process(WorkerT& wrk) if (!result.error()) { if (!fileExists || wrk.FileSys().FileDiffers(wrk.Moc().PredefsFileAbs, result.StdOut)) { - if (wrk.FileSys().FileWrite(GenT::MOC, wrk.Moc().PredefsFileAbs, - result.StdOut)) { + std::string error; + if (wrk.FileSys().FileWrite(wrk.Moc().PredefsFileAbs, result.StdOut, + &error)) { // Success } else { std::string emsg = "Writing "; emsg += Quoted(wrk.Moc().PredefsFileRel); - emsg += " failed."; + emsg += " failed. "; + emsg += error; wrk.LogFileError(GenT::MOC, wrk.Moc().PredefsFileAbs, emsg); } } else { @@ -835,7 +837,12 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk) { // Make sure the parent directory exists - if (wrk.FileSys().MakeParentDirectory(GenT::MOC, BuildFile)) { + if (!wrk.FileSys().MakeParentDirectory(BuildFile)) { + wrk.LogFileError(GenT::MOC, BuildFile, + "Could not create parent directory."); + return; + } + { // Compose moc command std::vector<std::string> cmd; cmd.push_back(wrk.Moc().Executable); @@ -950,7 +957,12 @@ bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk) void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk) { // Make sure the parent directory exists - if (wrk.FileSys().MakeParentDirectory(GenT::UIC, BuildFile)) { + if (!wrk.FileSys().MakeParentDirectory(BuildFile)) { + wrk.LogFileError(GenT::UIC, BuildFile, + "Could not create parent directory."); + return; + } + { // Compose uic command std::vector<std::string> cmd; cmd.push_back(wrk.Uic().Executable); @@ -1136,11 +1148,23 @@ cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic() Uic_.RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+" "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); + // Initialize libuv loop + uv_disable_stdio_inheritance(); +#ifdef CMAKE_UV_SIGNAL_HACK + UVHackRAII_ = cm::make_unique<cmUVSignalHackRAII>(); +#endif + UVLoop_ = cm::make_unique<uv_loop_t>(); + uv_loop_init(UVLoop()); + // Initialize libuv asynchronous iteration request UVRequest().init(*UVLoop(), &cmQtAutoGeneratorMocUic::UVPollStage, this); } -cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic() = default; +cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic() +{ + // Close libuv loop + uv_loop_close(UVLoop()); +} bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) { @@ -1691,9 +1715,10 @@ void cmQtAutoGeneratorMocUic::SettingsFileWrite() SettingAppend("uic", SettingsStringUic_); } // Write settings file - if (!FileSys().FileWrite(GenT::GEN, SettingsFile_, content)) { + std::string error; + if (!FileSys().FileWrite(SettingsFile_, content, &error)) { Log().ErrorFile(GenT::GEN, SettingsFile_, - "Settings file writing failed"); + "Settings file writing failed. " + error); // Remove old settings file to trigger a full rebuild on the next run FileSys().FileRemove(SettingsFile_); RegisterJobError(); @@ -1704,7 +1729,9 @@ void cmQtAutoGeneratorMocUic::SettingsFileWrite() void cmQtAutoGeneratorMocUic::CreateDirectories() { // Create AUTOGEN include directory - if (!FileSys().MakeDirectory(GenT::GEN, Base().AutogenIncludeDir)) { + if (!FileSys().MakeDirectory(Base().AutogenIncludeDir)) { + Log().ErrorFile(GenT::GEN, Base().AutogenIncludeDir, + "Could not create directory."); RegisterJobError(); } } @@ -2003,9 +2030,10 @@ void cmQtAutoGeneratorMocUic::MocGenerateCompilation() if (Log().Verbose()) { Log().Info(GenT::MOC, "Generating MOC compilation " + compAbs); } - if (!FileSys().FileWrite(GenT::MOC, compAbs, content)) { + std::string error; + if (!FileSys().FileWrite(compAbs, content, &error)) { Log().ErrorFile(GenT::MOC, compAbs, - "mocs compilation file writing failed"); + "mocs compilation file writing failed. " + error); RegisterJobError(); return; } diff --git a/Source/cmQtAutoGeneratorMocUic.h b/Source/cmQtAutoGeneratorMocUic.h index e48d7f3..27d73a7 100644 --- a/Source/cmQtAutoGeneratorMocUic.h +++ b/Source/cmQtAutoGeneratorMocUic.h @@ -8,6 +8,7 @@ #include "cmQtAutoGen.h" #include "cmQtAutoGenerator.h" #include "cmUVHandlePtr.h" +#include "cmUVSignalHackRAII.h" // IWYU pragma: keep #include "cm_uv.h" #include "cmsys/RegularExpression.hxx" @@ -387,6 +388,12 @@ public: void ParallelMocAutoUpdated(); private: + // -- Utility accessors + Logger& Log() { return Logger_; } + FileSystem& FileSys() { return FileSys_; } + // -- libuv loop accessors + uv_loop_t* UVLoop() { return UVLoop_.get(); } + cm::uv_async_ptr& UVRequest() { return UVRequest_; } // -- Abstract processing interface bool Init(cmMakefile* makefile) override; bool Process() override; @@ -407,11 +414,19 @@ private: void MocGenerateCompilation(); private: + // -- Utility + Logger Logger_; + FileSystem FileSys_; // -- Settings BaseSettingsT Base_; MocSettingsT Moc_; UicSettingsT Uic_; - // -- Progress + // -- libuv loop +#ifdef CMAKE_UV_SIGNAL_HACK + std::unique_ptr<cmUVSignalHackRAII> UVHackRAII_; +#endif + std::unique_ptr<uv_loop_t> UVLoop_; + cm::uv_async_ptr UVRequest_; StageT Stage_ = StageT::SETTINGS_READ; // -- Job queues std::mutex JobsMutex_; diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx deleted file mode 100644 index 5deb532..0000000 --- a/Source/cmQtAutoGeneratorRcc.cxx +++ /dev/null @@ -1,666 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmQtAutoGeneratorRcc.h" -#include "cmQtAutoGen.h" - -#include "cmAlgorithms.h" -#include "cmCryptoHash.h" -#include "cmFileLockResult.h" -#include "cmMakefile.h" -#include "cmSystemTools.h" -#include "cmUVHandlePtr.h" - -// -- Class methods - -cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc() -{ - // Initialize libuv asynchronous iteration request - UVRequest().init(*UVLoop(), &cmQtAutoGeneratorRcc::UVPollStage, this); -} - -cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc() = default; - -bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) -{ - // -- Utility lambdas - auto InfoGet = [makefile](std::string const& key) { - return makefile->GetSafeDefinition(key); - }; - auto InfoGetList = - [makefile](std::string const& key) -> std::vector<std::string> { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); - return list; - }; - auto InfoGetConfig = [makefile, - this](std::string const& key) -> std::string { - const char* valueConf = nullptr; - { - std::string keyConf = key; - keyConf += '_'; - keyConf += InfoConfig(); - valueConf = makefile->GetDefinition(keyConf); - } - if (valueConf == nullptr) { - return makefile->GetSafeDefinition(key); - } - return std::string(valueConf); - }; - auto InfoGetConfigList = - [&InfoGetConfig](std::string const& key) -> std::vector<std::string> { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(InfoGetConfig(key), list); - return list; - }; - - // -- Read info file - if (!makefile->ReadListFile(InfoFile())) { - Log().ErrorFile(GenT::RCC, InfoFile(), "File processing failed"); - return false; - } - - // - Configurations - Log().RaiseVerbosity(InfoGet("ARCC_VERBOSITY")); - MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG"); - - // - Directories - AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR"); - if (AutogenBuildDir_.empty()) { - Log().ErrorFile(GenT::RCC, InfoFile(), "Build directory empty"); - return false; - } - - IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR"); - if (IncludeDir_.empty()) { - Log().ErrorFile(GenT::RCC, InfoFile(), "Include directory empty"); - return false; - } - - // - Rcc executable - RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE"); - RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS"); - - // - Job - LockFile_ = InfoGet("ARCC_LOCK_FILE"); - QrcFile_ = InfoGet("ARCC_SOURCE"); - QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_); - QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_); - RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM"); - RccFileName_ = InfoGet("ARCC_OUTPUT_NAME"); - Options_ = InfoGetConfigList("ARCC_OPTIONS"); - Inputs_ = InfoGetList("ARCC_INPUTS"); - - // - Settings file - SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE"); - - // - Validity checks - if (LockFile_.empty()) { - Log().ErrorFile(GenT::RCC, InfoFile(), "Lock file name missing"); - return false; - } - if (SettingsFile_.empty()) { - Log().ErrorFile(GenT::RCC, InfoFile(), "Settings file name missing"); - return false; - } - if (AutogenBuildDir_.empty()) { - Log().ErrorFile(GenT::RCC, InfoFile(), "Autogen build directory missing"); - return false; - } - if (RccExecutable_.empty()) { - Log().ErrorFile(GenT::RCC, InfoFile(), "rcc executable missing"); - return false; - } - if (QrcFile_.empty()) { - Log().ErrorFile(GenT::RCC, InfoFile(), "rcc input file missing"); - return false; - } - if (RccFileName_.empty()) { - Log().ErrorFile(GenT::RCC, InfoFile(), "rcc output file missing"); - return false; - } - - // Init derived information - // ------------------------ - - RccFilePublic_ = AutogenBuildDir_; - RccFilePublic_ += '/'; - RccFilePublic_ += RccPathChecksum_; - RccFilePublic_ += '/'; - RccFilePublic_ += RccFileName_; - - // Compute rcc output file name - if (IsMultiConfig()) { - RccFileOutput_ = IncludeDir_; - RccFileOutput_ += '/'; - RccFileOutput_ += MultiConfigOutput(); - } else { - RccFileOutput_ = RccFilePublic_; - } - - return true; -} - -bool cmQtAutoGeneratorRcc::Process() -{ - // Run libuv event loop - UVRequest().send(); - if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) { - if (Error_) { - return false; - } - } else { - return false; - } - return true; -} - -void cmQtAutoGeneratorRcc::UVPollStage(uv_async_t* handle) -{ - reinterpret_cast<cmQtAutoGeneratorRcc*>(handle->data)->PollStage(); -} - -void cmQtAutoGeneratorRcc::PollStage() -{ - switch (Stage_) { - // -- Initialize - case StageT::SETTINGS_READ: - if (SettingsFileRead()) { - SetStage(StageT::TEST_QRC_RCC_FILES); - } else { - SetStage(StageT::FINISH); - } - break; - - // -- Change detection - case StageT::TEST_QRC_RCC_FILES: - if (TestQrcRccFiles()) { - SetStage(StageT::GENERATE); - } else { - SetStage(StageT::TEST_RESOURCES_READ); - } - break; - case StageT::TEST_RESOURCES_READ: - if (TestResourcesRead()) { - SetStage(StageT::TEST_RESOURCES); - } - break; - case StageT::TEST_RESOURCES: - if (TestResources()) { - SetStage(StageT::GENERATE); - } else { - SetStage(StageT::TEST_INFO_FILE); - } - break; - case StageT::TEST_INFO_FILE: - TestInfoFile(); - SetStage(StageT::GENERATE_WRAPPER); - break; - - // -- Generation - case StageT::GENERATE: - GenerateParentDir(); - SetStage(StageT::GENERATE_RCC); - break; - case StageT::GENERATE_RCC: - if (GenerateRcc()) { - SetStage(StageT::GENERATE_WRAPPER); - } - break; - case StageT::GENERATE_WRAPPER: - GenerateWrapper(); - SetStage(StageT::SETTINGS_WRITE); - break; - - // -- Finalize - case StageT::SETTINGS_WRITE: - SettingsFileWrite(); - SetStage(StageT::FINISH); - break; - case StageT::FINISH: - // Clear all libuv handles - UVRequest().reset(); - // Set highest END stage manually - Stage_ = StageT::END; - break; - case StageT::END: - break; - } -} - -void cmQtAutoGeneratorRcc::SetStage(StageT stage) -{ - if (Error_) { - stage = StageT::FINISH; - } - // Only allow to increase the stage - if (Stage_ < stage) { - Stage_ = stage; - UVRequest().send(); - } -} - -std::string cmQtAutoGeneratorRcc::MultiConfigOutput() const -{ - static std::string const suffix = "_CMAKE_"; - std::string res; - res += RccPathChecksum_; - res += '/'; - res += AppendFilenameSuffix(RccFileName_, suffix); - return res; -} - -bool cmQtAutoGeneratorRcc::SettingsFileRead() -{ - // Compose current settings strings - { - cmCryptoHash crypt(cmCryptoHash::AlgoSHA256); - std::string const sep(" ~~~ "); - { - std::string str; - str += RccExecutable_; - str += sep; - str += cmJoin(RccListOptions_, ";"); - str += sep; - str += QrcFile_; - str += sep; - str += RccPathChecksum_; - str += sep; - str += RccFileName_; - str += sep; - str += cmJoin(Options_, ";"); - str += sep; - str += cmJoin(Inputs_, ";"); - str += sep; - SettingsString_ = crypt.HashString(str); - } - } - - // Make sure the settings file exists - if (!FileSys().FileExists(SettingsFile_, true)) { - // Touch the settings file to make sure it exists - FileSys().Touch(SettingsFile_, true); - } - - // Lock the lock file - { - // Make sure the lock file exists - if (!FileSys().FileExists(LockFile_, true)) { - if (!FileSys().Touch(LockFile_, true)) { - Log().ErrorFile(GenT::RCC, LockFile_, "Lock file creation failed"); - Error_ = true; - return false; - } - } - // Lock the lock file - cmFileLockResult lockResult = - LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1)); - if (!lockResult.IsOk()) { - Log().ErrorFile(GenT::RCC, LockFile_, - "File lock failed: " + lockResult.GetOutputMessage()); - Error_ = true; - return false; - } - } - - // Read old settings - { - std::string content; - if (FileSys().FileRead(content, SettingsFile_)) { - SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc")); - // In case any setting changed clear the old settings file. - // This triggers a full rebuild on the next run if the current - // build is aborted before writing the current settings in the end. - if (SettingsChanged_) { - FileSys().FileWrite(GenT::RCC, SettingsFile_, ""); - } - } else { - SettingsChanged_ = true; - } - } - - return true; -} - -void cmQtAutoGeneratorRcc::SettingsFileWrite() -{ - // Only write if any setting changed - if (SettingsChanged_) { - if (Log().Verbose()) { - Log().Info(GenT::RCC, "Writing settings file " + Quoted(SettingsFile_)); - } - // Write settings file - std::string content = "rcc:"; - content += SettingsString_; - content += '\n'; - if (!FileSys().FileWrite(GenT::RCC, SettingsFile_, content)) { - Log().ErrorFile(GenT::RCC, SettingsFile_, - "Settings file writing failed"); - // Remove old settings file to trigger a full rebuild on the next run - FileSys().FileRemove(SettingsFile_); - Error_ = true; - } - } - - // Unlock the lock file - LockFileLock_.Release(); -} - -bool cmQtAutoGeneratorRcc::TestQrcRccFiles() -{ - // Do basic checks if rcc generation is required - - // Test if the rcc output file exists - if (!FileSys().FileExists(RccFileOutput_)) { - if (Log().Verbose()) { - std::string reason = "Generating "; - reason += Quoted(RccFileOutput_); - reason += " from its source file "; - reason += Quoted(QrcFile_); - reason += " because it doesn't exist"; - Log().Info(GenT::RCC, reason); - } - Generate_ = true; - return Generate_; - } - - // Test if the settings changed - if (SettingsChanged_) { - if (Log().Verbose()) { - std::string reason = "Generating "; - reason += Quoted(RccFileOutput_); - reason += " from "; - reason += Quoted(QrcFile_); - reason += " because the RCC settings changed"; - Log().Info(GenT::RCC, reason); - } - Generate_ = true; - return Generate_; - } - - // Test if the rcc output file is older than the .qrc file - { - bool isOlder = false; - { - std::string error; - isOlder = FileSys().FileIsOlderThan(RccFileOutput_, QrcFile_, &error); - if (!error.empty()) { - Log().ErrorFile(GenT::RCC, QrcFile_, error); - Error_ = true; - } - } - if (isOlder) { - if (Log().Verbose()) { - std::string reason = "Generating "; - reason += Quoted(RccFileOutput_); - reason += " because it is older than "; - reason += Quoted(QrcFile_); - Log().Info(GenT::RCC, reason); - } - Generate_ = true; - } - } - - return Generate_; -} - -bool cmQtAutoGeneratorRcc::TestResourcesRead() -{ - if (!Inputs_.empty()) { - // Inputs are known already - return true; - } - - if (!RccListOptions_.empty()) { - // Start a rcc list process and parse the output - if (Process_) { - // Process is running already - if (Process_->IsFinished()) { - // Process is finished - if (!ProcessResult_.error()) { - // Process success - std::string parseError; - if (!RccListParseOutput(ProcessResult_.StdOut, ProcessResult_.StdErr, - Inputs_, parseError)) { - Log().ErrorFile(GenT::RCC, QrcFile_, parseError); - Error_ = true; - } - } else { - Log().ErrorFile(GenT::RCC, QrcFile_, ProcessResult_.ErrorMessage); - Error_ = true; - } - // Clean up - Process_.reset(); - ProcessResult_.reset(); - } else { - // Process is not finished, yet. - return false; - } - } else { - // Start a new process - // rcc prints relative entry paths when started in the directory of the - // qrc file with a pathless qrc file name argument. - // This is important because on Windows absolute paths returned by rcc - // might contain bad multibyte characters when the qrc file path - // contains non-ASCII pcharacters. - std::vector<std::string> cmd; - cmd.push_back(RccExecutable_); - cmd.insert(cmd.end(), RccListOptions_.begin(), RccListOptions_.end()); - cmd.push_back(QrcFileName_); - // We're done here if the process fails to start - return !StartProcess(QrcFileDir_, cmd, false); - } - } else { - // rcc does not support the --list command. - // Read the qrc file content and parse it. - std::string qrcContent; - if (FileSys().FileRead(GenT::RCC, qrcContent, QrcFile_)) { - RccListParseContent(qrcContent, Inputs_); - } - } - - if (!Inputs_.empty()) { - // Convert relative paths to absolute paths - RccListConvertFullPath(QrcFileDir_, Inputs_); - } - - return true; -} - -bool cmQtAutoGeneratorRcc::TestResources() -{ - if (Inputs_.empty()) { - return true; - } - { - std::string error; - for (std::string const& resFile : Inputs_) { - // Check if the resource file exists - if (!FileSys().FileExists(resFile)) { - error = "Could not find the resource file\n "; - error += Quoted(resFile); - error += '\n'; - Log().ErrorFile(GenT::RCC, QrcFile_, error); - Error_ = true; - break; - } - // Check if the resource file is newer than the build file - if (FileSys().FileIsOlderThan(RccFileOutput_, resFile, &error)) { - if (Log().Verbose()) { - std::string reason = "Generating "; - reason += Quoted(RccFileOutput_); - reason += " from "; - reason += Quoted(QrcFile_); - reason += " because it is older than "; - reason += Quoted(resFile); - Log().Info(GenT::RCC, reason); - } - Generate_ = true; - break; - } - // Print error and break on demand - if (!error.empty()) { - Log().ErrorFile(GenT::RCC, QrcFile_, error); - Error_ = true; - break; - } - } - } - - return Generate_; -} - -void cmQtAutoGeneratorRcc::TestInfoFile() -{ - // Test if the rcc output file is older than the info file - { - bool isOlder = false; - { - std::string error; - isOlder = FileSys().FileIsOlderThan(RccFileOutput_, InfoFile(), &error); - if (!error.empty()) { - Log().ErrorFile(GenT::RCC, QrcFile_, error); - Error_ = true; - } - } - if (isOlder) { - if (Log().Verbose()) { - std::string reason = "Touching "; - reason += Quoted(RccFileOutput_); - reason += " because it is older than "; - reason += Quoted(InfoFile()); - Log().Info(GenT::RCC, reason); - } - // Touch build file - FileSys().Touch(RccFileOutput_); - BuildFileChanged_ = true; - } - } -} - -void cmQtAutoGeneratorRcc::GenerateParentDir() -{ - // Make sure the parent directory exists - if (!FileSys().MakeParentDirectory(GenT::RCC, RccFileOutput_)) { - Error_ = true; - } -} - -/** - * @return True when finished - */ -bool cmQtAutoGeneratorRcc::GenerateRcc() -{ - if (!Generate_) { - // Nothing to do - return true; - } - - if (Process_) { - // Process is running already - if (Process_->IsFinished()) { - // Process is finished - if (!ProcessResult_.error()) { - // Rcc process success - // Print rcc output - if (!ProcessResult_.StdOut.empty()) { - Log().Info(GenT::RCC, ProcessResult_.StdOut); - } - BuildFileChanged_ = true; - } else { - // Rcc process failed - { - std::string emsg = "The rcc process failed to compile\n "; - emsg += Quoted(QrcFile_); - emsg += "\ninto\n "; - emsg += Quoted(RccFileOutput_); - if (ProcessResult_.error()) { - emsg += "\n"; - emsg += ProcessResult_.ErrorMessage; - } - Log().ErrorCommand(GenT::RCC, emsg, Process_->Setup().Command, - ProcessResult_.StdOut); - } - FileSys().FileRemove(RccFileOutput_); - Error_ = true; - } - // Clean up - Process_.reset(); - ProcessResult_.reset(); - } else { - // Process is not finished, yet. - return false; - } - } else { - // Start a rcc process - std::vector<std::string> cmd; - cmd.push_back(RccExecutable_); - cmd.insert(cmd.end(), Options_.begin(), Options_.end()); - cmd.emplace_back("-o"); - cmd.push_back(RccFileOutput_); - cmd.push_back(QrcFile_); - // We're done here if the process fails to start - return !StartProcess(AutogenBuildDir_, cmd, true); - } - - return true; -} - -void cmQtAutoGeneratorRcc::GenerateWrapper() -{ - // Generate a wrapper source file on demand - if (IsMultiConfig()) { - // Wrapper file content - std::string content; - content += "// This is an autogenerated configuration wrapper file.\n"; - content += "// Changes will be overwritten.\n"; - content += "#include <"; - content += MultiConfigOutput(); - content += ">\n"; - - // Write content to file - if (FileSys().FileDiffers(RccFilePublic_, content)) { - // Write new wrapper file - if (Log().Verbose()) { - Log().Info(GenT::RCC, "Generating RCC wrapper file " + RccFilePublic_); - } - if (!FileSys().FileWrite(GenT::RCC, RccFilePublic_, content)) { - Log().ErrorFile(GenT::RCC, RccFilePublic_, - "RCC wrapper file writing failed"); - Error_ = true; - } - } else if (BuildFileChanged_) { - // Just touch the wrapper file - if (Log().Verbose()) { - Log().Info(GenT::RCC, "Touching RCC wrapper file " + RccFilePublic_); - } - FileSys().Touch(RccFilePublic_); - } - } -} - -bool cmQtAutoGeneratorRcc::StartProcess( - std::string const& workingDirectory, std::vector<std::string> const& command, - bool mergedOutput) -{ - // Log command - if (Log().Verbose()) { - std::string msg = "Running command:\n"; - msg += QuotedCommand(command); - msg += '\n'; - Log().Info(GenT::RCC, msg); - } - - // Create process handler - Process_ = cm::make_unique<ReadOnlyProcessT>(); - Process_->setup(&ProcessResult_, mergedOutput, command, workingDirectory); - // Start process - if (!Process_->start(UVLoop(), [this] { UVRequest().send(); })) { - Log().ErrorFile(GenT::RCC, QrcFile_, ProcessResult_.ErrorMessage); - Error_ = true; - // Clean up - Process_.reset(); - ProcessResult_.reset(); - return false; - } - return true; -} diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx new file mode 100644 index 0000000..e58324d --- /dev/null +++ b/Source/cmQtAutoRcc.cxx @@ -0,0 +1,516 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoRcc.h" +#include "cmQtAutoGen.h" + +#include "cmAlgorithms.h" +#include "cmCryptoHash.h" +#include "cmDuration.h" +#include "cmFileLockResult.h" +#include "cmMakefile.h" +#include "cmProcessOutput.h" +#include "cmSystemTools.h" + +// -- Class methods + +cmQtAutoRcc::cmQtAutoRcc() = default; + +cmQtAutoRcc::~cmQtAutoRcc() = default; + +bool cmQtAutoRcc::Init(cmMakefile* makefile) +{ + // -- Utility lambdas + auto InfoGet = [makefile](std::string const& key) { + return makefile->GetSafeDefinition(key); + }; + auto InfoGetList = + [makefile](std::string const& key) -> std::vector<std::string> { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); + return list; + }; + auto InfoGetConfig = [makefile, + this](std::string const& key) -> std::string { + const char* valueConf = nullptr; + { + std::string keyConf = key; + keyConf += '_'; + keyConf += InfoConfig(); + valueConf = makefile->GetDefinition(keyConf); + } + if (valueConf == nullptr) { + return makefile->GetSafeDefinition(key); + } + return std::string(valueConf); + }; + auto InfoGetConfigList = + [&InfoGetConfig](std::string const& key) -> std::vector<std::string> { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(InfoGetConfig(key), list); + return list; + }; + + // -- Read info file + if (!makefile->ReadListFile(InfoFile())) { + Log().ErrorFile(GenT::RCC, InfoFile(), "File processing failed."); + return false; + } + + // - Configurations + Log().RaiseVerbosity(InfoGet("ARCC_VERBOSITY")); + MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG"); + + // - Directories + AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR"); + if (AutogenBuildDir_.empty()) { + Log().ErrorFile(GenT::RCC, InfoFile(), "Build directory empty."); + return false; + } + + IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR"); + if (IncludeDir_.empty()) { + Log().ErrorFile(GenT::RCC, InfoFile(), "Include directory empty."); + return false; + } + + // - Rcc executable + RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE"); + RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS"); + + // - Job + LockFile_ = InfoGet("ARCC_LOCK_FILE"); + QrcFile_ = InfoGet("ARCC_SOURCE"); + QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_); + QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_); + RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM"); + RccFileName_ = InfoGet("ARCC_OUTPUT_NAME"); + Options_ = InfoGetConfigList("ARCC_OPTIONS"); + Inputs_ = InfoGetList("ARCC_INPUTS"); + + // - Settings file + SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE"); + + // - Validity checks + if (LockFile_.empty()) { + Log().ErrorFile(GenT::RCC, InfoFile(), "Lock file name missing."); + return false; + } + if (SettingsFile_.empty()) { + Log().ErrorFile(GenT::RCC, InfoFile(), "Settings file name missing."); + return false; + } + if (AutogenBuildDir_.empty()) { + Log().ErrorFile(GenT::RCC, InfoFile(), "Autogen build directory missing."); + return false; + } + if (RccExecutable_.empty()) { + Log().ErrorFile(GenT::RCC, InfoFile(), "rcc executable missing."); + return false; + } + if (QrcFile_.empty()) { + Log().ErrorFile(GenT::RCC, InfoFile(), "rcc input file missing."); + return false; + } + if (RccFileName_.empty()) { + Log().ErrorFile(GenT::RCC, InfoFile(), "rcc output file missing."); + return false; + } + + // Init derived information + // ------------------------ + + RccFilePublic_ = AutogenBuildDir_; + RccFilePublic_ += '/'; + RccFilePublic_ += RccPathChecksum_; + RccFilePublic_ += '/'; + RccFilePublic_ += RccFileName_; + + // Compute rcc output file name + if (IsMultiConfig()) { + RccFileOutput_ = IncludeDir_; + RccFileOutput_ += '/'; + RccFileOutput_ += MultiConfigOutput(); + } else { + RccFileOutput_ = RccFilePublic_; + } + + return true; +} + +bool cmQtAutoRcc::Process() +{ + if (!SettingsFileRead()) { + return false; + } + + // Test if the rcc output needs to be regenerated + bool generate = false; + if (!TestQrcRccFiles(generate)) { + return false; + } + if (!generate && !TestResources(generate)) { + return false; + } + // Generate on demand + if (generate) { + if (!GenerateRcc()) { + return false; + } + } else { + // Test if the info file is newer than the output file + if (!TestInfoFile()) { + return false; + } + } + + if (!GenerateWrapper()) { + return false; + } + + return SettingsFileWrite(); +} + +std::string cmQtAutoRcc::MultiConfigOutput() const +{ + static std::string const suffix = "_CMAKE_"; + std::string res; + res += RccPathChecksum_; + res += '/'; + res += AppendFilenameSuffix(RccFileName_, suffix); + return res; +} + +bool cmQtAutoRcc::SettingsFileRead() +{ + // Compose current settings strings + { + cmCryptoHash crypt(cmCryptoHash::AlgoSHA256); + std::string const sep(" ~~~ "); + { + std::string str; + str += RccExecutable_; + str += sep; + str += cmJoin(RccListOptions_, ";"); + str += sep; + str += QrcFile_; + str += sep; + str += RccPathChecksum_; + str += sep; + str += RccFileName_; + str += sep; + str += cmJoin(Options_, ";"); + str += sep; + str += cmJoin(Inputs_, ";"); + str += sep; + SettingsString_ = crypt.HashString(str); + } + } + + // Make sure the settings file exists + if (!cmSystemTools::FileExists(SettingsFile_, true)) { + // Touch the settings file to make sure it exists + if (!cmSystemTools::Touch(SettingsFile_, true)) { + Log().ErrorFile(GenT::RCC, SettingsFile_, + "Settings file creation failed."); + return false; + } + } + + // Lock the lock file + { + // Make sure the lock file exists + if (!cmSystemTools::FileExists(LockFile_, true)) { + if (!cmSystemTools::Touch(LockFile_, true)) { + Log().ErrorFile(GenT::RCC, LockFile_, "Lock file creation failed."); + return false; + } + } + // Lock the lock file + cmFileLockResult lockResult = + LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1)); + if (!lockResult.IsOk()) { + Log().ErrorFile(GenT::RCC, LockFile_, + "File lock failed: " + lockResult.GetOutputMessage()); + return false; + } + } + + // Read old settings + { + std::string content; + if (FileRead(content, SettingsFile_)) { + SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc")); + // In case any setting changed clear the old settings file. + // This triggers a full rebuild on the next run if the current + // build is aborted before writing the current settings in the end. + if (SettingsChanged_) { + std::string error; + if (!FileWrite(SettingsFile_, "", &error)) { + Log().ErrorFile(GenT::RCC, SettingsFile_, + "Settings file clearing failed. " + error); + return false; + } + } + } else { + SettingsChanged_ = true; + } + } + + return true; +} + +bool cmQtAutoRcc::SettingsFileWrite() +{ + // Only write if any setting changed + if (SettingsChanged_) { + if (Log().Verbose()) { + Log().Info(GenT::RCC, "Writing settings file " + Quoted(SettingsFile_)); + } + // Write settings file + std::string content = "rcc:"; + content += SettingsString_; + content += '\n'; + std::string error; + if (!FileWrite(SettingsFile_, content, &error)) { + Log().ErrorFile(GenT::RCC, SettingsFile_, + "Settings file writing failed. " + error); + // Remove old settings file to trigger a full rebuild on the next run + cmSystemTools::RemoveFile(SettingsFile_); + return false; + } + } + + // Unlock the lock file + LockFileLock_.Release(); + return true; +} + +/// Do basic checks if rcc generation is required +bool cmQtAutoRcc::TestQrcRccFiles(bool& generate) +{ + // Test if the rcc input file exists + if (!QrcFileTime_.Load(QrcFile_)) { + std::string error; + error = "The resources file "; + error += Quoted(QrcFile_); + error += " does not exist"; + Log().ErrorFile(GenT::RCC, QrcFile_, error); + return false; + } + + // Test if the rcc output file exists + if (!RccFileTime_.Load(RccFileOutput_)) { + if (Log().Verbose()) { + std::string reason = "Generating "; + reason += Quoted(RccFileOutput_); + reason += " from its source file "; + reason += Quoted(QrcFile_); + reason += " because it doesn't exist"; + Log().Info(GenT::RCC, reason); + } + generate = true; + return true; + } + + // Test if the settings changed + if (SettingsChanged_) { + if (Log().Verbose()) { + std::string reason = "Generating "; + reason += Quoted(RccFileOutput_); + reason += " from "; + reason += Quoted(QrcFile_); + reason += " because the RCC settings changed"; + Log().Info(GenT::RCC, reason); + } + generate = true; + return true; + } + + // Test if the rcc output file is older than the .qrc file + if (RccFileTime_.Older(QrcFileTime_)) { + if (Log().Verbose()) { + std::string reason = "Generating "; + reason += Quoted(RccFileOutput_); + reason += " because it is older than "; + reason += Quoted(QrcFile_); + Log().Info(GenT::RCC, reason); + } + generate = true; + return true; + } + + return true; +} + +bool cmQtAutoRcc::TestResources(bool& generate) +{ + // Read resource files list + if (Inputs_.empty()) { + std::string error; + RccLister const lister(RccExecutable_, RccListOptions_); + if (!lister.list(QrcFile_, Inputs_, error, Log().Verbose())) { + Log().ErrorFile(GenT::RCC, QrcFile_, error); + return false; + } + } + + for (std::string const& resFile : Inputs_) { + // Check if the resource file exists + cmFileTime fileTime; + if (!fileTime.Load(resFile)) { + std::string error; + error = "Could not find the resource file\n "; + error += Quoted(resFile); + error += '\n'; + Log().ErrorFile(GenT::RCC, QrcFile_, error); + return false; + } + // Check if the resource file is newer than the build file + if (RccFileTime_.Older(fileTime)) { + if (Log().Verbose()) { + std::string reason = "Generating "; + reason += Quoted(RccFileOutput_); + reason += " from "; + reason += Quoted(QrcFile_); + reason += " because it is older than "; + reason += Quoted(resFile); + Log().Info(GenT::RCC, reason); + } + generate = true; + break; + } + } + return true; +} + +bool cmQtAutoRcc::TestInfoFile() +{ + // Test if the rcc output file is older than the info file + + cmFileTime infoFileTime; + if (!infoFileTime.Load(InfoFile())) { + std::string error; + error = "Could not find the info file "; + error += Quoted(InfoFile()); + error += '\n'; + Log().ErrorFile(GenT::RCC, QrcFile_, error); + return false; + } + if (RccFileTime_.Older(infoFileTime)) { + if (Log().Verbose()) { + std::string reason = "Touching "; + reason += Quoted(RccFileOutput_); + reason += " because it is older than "; + reason += Quoted(InfoFile()); + Log().Info(GenT::RCC, reason); + } + // Touch build file + if (!cmSystemTools::Touch(RccFileOutput_, false)) { + Log().ErrorFile(GenT::RCC, RccFileOutput_, "Build file touch failed"); + return false; + } + BuildFileChanged_ = true; + } + + return true; +} + +bool cmQtAutoRcc::GenerateRcc() +{ + // Make parent directory + if (!MakeParentDirectory(RccFileOutput_)) { + Log().ErrorFile(GenT::RCC, RccFileOutput_, + "Could not create parent directory"); + return false; + } + + // Start a rcc process + std::vector<std::string> cmd; + cmd.push_back(RccExecutable_); + cmd.insert(cmd.end(), Options_.begin(), Options_.end()); + cmd.emplace_back("-o"); + cmd.push_back(RccFileOutput_); + cmd.push_back(QrcFile_); + + // Log command + if (Log().Verbose()) { + std::string msg = "Running command:\n"; + msg += QuotedCommand(cmd); + msg += '\n'; + cmSystemTools::Stdout(msg); + } + + std::string rccStdOut; + std::string rccStdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + cmd, &rccStdOut, &rccStdErr, &retVal, AutogenBuildDir_.c_str(), + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); + if (!result || (retVal != 0)) { + // rcc process failed + { + std::string err = "The rcc process failed to compile\n "; + err += Quoted(QrcFile_); + err += "\ninto\n "; + err += Quoted(RccFileOutput_); + Log().ErrorCommand(GenT::RCC, err, cmd, rccStdOut + rccStdErr); + } + cmSystemTools::RemoveFile(RccFileOutput_); + return false; + } + + // rcc process success + // Print rcc output + if (!rccStdOut.empty()) { + Log().Info(GenT::RCC, rccStdOut); + } + BuildFileChanged_ = true; + + return true; +} + +bool cmQtAutoRcc::GenerateWrapper() +{ + // Generate a wrapper source file on demand + if (IsMultiConfig()) { + // Wrapper file content + std::string content; + content += "// This is an autogenerated configuration wrapper file.\n"; + content += "// Changes will be overwritten.\n"; + content += "#include <"; + content += MultiConfigOutput(); + content += ">\n"; + + // Compare with existing file content + bool fileDiffers = true; + { + std::string oldContents; + if (FileRead(oldContents, RccFilePublic_)) { + fileDiffers = (oldContents != content); + } + } + if (fileDiffers) { + // Write new wrapper file + if (Log().Verbose()) { + Log().Info(GenT::RCC, "Generating RCC wrapper file " + RccFilePublic_); + } + std::string error; + if (!FileWrite(RccFilePublic_, content, &error)) { + Log().ErrorFile(GenT::RCC, RccFilePublic_, + "RCC wrapper file writing failed. " + error); + return false; + } + } else if (BuildFileChanged_) { + // Just touch the wrapper file + if (Log().Verbose()) { + Log().Info(GenT::RCC, "Touching RCC wrapper file " + RccFilePublic_); + } + if (!cmSystemTools::Touch(RccFilePublic_, false)) { + Log().ErrorFile(GenT::RCC, RccFilePublic_, + "RCC wrapper file touch failed."); + return false; + } + } + } + return true; +} diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoRcc.h index 1ec1c4a..8dc9179 100644 --- a/Source/cmQtAutoGeneratorRcc.h +++ b/Source/cmQtAutoRcc.h @@ -1,13 +1,13 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGeneratorRcc_h -#define cmQtAutoGeneratorRcc_h +#ifndef cmQtAutoRcc_h +#define cmQtAutoRcc_h #include "cmConfigure.h" // IWYU pragma: keep #include "cmFileLock.h" +#include "cmFileTime.h" #include "cmQtAutoGenerator.h" -#include "cm_uv.h" #include <string> #include <vector> @@ -15,62 +15,38 @@ class cmMakefile; // @brief AUTORCC generator -class cmQtAutoGeneratorRcc : public cmQtAutoGenerator +class cmQtAutoRcc : public cmQtAutoGenerator { public: - cmQtAutoGeneratorRcc(); - ~cmQtAutoGeneratorRcc() override; + cmQtAutoRcc(); + ~cmQtAutoRcc() override; - cmQtAutoGeneratorRcc(cmQtAutoGeneratorRcc const&) = delete; - cmQtAutoGeneratorRcc& operator=(cmQtAutoGeneratorRcc const&) = delete; + cmQtAutoRcc(cmQtAutoRcc const&) = delete; + cmQtAutoRcc& operator=(cmQtAutoRcc const&) = delete; private: - // -- Types - - /// @brief Processing stage - enum class StageT : unsigned char - { - SETTINGS_READ, - TEST_QRC_RCC_FILES, - TEST_RESOURCES_READ, - TEST_RESOURCES, - TEST_INFO_FILE, - GENERATE, - GENERATE_RCC, - GENERATE_WRAPPER, - SETTINGS_WRITE, - FINISH, - END - }; + // -- Utility + Logger& Log() { return Logger_; } + bool IsMultiConfig() const { return MultiConfig_; } + std::string MultiConfigOutput() const; // -- Abstract processing interface bool Init(cmMakefile* makefile) override; bool Process() override; - // -- Process stage - static void UVPollStage(uv_async_t* handle); - void PollStage(); - void SetStage(StageT stage); // -- Settings file bool SettingsFileRead(); - void SettingsFileWrite(); + bool SettingsFileWrite(); // -- Tests - bool TestQrcRccFiles(); - bool TestResourcesRead(); - bool TestResources(); - void TestInfoFile(); + bool TestQrcRccFiles(bool& generate); + bool TestResources(bool& generate); + bool TestInfoFile(); // -- Generation - void GenerateParentDir(); bool GenerateRcc(); - void GenerateWrapper(); - - // -- Utility - bool IsMultiConfig() const { return MultiConfig_; } - std::string MultiConfigOutput() const; - bool StartProcess(std::string const& workingDirectory, - std::vector<std::string> const& command, - bool mergedOutput); + bool GenerateWrapper(); private: + // -- Logging + Logger Logger_; // -- Config settings bool MultiConfig_ = false; // -- Directories @@ -85,23 +61,18 @@ private: std::string QrcFile_; std::string QrcFileName_; std::string QrcFileDir_; + cmFileTime QrcFileTime_; std::string RccPathChecksum_; std::string RccFileName_; std::string RccFileOutput_; std::string RccFilePublic_; + cmFileTime RccFileTime_; std::vector<std::string> Options_; std::vector<std::string> Inputs_; - // -- Subprocess - ProcessResultT ProcessResult_; - std::unique_ptr<ReadOnlyProcessT> Process_; // -- Settings file std::string SettingsFile_; std::string SettingsString_; bool SettingsChanged_ = false; - // -- libuv loop - StageT Stage_ = StageT::SETTINGS_READ; - bool Error_ = false; - bool Generate_ = false; bool BuildFileChanged_ = false; }; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index cf9f064..c18c256 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -8,7 +8,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmQtAutoGeneratorMocUic.h" -#include "cmQtAutoGeneratorRcc.h" +#include "cmQtAutoRcc.h" #include "cmRange.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -1024,7 +1024,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return autoGen.Run(infoDir, config) ? 0 : 1; } if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) { - cmQtAutoGeneratorRcc autoGen; + cmQtAutoRcc autoGen; std::string const& infoFile = args[2]; std::string config; if (args.size() > 3) { |