A security patch will be applied between 1pm - 1:30pm, (UTC-0400), today- Aug 5th. No downtime is expected, but the site could be slow during that time.

Commit 7e60e77c authored by Brad King's avatar Brad King Committed by Kitware Robot
Browse files

Merge topic 'autogen_autorcc_no_libuv'

7b98a6eb Autogen: Rename cmQtAutoGeneratorRcc to cmQtAutoRcc
9710d4aa Autogen: Move libuv loop from cmQtAutoGenerator to cmQtAutoGeneratorMocUic
95e72c01 Autogen: Make cmQtAutoGenerator::FileSystem Logger free
f161cfe5 Autogen: Move Logger and FileSystem member variables to generator classes
7baec5e9 AutoRcc: Don't use cmQtAutoGenerator::FileSystem methods
191269d2 AutoRcc: Remove libuv event loop from cmQtAutoGeneratorRcc
95de172b AutoRcc: Make rcc parsing function private
521475b4

 AutoRcc: Use cmQtAutoGen::RccLister in initializer and generator
...
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !3202
parents 14270eab 7b98a6eb
Pipeline #134194 passed with stage
in 0 seconds
......@@ -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
......
/* 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;
}
......@@ -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
......@@ -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;
}
......@@ -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;
......
......@@ -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);
}