summaryrefslogtreecommitdiffstats
path: root/Source/cmQtAutoGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmQtAutoGenerator.cxx')
-rw-r--r--Source/cmQtAutoGenerator.cxx613
1 files changed, 108 insertions, 505 deletions
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index e2d7deb..e1c435b 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -14,10 +14,33 @@
#include "cmSystemTools.h"
#include "cmake.h"
-#include <algorithm>
-#include <utility>
+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);
+ }
+ }
+}
-// -- Class methods
+cmQtAutoGenerator::Logger::~Logger() = default;
void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value)
{
@@ -43,8 +66,8 @@ std::string cmQtAutoGenerator::Logger::HeadLine(std::string const& title)
return head;
}
-void cmQtAutoGenerator::Logger::Info(GeneratorT genType,
- std::string const& message)
+void cmQtAutoGenerator::Logger::Info(GenT genType,
+ std::string const& message) const
{
std::string msg = GeneratorName(genType);
msg += ": ";
@@ -58,8 +81,8 @@ void cmQtAutoGenerator::Logger::Info(GeneratorT genType,
}
}
-void cmQtAutoGenerator::Logger::Warning(GeneratorT genType,
- std::string const& message)
+void cmQtAutoGenerator::Logger::Warning(GenT genType,
+ std::string const& message) const
{
std::string msg;
if (message.find('\n') == std::string::npos) {
@@ -82,9 +105,9 @@ void cmQtAutoGenerator::Logger::Warning(GeneratorT genType,
}
}
-void cmQtAutoGenerator::Logger::WarningFile(GeneratorT genType,
+void cmQtAutoGenerator::Logger::WarningFile(GenT genType,
std::string const& filename,
- std::string const& message)
+ std::string const& message) const
{
std::string msg = " ";
msg += Quoted(filename);
@@ -94,8 +117,8 @@ void cmQtAutoGenerator::Logger::WarningFile(GeneratorT genType,
Warning(genType, msg);
}
-void cmQtAutoGenerator::Logger::Error(GeneratorT genType,
- std::string const& message)
+void cmQtAutoGenerator::Logger::Error(GenT genType,
+ std::string const& message) const
{
std::string msg;
msg += HeadLine(GeneratorName(genType) + " error");
@@ -111,9 +134,9 @@ void cmQtAutoGenerator::Logger::Error(GeneratorT genType,
}
}
-void cmQtAutoGenerator::Logger::ErrorFile(GeneratorT genType,
+void cmQtAutoGenerator::Logger::ErrorFile(GenT genType,
std::string const& filename,
- std::string const& message)
+ std::string const& message) const
{
std::string emsg = " ";
emsg += Quoted(filename);
@@ -124,8 +147,8 @@ void cmQtAutoGenerator::Logger::ErrorFile(GeneratorT genType,
}
void cmQtAutoGenerator::Logger::ErrorCommand(
- GeneratorT genType, std::string const& message,
- std::vector<std::string> const& command, std::string const& output)
+ GenT genType, std::string const& message,
+ std::vector<std::string> const& command, std::string const& output) const
{
std::string msg;
msg.push_back('\n');
@@ -153,528 +176,101 @@ void cmQtAutoGenerator::Logger::ErrorCommand(
}
}
-std::string cmQtAutoGenerator::FileSystem::GetRealPath(
- std::string const& filename)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::GetRealPath(filename);
-}
-
-std::string cmQtAutoGenerator::FileSystem::CollapseCombinedPath(
- std::string const& dir, std::string const& file)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::CollapseCombinedPath(dir, file);
-}
-
-void cmQtAutoGenerator::FileSystem::SplitPath(
- const std::string& p, std::vector<std::string>& components,
- bool expand_home_dir)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- cmSystemTools::SplitPath(p, components, expand_home_dir);
-}
-
-std::string cmQtAutoGenerator::FileSystem::JoinPath(
- const std::vector<std::string>& components)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::JoinPath(components);
-}
-
-std::string cmQtAutoGenerator::FileSystem::JoinPath(
- std::vector<std::string>::const_iterator first,
- std::vector<std::string>::const_iterator last)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::JoinPath(first, last);
-}
-
-std::string cmQtAutoGenerator::FileSystem::GetFilenameWithoutLastExtension(
- const std::string& filename)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::GetFilenameWithoutLastExtension(filename);
-}
-
-std::string cmQtAutoGenerator::FileSystem::SubDirPrefix(
- std::string const& filename)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmQtAutoGen::SubDirPrefix(filename);
-}
-
-void cmQtAutoGenerator::FileSystem::setupFilePathChecksum(
- std::string const& currentSrcDir, std::string const& currentBinDir,
- std::string const& projectSrcDir, std::string const& projectBinDir)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- FilePathChecksum_.setupParentDirs(currentSrcDir, currentBinDir,
- projectSrcDir, projectBinDir);
-}
-
-std::string cmQtAutoGenerator::FileSystem::GetFilePathChecksum(
- std::string const& filename)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return FilePathChecksum_.getPart(filename);
-}
-
-bool cmQtAutoGenerator::FileSystem::FileExists(std::string const& filename)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::FileExists(filename);
-}
-
-bool cmQtAutoGenerator::FileSystem::FileExists(std::string const& filename,
- bool isFile)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::FileExists(filename, isFile);
-}
-
-unsigned long cmQtAutoGenerator::FileSystem::FileLength(
- std::string const& filename)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::FileLength(filename);
-}
-
-bool cmQtAutoGenerator::FileSystem::FileIsOlderThan(
- std::string const& buildFile, std::string const& sourceFile,
- std::string* error)
-{
- bool res(false);
- int result = 0;
- {
- std::lock_guard<std::mutex> lock(Mutex_);
- res = cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result);
- }
- if (res) {
- res = (result < 0);
- } else {
- if (error != nullptr) {
- error->append(
- "File modification time comparison failed for the files\n ");
- error->append(Quoted(buildFile));
- error->append("\nand\n ");
- error->append(Quoted(sourceFile));
- }
- }
- return res;
-}
-
-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(GeneratorT 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;
-}
-
-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(GeneratorT 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;
-}
-
-bool cmQtAutoGenerator::FileSystem::FileDiffers(std::string const& filename,
- std::string const& content)
-{
- bool differs = true;
- {
- std::string oldContents;
- if (FileRead(oldContents, filename)) {
- differs = (oldContents != content);
- }
- }
- return differs;
-}
-
-bool cmQtAutoGenerator::FileSystem::FileRemove(std::string const& filename)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::RemoveFile(filename);
-}
-
-bool cmQtAutoGenerator::FileSystem::Touch(std::string const& filename,
- bool create)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::Touch(filename, create);
-}
-
-bool cmQtAutoGenerator::FileSystem::MakeDirectory(std::string const& dirname)
-{
- std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::MakeDirectory(dirname);
-}
-
-bool cmQtAutoGenerator::FileSystem::MakeDirectory(GeneratorT 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 cmQtAutoGenerator::MakeParentDirectory(std::string const& filename)
{
bool success = true;
std::string const dirName = cmSystemTools::GetFilenamePath(filename);
if (!dirName.empty()) {
- success = MakeDirectory(dirName);
+ success = cmSystemTools::MakeDirectory(dirName);
}
return success;
}
-bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
- GeneratorT genType, std::string const& filename)
+bool cmQtAutoGenerator::FileRead(std::string& content,
+ std::string const& filename,
+ std::string* error)
{
- if (!MakeParentDirectory(filename)) {
- Log()->ErrorFile(genType, filename, "Could not create parent directory");
+ content.clear();
+ if (!cmSystemTools::FileExists(filename, true)) {
+ if (error != nullptr) {
+ *error = "Not a file.";
+ }
return false;
}
- return true;
-}
-int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::init(uv_loop_t* uv_loop,
- ReadOnlyProcessT* process)
-{
- Process_ = process;
- Target_ = nullptr;
- return UVPipe_.init(*uv_loop, 0, this);
-}
-
-int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::startRead(std::string* target)
-{
- Target_ = target;
- return uv_read_start(uv_stream(), &PipeT::UVAlloc, &PipeT::UVData);
-}
+ unsigned long const length = cmSystemTools::FileLength(filename);
+ cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
-void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::reset()
-{
- Process_ = nullptr;
- Target_ = nullptr;
- UVPipe_.reset();
- Buffer_.clear();
- Buffer_.shrink_to_fit();
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVAlloc(uv_handle_t* handle,
- size_t suggestedSize,
- uv_buf_t* buf)
-{
- auto& pipe = *reinterpret_cast<PipeT*>(handle->data);
- pipe.Buffer_.resize(suggestedSize);
- buf->base = &pipe.Buffer_.front();
- buf->len = pipe.Buffer_.size();
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVData(uv_stream_t* stream,
- ssize_t nread,
- const uv_buf_t* buf)
-{
- auto& pipe = *reinterpret_cast<PipeT*>(stream->data);
- if (nread > 0) {
- // Append data to merged output
- if ((buf->base != nullptr) && (pipe.Target_ != nullptr)) {
- pipe.Target_->append(buf->base, nread);
+ // Use lambda to save destructor calls of ifs
+ return [&ifs, length, &content, error]() -> bool {
+ if (!ifs) {
+ if (error != nullptr) {
+ *error = "Opening the file for reading failed.";
+ }
+ return false;
}
- } else if (nread < 0) {
- // EOF or error
- auto* proc = pipe.Process_;
- // Check it this an unusual error
- if (nread != UV_EOF) {
- if (!proc->Result()->error()) {
- proc->Result()->ErrorMessage =
- "libuv reading from pipe failed with error code ";
- proc->Result()->ErrorMessage += std::to_string(nread);
+ content.reserve(length);
+ typedef std::istreambuf_iterator<char> IsIt;
+ content.assign(IsIt{ ifs }, IsIt{});
+ if (!ifs) {
+ content.clear();
+ if (error != nullptr) {
+ *error = "Reading from the file failed.";
}
+ return false;
}
- // Clear libuv pipe handle and try to finish
- pipe.reset();
- proc->UVTryFinish();
- }
-}
-
-void cmQtAutoGenerator::ProcessResultT::reset()
-{
- ExitStatus = 0;
- TermSignal = 0;
- if (!StdOut.empty()) {
- StdOut.clear();
- StdOut.shrink_to_fit();
- }
- if (!StdErr.empty()) {
- StdErr.clear();
- StdErr.shrink_to_fit();
- }
- if (!ErrorMessage.empty()) {
- ErrorMessage.clear();
- ErrorMessage.shrink_to_fit();
- }
+ return true;
+ }();
}
-void cmQtAutoGenerator::ReadOnlyProcessT::setup(
- ProcessResultT* result, bool mergedOutput,
- std::vector<std::string> const& command, std::string const& workingDirectory)
+bool cmQtAutoGenerator::FileWrite(std::string const& filename,
+ std::string const& content,
+ std::string* error)
{
- Setup_.WorkingDirectory = workingDirectory;
- Setup_.Command = command;
- Setup_.Result = result;
- Setup_.MergedOutput = mergedOutput;
-}
-
-bool cmQtAutoGenerator::ReadOnlyProcessT::start(
- uv_loop_t* uv_loop, std::function<void()>&& finishedCallback)
-{
- if (IsStarted() || (Result() == nullptr)) {
- return false;
- }
-
- // Reset result before the start
- Result()->reset();
-
- // Fill command string pointers
- if (!Setup().Command.empty()) {
- CommandPtr_.reserve(Setup().Command.size() + 1);
- for (std::string const& arg : Setup().Command) {
- CommandPtr_.push_back(arg.c_str());
- }
- CommandPtr_.push_back(nullptr);
- } else {
- Result()->ErrorMessage = "Empty command";
- }
-
- if (!Result()->error()) {
- if (UVPipeOut_.init(uv_loop, this) != 0) {
- Result()->ErrorMessage = "libuv stdout pipe initialization failed";
- }
- }
- if (!Result()->error()) {
- if (UVPipeErr_.init(uv_loop, this) != 0) {
- Result()->ErrorMessage = "libuv stderr pipe initialization failed";
- }
- }
- if (!Result()->error()) {
- // -- Setup process stdio options
- // stdin
- UVOptionsStdIO_[0].flags = UV_IGNORE;
- UVOptionsStdIO_[0].data.stream = nullptr;
- // stdout
- UVOptionsStdIO_[1].flags =
- static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
- UVOptionsStdIO_[1].data.stream = UVPipeOut_.uv_stream();
- // stderr
- UVOptionsStdIO_[2].flags =
- static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
- UVOptionsStdIO_[2].data.stream = UVPipeErr_.uv_stream();
-
- // -- Setup process options
- std::fill_n(reinterpret_cast<char*>(&UVOptions_), sizeof(UVOptions_), 0);
- UVOptions_.exit_cb = &ReadOnlyProcessT::UVExit;
- UVOptions_.file = CommandPtr_[0];
- UVOptions_.args = const_cast<char**>(&CommandPtr_.front());
- UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
- UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
- UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
- UVOptions_.stdio = &UVOptionsStdIO_.front();
-
- // -- Spawn process
- if (UVProcess_.spawn(*uv_loop, UVOptions_, this) != 0) {
- Result()->ErrorMessage = "libuv process spawn failed";
- }
- }
- // -- Start reading from stdio streams
- if (!Result()->error()) {
- if (UVPipeOut_.startRead(&Result()->StdOut) != 0) {
- Result()->ErrorMessage = "libuv start reading from stdout pipe failed";
- }
- }
- if (!Result()->error()) {
- if (UVPipeErr_.startRead(Setup_.MergedOutput ? &Result()->StdOut
- : &Result()->StdErr) != 0) {
- Result()->ErrorMessage = "libuv start reading from stderr pipe failed";
+ // Make sure the parent directory exists
+ if (!cmQtAutoGenerator::MakeParentDirectory(filename)) {
+ if (error != nullptr) {
+ *error = "Could not create parent directory.";
}
+ return false;
}
+ cmsys::ofstream ofs;
+ ofs.open(filename.c_str(),
+ (std::ios::out | std::ios::binary | std::ios::trunc));
- if (!Result()->error()) {
- IsStarted_ = true;
- FinishedCallback_ = std::move(finishedCallback);
- } else {
- // Clear libuv handles and finish
- UVProcess_.reset();
- UVPipeOut_.reset();
- UVPipeErr_.reset();
- CommandPtr_.clear();
- }
-
- return IsStarted();
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::UVExit(uv_process_t* handle,
- int64_t exitStatus,
- int termSignal)
-{
- auto& proc = *reinterpret_cast<ReadOnlyProcessT*>(handle->data);
- if (proc.IsStarted() && !proc.IsFinished()) {
- // Set error message on demand
- proc.Result()->ExitStatus = exitStatus;
- proc.Result()->TermSignal = termSignal;
- if (!proc.Result()->error()) {
- if (termSignal != 0) {
- proc.Result()->ErrorMessage = "Process was terminated by signal ";
- proc.Result()->ErrorMessage +=
- std::to_string(proc.Result()->TermSignal);
- } else if (exitStatus != 0) {
- proc.Result()->ErrorMessage = "Process failed with return value ";
- proc.Result()->ErrorMessage +=
- std::to_string(proc.Result()->ExitStatus);
+ // Use lambda to save destructor calls of ofs
+ return [&ofs, &content, error]() -> bool {
+ if (!ofs) {
+ if (error != nullptr) {
+ *error = "Opening file for writing failed.";
}
+ return false;
}
-
- // Reset process handle and try to finish
- proc.UVProcess_.reset();
- proc.UVTryFinish();
- }
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::UVTryFinish()
-{
- // There still might be data in the pipes after the process has finished.
- // Therefore check if the process is finished AND all pipes are closed
- // before signaling the worker thread to continue.
- if (UVProcess_.get() == nullptr) {
- if (UVPipeOut_.uv_pipe() == nullptr) {
- if (UVPipeErr_.uv_pipe() == nullptr) {
- IsFinished_ = true;
- FinishedCallback_();
+ ofs << content;
+ if (!ofs.good()) {
+ if (error != nullptr) {
+ *error = "File writing failed.";
}
+ return false;
}
- }
+ return true;
+ }();
}
-cmQtAutoGenerator::cmQtAutoGenerator()
- : FileSys_(&Logger_)
+bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
+ std::string const& content)
{
- // 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);
- }
+ bool differs = true;
+ std::string oldContents;
+ if (FileRead(oldContents, filename) && (oldContents == content)) {
+ differs = false;
}
-
- // 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());
+ return differs;
}
-cmQtAutoGenerator::~cmQtAutoGenerator()
-{
- // Close libuv loop
- uv_loop_close(UVLoop());
-}
+cmQtAutoGenerator::cmQtAutoGenerator() = default;
+
+cmQtAutoGenerator::~cmQtAutoGenerator() = default;
bool cmQtAutoGenerator::Run(std::string const& infoFile,
std::string const& config)
@@ -682,6 +278,13 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
// Info settings
InfoFile_ = infoFile;
cmSystemTools::ConvertToUnixSlashes(InfoFile_);
+ if (!InfoFileTime_.Load(InfoFile_)) {
+ std::string msg = "AutoGen: The info file ";
+ msg += Quoted(InfoFile_);
+ msg += " is not readable\n";
+ cmSystemTools::Stderr(msg);
+ return false;
+ }
InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
InfoConfig_ = config;