/* 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 "cmSystemTools.h" #include "cmsys/RegularExpression.hxx" #include #include #include // - Static variables std::string const genNameGen = "AutoGen"; std::string const genNameMoc = "AutoMoc"; std::string const genNameUic = "AutoUic"; std::string const genNameRcc = "AutoRcc"; std::string const mcNameSingle = "SINGLE"; std::string const mcNameWrapper = "WRAPPER"; std::string const mcNameMulti = "MULTI"; // - Static functions /// @brief Merges newOpts into baseOpts /// @arg valueOpts list of options that accept a value void MergeOptions(std::vector& baseOpts, std::vector const& newOpts, std::vector const& valueOpts, bool isQt5) { typedef std::vector::iterator Iter; typedef std::vector::const_iterator CIter; if (newOpts.empty()) { return; } if (baseOpts.empty()) { baseOpts = newOpts; return; } std::vector extraOpts; for (CIter fit = newOpts.begin(), fitEnd = newOpts.end(); fit != fitEnd; ++fit) { std::string const& newOpt = *fit; Iter existIt = std::find(baseOpts.begin(), baseOpts.end(), newOpt); if (existIt != baseOpts.end()) { if (newOpt.size() >= 2) { // Acquire the option name std::string optName; { auto oit = newOpt.begin(); if (*oit == '-') { ++oit; if (isQt5 && (*oit == '-')) { ++oit; } optName.assign(oit, newOpt.end()); } } // Test if this is a value option and change the existing value if (!optName.empty() && (std::find(valueOpts.begin(), valueOpts.end(), optName) != valueOpts.end())) { const Iter existItNext(existIt + 1); const CIter fitNext(fit + 1); if ((existItNext != baseOpts.end()) && (fitNext != fitEnd)) { *existItNext = *fitNext; ++fit; } } } } else { extraOpts.push_back(newOpt); } } // Append options baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end()); } // - Class definitions std::string const cmQtAutoGen::ListSep = "<<>>"; unsigned int const cmQtAutoGen::ParallelMax = 64; std::string const& cmQtAutoGen::GeneratorName(GeneratorT type) { switch (type) { case GeneratorT::GEN: return genNameGen; case GeneratorT::MOC: return genNameMoc; case GeneratorT::UIC: return genNameUic; case GeneratorT::RCC: return genNameRcc; } return genNameGen; } std::string cmQtAutoGen::GeneratorNameUpper(GeneratorT genType) { return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType)); } std::string const& cmQtAutoGen::MultiConfigName(MultiConfigT config) { switch (config) { case MultiConfigT::SINGLE: return mcNameSingle; case MultiConfigT::WRAPPER: return mcNameWrapper; case MultiConfigT::MULTI: return mcNameMulti; } return mcNameWrapper; } cmQtAutoGen::MultiConfigT cmQtAutoGen::MultiConfigType(std::string const& name) { if (name == mcNameSingle) { return MultiConfigT::SINGLE; } if (name == mcNameMulti) { return MultiConfigT::MULTI; } return MultiConfigT::WRAPPER; } 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" }; std::string res = text; for (const char* const* it = cm::cbegin(rep); it != cm::cend(rep); it += 2) { cmSystemTools::ReplaceString(res, *it, *(it + 1)); } res = '"' + res; res += '"'; return res; } std::string cmQtAutoGen::QuotedCommand(std::vector const& command) { std::string res; for (std::string const& item : command) { if (!res.empty()) { res.push_back(' '); } std::string const cesc = cmQtAutoGen::Quoted(item); if (item.empty() || (cesc.size() > (item.size() + 2)) || (cesc.find(' ') != std::string::npos)) { res += cesc; } else { res += item; } } return res; } std::string cmQtAutoGen::SubDirPrefix(std::string const& filename) { std::string res(cmSystemTools::GetFilenamePath(filename)); if (!res.empty()) { res += '/'; } return res; } std::string cmQtAutoGen::AppendFilenameSuffix(std::string const& filename, std::string const& suffix) { std::string res; auto pos = filename.rfind('.'); if (pos != std::string::npos) { const auto it_dot = filename.begin() + pos; res.assign(filename.begin(), it_dot); res.append(suffix); res.append(it_dot, filename.end()); } else { res = filename; res.append(suffix); } return res; } void cmQtAutoGen::UicMergeOptions(std::vector& baseOpts, std::vector const& newOpts, bool isQt5) { static std::vector const valueOpts = { "tr", "translate", "postfix", "generator", "include", // Since Qt 5.3 "g" }; MergeOptions(baseOpts, newOpts, valueOpts, isQt5); } void cmQtAutoGen::RccMergeOptions(std::vector& baseOpts, std::vector const& newOpts, bool isQt5) { static std::vector const valueOpts = { "name", "root", "compress", "threshold" }; MergeOptions(baseOpts, newOpts, valueOpts, isQt5); } void cmQtAutoGen::RccListParseContent(std::string const& content, std::vector& files) { cmsys::RegularExpression fileMatchRegex("(]*>)"); const char* contentChars = content.c_str(); while (fileMatchRegex.find(contentChars)) { std::string const qrcEntry = fileMatchRegex.match(1); contentChars += qrcEntry.size(); { fileReplaceRegex.find(qrcEntry); std::string const tag = fileReplaceRegex.match(1); files.push_back(qrcEntry.substr(tag.size())); } } } bool cmQtAutoGen::RccListParseOutput(std::string const& rccStdOut, std::string const& rccStdErr, std::vector& files, std::string& error) { // Lambda to strip CR characters auto StripCR = [](std::string& line) { std::string::size_type cr = line.find('\r'); if (cr != std::string::npos) { line = line.substr(0, cr); } }; // Parse rcc std output { std::istringstream ostr(rccStdOut); std::string oline; while (std::getline(ostr, oline)) { StripCR(oline); if (!oline.empty()) { files.push_back(oline); } } } // Parse rcc error output { std::istringstream estr(rccStdErr); std::string eline; while (std::getline(estr, eline)) { StripCR(eline); if (cmHasLiteralPrefix(eline, "RCC: Error in")) { static std::string const searchString = "Cannot find file '"; std::string::size_type pos = eline.find(searchString); if (pos == std::string::npos) { error = "rcc lists unparsable output:\n"; error += cmQtAutoGen::Quoted(eline); error += "\n"; return false; } pos += searchString.length(); std::string::size_type sz = eline.size() - pos - 1; files.push_back(eline.substr(pos, sz)); } } } return true; } void cmQtAutoGen::RccListConvertFullPath(std::string const& qrcFileDir, std::vector& files) { for (std::string& entry : files) { std::string tmp = cmSystemTools::CollapseCombinedPath(qrcFileDir, entry); entry = std::move(tmp); } }