summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2019-04-08 11:58:48 (GMT)
committerKitware Robot <kwrobot@kitware.com>2019-04-08 11:58:58 (GMT)
commit7e60e77c3c2a09eb11750616db50d2dc149a9c54 (patch)
tree52c860bbe7b64c54965f07fe12670e8b236dd97c
parent14270eab369c3b700d89ef385af2cb94a6497b1e (diff)
parent7b98a6eb68e6a2c9a422e42c8eeb78dfa4038364 (diff)
downloadCMake-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.txt4
-rw-r--r--Source/cmQtAutoGen.cxx118
-rw-r--r--Source/cmQtAutoGen.h53
-rw-r--r--Source/cmQtAutoGenInitializer.cxx90
-rw-r--r--Source/cmQtAutoGenInitializer.h4
-rw-r--r--Source/cmQtAutoGenerator.cxx265
-rw-r--r--Source/cmQtAutoGenerator.h51
-rw-r--r--Source/cmQtAutoGeneratorMocUic.cxx50
-rw-r--r--Source/cmQtAutoGeneratorMocUic.h17
-rw-r--r--Source/cmQtAutoGeneratorRcc.cxx666
-rw-r--r--Source/cmQtAutoRcc.cxx516
-rw-r--r--Source/cmQtAutoRcc.h (renamed from Source/cmQtAutoGeneratorRcc.h)71
-rw-r--r--Source/cmcmd.cxx4
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) {