diff options
Diffstat (limited to 'Source/cmQtAutoGen.cxx')
-rw-r--r-- | Source/cmQtAutoGen.cxx | 202 |
1 files changed, 159 insertions, 43 deletions
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 653caf7..3683edd 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -1,23 +1,19 @@ /* 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> -#include <iterator> +#include <array> #include <sstream> #include <utility> -// - Static variables - -std::string const genNameGen = "AutoGen"; -std::string const genNameMoc = "AutoMoc"; -std::string const genNameUic = "AutoUic"; -std::string const genNameRcc = "AutoRcc"; - // - Static functions /// @brief Merges newOpts into baseOpts @@ -72,32 +68,52 @@ void MergeOptions(std::vector<std::string>& baseOpts, } } // Append options - baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end()); + cmAppend(baseOpts, extraOpts); } // - Class definitions -std::string const cmQtAutoGen::ListSep = "<<<S>>>"; unsigned int const cmQtAutoGen::ParallelMax = 64; +std::string const cmQtAutoGen::ListSep = "<<<S>>>"; -std::string const& cmQtAutoGen::GeneratorName(GeneratorT type) +std::string const& cmQtAutoGen::GeneratorName(GenT genType) { - switch (type) { - case GeneratorT::GEN: - return genNameGen; - case GeneratorT::MOC: - return genNameMoc; - case GeneratorT::UIC: - return genNameUic; - case GeneratorT::RCC: - return genNameRcc; + static const std::string AutoGen("AutoGen"); + static const std::string AutoMoc("AutoMoc"); + static const std::string AutoUic("AutoUic"); + static const std::string AutoRcc("AutoRcc"); + + switch (genType) { + case GenT::GEN: + return AutoGen; + case GenT::MOC: + return AutoMoc; + case GenT::UIC: + return AutoUic; + case GenT::RCC: + return AutoRcc; } - return genNameGen; + return AutoGen; } -std::string cmQtAutoGen::GeneratorNameUpper(GeneratorT genType) +std::string const& cmQtAutoGen::GeneratorNameUpper(GenT genType) { - return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType)); + static const std::string AUTOGEN("AUTOGEN"); + static const std::string AUTOMOC("AUTOMOC"); + static const std::string AUTOUIC("AUTOUIC"); + static const std::string AUTORCC("AUTORCC"); + + switch (genType) { + case GenT::GEN: + return AUTOGEN; + case GenT::MOC: + return AUTOMOC; + case GenT::UIC: + return AUTOUIC; + case GenT::RCC: + return AUTORCC; + } + return AUTOGEN; } std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc) @@ -137,13 +153,21 @@ std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc) std::string cmQtAutoGen::Quoted(std::string const& text) { - static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", - "\b", "\\b", "\f", "\\f", "\n", "\\n", - "\r", "\\r", "\t", "\\t", "\v", "\\v" }; + const std::array<std::pair<const char*, const char*>, 9> replaces = { + { { "\\", "\\\\" }, + { "\"", "\\\"" }, + { "\a", "\\a" }, + { "\b", "\\b" }, + { "\f", "\\f" }, + { "\n", "\\n" }, + { "\r", "\\r" }, + { "\t", "\\t" }, + { "\v", "\\v" } } + }; std::string res = text; - for (const char* const* it = cm::cbegin(rep); it != cm::cend(rep); it += 2) { - cmSystemTools::ReplaceString(res, *it, *(it + 1)); + for (auto const& pair : replaces) { + cmSystemTools::ReplaceString(res, pair.first, pair.second); } res = '"' + res; res += '"'; @@ -170,11 +194,11 @@ std::string cmQtAutoGen::QuotedCommand(std::vector<std::string> const& command) std::string cmQtAutoGen::SubDirPrefix(std::string const& filename) { - std::string res(cmSystemTools::GetFilenamePath(filename)); - if (!res.empty()) { - res += '/'; + std::string::size_type slash_pos = filename.rfind('/'); + if (slash_pos == std::string::npos) { + return std::string(); } - return res; + return filename.substr(0, slash_pos + 1); } std::string cmQtAutoGen::AppendFilenameSuffix(std::string const& filename, @@ -216,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[^>]*>)"); @@ -234,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) { @@ -284,11 +308,103 @@ 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_); + cmAppend(cmd, this->ListOptions_); + 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::CollapseCombinedPath(qrcFileDir, entry); - entry = std::move(tmp); + entry = cmSystemTools::CollapseFullPath(entry, fileDir); } + return true; } |