| /* 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(); |
| } |