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.
333 lines
8.7 KiB
333 lines
8.7 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 "cmState.h"
|
|
#include "cmStateDirectory.h"
|
|
#include "cmStateSnapshot.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmake.h"
|
|
|
|
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;
|
|
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(GenT genType,
|
|
std::string const& message) const
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::Warning(GenT genType,
|
|
std::string const& message) const
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::WarningFile(GenT genType,
|
|
std::string const& filename,
|
|
std::string const& message) const
|
|
{
|
|
std::string msg = " ";
|
|
msg += Quoted(filename);
|
|
msg.push_back('\n');
|
|
// Message
|
|
msg += message;
|
|
Warning(genType, msg);
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::Error(GenT genType,
|
|
std::string const& message) const
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::ErrorFile(GenT genType,
|
|
std::string const& filename,
|
|
std::string const& message) const
|
|
{
|
|
std::string emsg = " ";
|
|
emsg += Quoted(filename);
|
|
emsg += '\n';
|
|
// Message
|
|
emsg += message;
|
|
Error(genType, emsg);
|
|
}
|
|
|
|
void cmQtAutoGenerator::Logger::ErrorCommand(
|
|
GenT genType, std::string const& message,
|
|
std::vector<std::string> const& command, std::string const& output) const
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
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 = "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 = "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 = "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 = "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 = "Opening file for writing failed.";
|
|
}
|
|
return false;
|
|
}
|
|
ofs << content;
|
|
if (!ofs.good()) {
|
|
if (error != nullptr) {
|
|
*error = "File writing failed.";
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}();
|
|
}
|
|
|
|
bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
|
|
std::string const& content)
|
|
{
|
|
bool differs = true;
|
|
std::string oldContents;
|
|
if (FileRead(oldContents, filename) && (oldContents == content)) {
|
|
differs = false;
|
|
}
|
|
return differs;
|
|
}
|
|
|
|
cmQtAutoGenerator::cmQtAutoGenerator() = default;
|
|
|
|
cmQtAutoGenerator::~cmQtAutoGenerator() = default;
|
|
|
|
bool cmQtAutoGenerator::Run(std::string const& infoFile,
|
|
std::string const& config)
|
|
{
|
|
// 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;
|
|
|
|
bool success = false;
|
|
{
|
|
cmake cm(cmake::RoleScript, cmState::Unknown);
|
|
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();
|
|
}
|