You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
728 lines
21 KiB
728 lines
21 KiB
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
#include "cmQtAutoGenerator.h"
|
|
#include "cmQtAutoGen.h"
|
|
|
|
#include "cmsys/FStream.hxx"
|
|
|
|
#include "cmAlgorithms.h"
|
|
#include "cmGlobalGenerator.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmStateDirectory.h"
|
|
#include "cmStateSnapshot.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmake.h"
|
|
|
|
#include <algorithm>
|
|
|
|
// -- Class methods
|
|
|
|
void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value)
|
|
{
|
|
unsigned long verbosity = 0;
|
|
if (cmSystemTools::StringToULong(value.c_str(), &verbosity)) {
|
|
if (this->Verbosity_ < verbosity) {
|
|
this->Verbosity_ = static_cast<unsigned int>(verbosity);
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
|
|
{
|
|
ColorOutput_ = value;
|
|
}
|
|
|
|
std::string cmQtAutoGenerator::Logger::HeadLine(std::string const& title)
|
|
{
|
|
std::string head = title;
|
|
head += '\n';
|
|
head.append(head.size() - 1, '-');
|
|
head += '\n';
|
|
return head;
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::Info(GeneratorT genType,
|
|
std::string const& message)
|
|
{
|
|
std::string msg = GeneratorName(genType);
|
|
msg += ": ";
|
|
msg += message;
|
|
if (msg.back() != '\n') {
|
|
msg.push_back('\n');
|
|
}
|
|
{
|
|
std::lock_guard<std::mutex> lock(Mutex_);
|
|
cmSystemTools::Stdout(msg.c_str(), msg.size());
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::Warning(GeneratorT genType,
|
|
std::string const& message)
|
|
{
|
|
std::string msg;
|
|
if (message.find('\n') == std::string::npos) {
|
|
// Single line message
|
|
msg += GeneratorName(genType);
|
|
msg += " warning: ";
|
|
} else {
|
|
// Multi line message
|
|
msg += HeadLine(GeneratorName(genType) + " warning");
|
|
}
|
|
// Message
|
|
msg += message;
|
|
if (msg.back() != '\n') {
|
|
msg.push_back('\n');
|
|
}
|
|
msg.push_back('\n');
|
|
{
|
|
std::lock_guard<std::mutex> lock(Mutex_);
|
|
cmSystemTools::Stdout(msg.c_str(), msg.size());
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::WarningFile(GeneratorT genType,
|
|
std::string const& filename,
|
|
std::string const& message)
|
|
{
|
|
std::string msg = " ";
|
|
msg += Quoted(filename);
|
|
msg.push_back('\n');
|
|
// Message
|
|
msg += message;
|
|
Warning(genType, msg);
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::Error(GeneratorT genType,
|
|
std::string const& message)
|
|
{
|
|
std::string msg;
|
|
msg += HeadLine(GeneratorName(genType) + " error");
|
|
// Message
|
|
msg += message;
|
|
if (msg.back() != '\n') {
|
|
msg.push_back('\n');
|
|
}
|
|
msg.push_back('\n');
|
|
{
|
|
std::lock_guard<std::mutex> lock(Mutex_);
|
|
cmSystemTools::Stderr(msg.c_str(), msg.size());
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::ErrorFile(GeneratorT genType,
|
|
std::string const& filename,
|
|
std::string const& message)
|
|
{
|
|
std::string emsg = " ";
|
|
emsg += Quoted(filename);
|
|
emsg += '\n';
|
|
// Message
|
|
emsg += message;
|
|
Error(genType, emsg);
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::ErrorCommand(
|
|
GeneratorT genType, std::string const& message,
|
|
std::vector<std::string> const& command, std::string const& output)
|
|
{
|
|
std::string msg;
|
|
msg.push_back('\n');
|
|
msg += HeadLine(GeneratorName(genType) + " subprocess error");
|
|
msg += message;
|
|
if (msg.back() != '\n') {
|
|
msg.push_back('\n');
|
|
}
|
|
msg.push_back('\n');
|
|
msg += HeadLine("Command");
|
|
msg += QuotedCommand(command);
|
|
if (msg.back() != '\n') {
|
|
msg.push_back('\n');
|
|
}
|
|
msg.push_back('\n');
|
|
msg += HeadLine("Output");
|
|
msg += output;
|
|
if (msg.back() != '\n') {
|
|
msg.push_back('\n');
|
|
}
|
|
msg.push_back('\n');
|
|
{
|
|
std::lock_guard<std::mutex> lock(Mutex_);
|
|
cmSystemTools::Stderr(msg.c_str(), msg.size());
|
|
}
|
|
}
|
|
|
|
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 success = true;
|
|
std::string const dirName = cmSystemTools::GetFilenamePath(filename);
|
|
if (!dirName.empty()) {
|
|
success = MakeDirectory(dirName);
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
|
|
GeneratorT genType, std::string const& filename)
|
|
{
|
|
if (!MakeParentDirectory(filename)) {
|
|
Log()->ErrorFile(genType, filename, "Could not create parent directory");
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
} 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);
|
|
}
|
|
}
|
|
// 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();
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGenerator::ReadOnlyProcessT::setup(
|
|
ProcessResultT* result, bool mergedOutput,
|
|
std::vector<std::string> const& command, std::string const& workingDirectory)
|
|
{
|
|
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";
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
// 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_();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
// 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());
|
|
}
|
|
|
|
bool cmQtAutoGenerator::Run(std::string const& infoFile,
|
|
std::string const& config)
|
|
{
|
|
// Info settings
|
|
InfoFile_ = infoFile;
|
|
cmSystemTools::ConvertToUnixSlashes(InfoFile_);
|
|
InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
|
|
InfoConfig_ = config;
|
|
|
|
bool success = false;
|
|
{
|
|
cmake cm(cmake::RoleScript);
|
|
cm.SetHomeOutputDirectory(InfoDir());
|
|
cm.SetHomeDirectory(InfoDir());
|
|
cm.GetCurrentSnapshot().SetDefaultDefinitions();
|
|
cmGlobalGenerator gg(&cm);
|
|
|
|
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
|
|
snapshot.GetDirectory().SetCurrentBinary(InfoDir());
|
|
snapshot.GetDirectory().SetCurrentSource(InfoDir());
|
|
|
|
auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
|
|
// The OLD/WARN behavior for policy CMP0053 caused a speed regression.
|
|
// https://gitlab.kitware.com/cmake/cmake/issues/17570
|
|
makefile->SetPolicyVersion("3.9", std::string());
|
|
gg.SetCurrentMakefile(makefile.get());
|
|
success = this->Init(makefile.get());
|
|
}
|
|
if (success) {
|
|
success = this->Process();
|
|
}
|
|
return success;
|
|
}
|
|
|
|
std::string cmQtAutoGenerator::SettingsFind(std::string const& content,
|
|
const char* key)
|
|
{
|
|
std::string prefix(key);
|
|
prefix += ':';
|
|
std::string::size_type pos = content.find(prefix);
|
|
if (pos != std::string::npos) {
|
|
pos += prefix.size();
|
|
if (pos < content.size()) {
|
|
std::string::size_type posE = content.find('\n', pos);
|
|
if ((posE != std::string::npos) && (posE != pos)) {
|
|
return content.substr(pos, posE - pos);
|
|
}
|
|
}
|
|
}
|
|
return std::string();
|
|
}
|