mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-11 17:49:38 -06:00
This factors out the concurrency framework in `cmQtAutoGeneratorMocUic` to a dedicated class `cmWorkerPool` which might be reused in other places. `cmWorkerPool` supports fence jobs that require that - all other jobs before in the queue have been processed before the fence job processing gets started, - no jobs later in the queue will be processed before the fence job processing has been completed. Fence jobs are needed where the completion of all previous jobs in the queue is a requirement for further processing. E.g. in `cmQtAutoGeneratorMocUic` the generation of `mocs_compilation.cpp` requires that all previous source file parse jobs have been completed.
483 lines
13 KiB
C++
483 lines
13 KiB
C++
/* 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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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->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)
|
|
{
|
|
std::lock_guard<std::mutex> lock(Mutex_);
|
|
return cmSystemTools::GetRealPath(filename);
|
|
}
|
|
|
|
std::string cmQtAutoGenerator::FileSystem::CollapseFullPath(
|
|
std::string const& file, std::string const& dir)
|
|
{
|
|
std::lock_guard<std::mutex> lock(Mutex_);
|
|
return cmSystemTools::CollapseFullPath(file, dir);
|
|
}
|
|
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
std::lock_guard<std::mutex> lock(Mutex_);
|
|
return cmQtAutoGenerator::FileWrite(filename, content, error);
|
|
}
|
|
|
|
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::MakeParentDirectory(
|
|
std::string const& filename)
|
|
{
|
|
std::lock_guard<std::mutex> lock(Mutex_);
|
|
return cmQtAutoGenerator::MakeParentDirectory(filename);
|
|
}
|
|
|
|
cmQtAutoGenerator::cmQtAutoGenerator() = default;
|
|
|
|
cmQtAutoGenerator::~cmQtAutoGenerator() = default;
|
|
|
|
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, 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();
|
|
}
|