| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- /* 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 <iterator>
- #include <cm3p/json/reader.h>
- #include "cmsys/FStream.hxx"
- #include "cmQtAutoGen.h"
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- #include "cmValue.h"
- cmQtAutoGenerator::Logger::Logger()
- {
- // Initialize logger
- {
- std::string verbose;
- if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) {
- unsigned long iVerbose = 0;
- if (cmStrToULong(verbose, &iVerbose)) {
- this->SetVerbosity(static_cast<unsigned int>(iVerbose));
- } else {
- // Non numeric verbosity
- this->SetVerbose(cmIsOn(verbose));
- }
- }
- }
- {
- std::string colorEnv;
- cmSystemTools::GetEnv("COLOR", colorEnv);
- if (!colorEnv.empty()) {
- this->SetColorOutput(cmIsOn(colorEnv));
- } else {
- this->SetColorOutput(true);
- }
- }
- }
- void cmQtAutoGenerator::Logger::RaiseVerbosity(unsigned int value)
- {
- if (this->Verbosity_ < value) {
- this->Verbosity_ = value;
- }
- }
- void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
- {
- this->ColorOutput_ = value;
- }
- std::string cmQtAutoGenerator::Logger::HeadLine(cm::string_view title)
- {
- return cmStrCat(title, '\n', std::string(title.size(), '-'), '\n');
- }
- void cmQtAutoGenerator::Logger::Info(GenT genType,
- cm::string_view message) const
- {
- std::string msg = cmStrCat(GeneratorName(genType), ": ", message,
- cmHasSuffix(message, '\n') ? "" : "\n");
- {
- std::lock_guard<std::mutex> lock(this->Mutex_);
- cmSystemTools::Stdout(msg);
- }
- }
- void cmQtAutoGenerator::Logger::Warning(GenT genType,
- cm::string_view message) const
- {
- std::string msg;
- if (message.find('\n') == std::string::npos) {
- // Single line message
- msg = cmStrCat(GeneratorName(genType), " warning: ", message,
- cmHasSuffix(message, '\n') ? "\n" : "\n\n");
- } else {
- // Multi line message
- msg = cmStrCat(HeadLine(cmStrCat(GeneratorName(genType), " warning")),
- message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
- }
- {
- std::lock_guard<std::mutex> lock(this->Mutex_);
- cmSystemTools::Stdout(msg);
- }
- }
- void cmQtAutoGenerator::Logger::Error(GenT genType,
- cm::string_view message) const
- {
- std::string msg =
- cmStrCat('\n', HeadLine(cmStrCat(GeneratorName(genType), " error")),
- message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
- {
- std::lock_guard<std::mutex> lock(this->Mutex_);
- cmSystemTools::Stderr(msg);
- }
- }
- void cmQtAutoGenerator::Logger::ErrorCommand(
- GenT genType, cm::string_view message,
- std::vector<std::string> const& command, std::string const& output) const
- {
- std::string msg = cmStrCat(
- '\n', HeadLine(cmStrCat(GeneratorName(genType), " subprocess error")),
- message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
- msg += cmStrCat(HeadLine("Command"), QuotedCommand(command), "\n\n");
- msg += cmStrCat(HeadLine("Output"), output,
- cmHasSuffix(output, '\n') ? "\n" : "\n\n");
- {
- std::lock_guard<std::mutex> lock(this->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 = static_cast<bool>(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);
- using IsIt = std::istreambuf_iterator<char>;
- 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(GenT genType)
- : GenType_(genType)
- {
- }
- cmQtAutoGenerator::~cmQtAutoGenerator() = default;
- bool cmQtAutoGenerator::InfoT::Read(std::istream& istr)
- {
- try {
- istr >> this->Json_;
- } catch (...) {
- return false;
- }
- return true;
- }
- bool cmQtAutoGenerator::InfoT::GetJsonArray(std::vector<std::string>& list,
- Json::Value const& jval)
- {
- Json::ArrayIndex const arraySize = jval.size();
- if (arraySize == 0) {
- return false;
- }
- bool picked = false;
- list.reserve(list.size() + arraySize);
- for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
- Json::Value const& ival = jval[ii];
- if (ival.isString()) {
- list.emplace_back(ival.asString());
- picked = true;
- }
- }
- return picked;
- }
- bool cmQtAutoGenerator::InfoT::GetJsonArray(
- std::unordered_set<std::string>& list, Json::Value const& jval)
- {
- Json::ArrayIndex const arraySize = jval.size();
- if (arraySize == 0) {
- return false;
- }
- bool picked = false;
- list.reserve(list.size() + arraySize);
- for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
- Json::Value const& ival = jval[ii];
- if (ival.isString()) {
- list.emplace(ival.asString());
- picked = true;
- }
- }
- return picked;
- }
- std::string cmQtAutoGenerator::InfoT::ConfigKey(cm::string_view key) const
- {
- return cmStrCat(key, '_', this->Gen_.InfoConfig());
- }
- bool cmQtAutoGenerator::InfoT::GetString(std::string const& key,
- std::string& value,
- bool required) const
- {
- Json::Value const& jval = this->Json_[key];
- if (!jval.isString()) {
- if (!jval.isNull() || required) {
- return this->LogError(cmStrCat(key, " is not a string."));
- }
- } else {
- value = jval.asString();
- if (value.empty() && required) {
- return this->LogError(cmStrCat(key, " is empty."));
- }
- }
- return true;
- }
- bool cmQtAutoGenerator::InfoT::GetStringConfig(std::string const& key,
- std::string& value,
- bool required) const
- {
- { // Try config
- std::string const configKey = this->ConfigKey(key);
- Json::Value const& jval = this->Json_[configKey];
- if (!jval.isNull()) {
- if (!jval.isString()) {
- return this->LogError(cmStrCat(configKey, " is not a string."));
- }
- value = jval.asString();
- if (required && value.empty()) {
- return this->LogError(cmStrCat(configKey, " is empty."));
- }
- return true;
- }
- }
- // Try plain
- return this->GetString(key, value, required);
- }
- bool cmQtAutoGenerator::InfoT::GetBool(std::string const& key, bool& value,
- bool required) const
- {
- Json::Value const& jval = this->Json_[key];
- if (jval.isBool()) {
- value = jval.asBool();
- } else {
- if (!jval.isNull() || required) {
- return this->LogError(cmStrCat(key, " is not a boolean."));
- }
- }
- return true;
- }
- bool cmQtAutoGenerator::InfoT::GetUInt(std::string const& key,
- unsigned int& value,
- bool required) const
- {
- Json::Value const& jval = this->Json_[key];
- if (jval.isUInt()) {
- value = jval.asUInt();
- } else {
- if (!jval.isNull() || required) {
- return this->LogError(cmStrCat(key, " is not an unsigned integer."));
- }
- }
- return true;
- }
- bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
- std::vector<std::string>& list,
- bool required) const
- {
- Json::Value const& jval = this->Json_[key];
- if (!jval.isArray()) {
- if (!jval.isNull() || required) {
- return this->LogError(cmStrCat(key, " is not an array."));
- }
- }
- return GetJsonArray(list, jval) || !required;
- }
- bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
- std::unordered_set<std::string>& list,
- bool required) const
- {
- Json::Value const& jval = this->Json_[key];
- if (!jval.isArray()) {
- if (!jval.isNull() || required) {
- return this->LogError(cmStrCat(key, " is not an array."));
- }
- }
- return GetJsonArray(list, jval) || !required;
- }
- bool cmQtAutoGenerator::InfoT::GetArrayConfig(std::string const& key,
- std::vector<std::string>& list,
- bool required) const
- {
- { // Try config
- std::string const configKey = this->ConfigKey(key);
- Json::Value const& jval = this->Json_[configKey];
- if (!jval.isNull()) {
- if (!jval.isArray()) {
- return this->LogError(cmStrCat(configKey, " is not an array string."));
- }
- if (!GetJsonArray(list, jval) && required) {
- return this->LogError(cmStrCat(configKey, " is empty."));
- }
- return true;
- }
- }
- // Try plain
- return this->GetArray(key, list, required);
- }
- bool cmQtAutoGenerator::InfoT::LogError(GenT genType,
- cm::string_view message) const
- {
- this->Gen_.Log().Error(genType,
- cmStrCat("Info error in info file\n",
- Quoted(this->Gen_.InfoFile()), ":\n",
- message));
- return false;
- }
- bool cmQtAutoGenerator::InfoT::LogError(cm::string_view message) const
- {
- return this->LogError(this->Gen_.GenType_, message);
- }
- std::string cmQtAutoGenerator::SettingsFind(cm::string_view content,
- cm::string_view key)
- {
- cm::string_view res;
- std::string const prefix = cmStrCat(key, ':');
- cm::string_view::size_type pos = content.find(prefix);
- if (pos != cm::string_view::npos) {
- pos += prefix.size();
- if (pos < content.size()) {
- cm::string_view::size_type posE = content.find('\n', pos);
- if ((posE != cm::string_view::npos) && (posE != pos)) {
- res = content.substr(pos, posE - pos);
- }
- }
- }
- return std::string(res);
- }
- std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
- {
- std::string res;
- if (cmHasPrefix(path, this->ProjectDirs().Source)) {
- res = cmStrCat("SRC:", path.substr(this->ProjectDirs().Source.size()));
- } else if (cmHasPrefix(path, this->ProjectDirs().Binary)) {
- res = cmStrCat("BIN:", path.substr(this->ProjectDirs().Binary.size()));
- } else {
- res = std::string(path);
- }
- return cmQtAutoGen::Quoted(res);
- }
- bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config,
- cm::string_view executableConfig)
- {
- // Info config
- this->InfoConfig_ = std::string(config);
- this->ExecutableConfig_ = std::string(executableConfig);
- // Info file
- this->InfoFile_ = std::string(infoFile);
- cmSystemTools::CollapseFullPath(this->InfoFile_);
- this->InfoDir_ = cmSystemTools::GetFilenamePath(this->InfoFile_);
- // Load info file time
- if (!this->InfoFileTime_.Load(this->InfoFile_)) {
- cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
- Quoted(this->InfoFile_),
- " is not readable\n"));
- return false;
- }
- {
- InfoT info(*this);
- // Read info file
- {
- cmsys::ifstream ifs(this->InfoFile_.c_str(),
- (std::ios::in | std::ios::binary));
- if (!ifs) {
- this->Log().Error(
- this->GenType_,
- cmStrCat("Could not to open info file ", Quoted(this->InfoFile_)));
- return false;
- }
- if (!info.Read(ifs)) {
- this->Log().Error(
- this->GenType_,
- cmStrCat("Could not read info file ", Quoted(this->InfoFile_)));
- return false;
- }
- }
- // -- Read common info settings
- {
- unsigned int verbosity = 0;
- // Info: setup project directories
- if (!info.GetUInt("VERBOSITY", verbosity, false) ||
- !info.GetString("CMAKE_SOURCE_DIR", this->ProjectDirs_.Source,
- true) ||
- !info.GetString("CMAKE_BINARY_DIR", this->ProjectDirs_.Binary,
- true) ||
- !info.GetString("CMAKE_CURRENT_SOURCE_DIR",
- this->ProjectDirs_.CurrentSource, true) ||
- !info.GetString("CMAKE_CURRENT_BINARY_DIR",
- this->ProjectDirs_.CurrentBinary, true)) {
- return false;
- }
- this->Logger_.RaiseVerbosity(verbosity);
- }
- // -- Call virtual init from info method.
- if (!this->InitFromInfo(info)) {
- return false;
- }
- }
- // Call virtual process method.
- return this->Process();
- }
|