Autogen: Use JSON instead of CMake script for info files

We used to store information for the _autogen target in a CMake script
file AutogenInfo.cmake, which was imported by a temporary cmake instance in
the _autogen target.  This introduced the overhead of creating a temporary
cmake instance and inherited the limitations of the CMake language which
only supports lists.

This patch introduces JSON files to pass information to AUTORCC and
autogen_ targets.  JSON files are more flexible for passing data, e.g. they
support nested lists.

The patch has the side effects that

- AutogenInfo.cmake is renamed to AutogenInfo.json
- AutogenOldSettings.txt is renamed to AutogenUsed.txt
- RCC<qrcBaseName><checksum>Info.cmake is renamed to
  AutoRcc_<qrcBaseName>_<checksum>_Info.json
- RCC<qrcBaseName><checksum>.lock is renamed to
  AutoRcc_<qrcBaseName>_<checksum>_Lock.lock
- RCC<qrcBaseName><checksum>Settings.txt is renamed to
  AutoRcc_<qrcBaseName>_<checksum>_Used.txt
This commit is contained in:
Sebastian Holtermann
2019-09-20 22:39:13 +02:00
committed by Brad King
parent 881e3cfbf9
commit d867e05892
10 changed files with 1091 additions and 901 deletions

View File

@@ -72,7 +72,6 @@ void MergeOptions(std::vector<std::string>& baseOpts,
// - Class definitions
unsigned int const cmQtAutoGen::ParallelMax = 64;
std::string const cmQtAutoGen::ListSep = "<<<S>>>";
cm::string_view cmQtAutoGen::GeneratorName(GenT genType)
{
@@ -162,6 +161,16 @@ std::string cmQtAutoGen::QuotedCommand(std::vector<std::string> const& command)
return res;
}
std::string cmQtAutoGen::FileNameWithoutLastExtension(cm::string_view filename)
{
auto slashPos = filename.rfind('/');
if (slashPos != cm::string_view::npos) {
filename.remove_prefix(slashPos + 1);
}
auto dotPos = filename.rfind('.');
return std::string(filename.substr(0, dotPos));
}
std::string cmQtAutoGen::ParentDir(cm::string_view filename)
{
auto slashPos = filename.rfind('/');

View File

@@ -62,8 +62,6 @@ public:
RCC // AUTORCC
};
/// @brief Nested lists separator
static std::string const ListSep;
/// @brief Maximum number of parallel threads/processes in a generator
static unsigned int const ParallelMax;
@@ -81,6 +79,9 @@ public:
static std::string QuotedCommand(std::vector<std::string> const& command);
/// @brief Returns the file name without path and extension (thread safe)
static std::string FileNameWithoutLastExtension(cm::string_view filename);
/// @brief Returns the parent directory of the file (thread safe)
static std::string ParentDir(cm::string_view filename);

File diff suppressed because it is too large Load Diff

View File

@@ -4,17 +4,16 @@
#define cmQtAutoGenInitializer_h
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmGeneratedFileStream.h"
#include "cmFilePathChecksum.h"
#include "cmQtAutoGen.h"
#include <cm/string_view>
#include <map>
#include <memory>
#include <ostream>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
@@ -32,6 +31,23 @@ class cmTarget;
class cmQtAutoGenInitializer : public cmQtAutoGen
{
public:
/** String value with per configuration variants. */
class ConfigString
{
public:
std::string Default;
std::unordered_map<std::string, std::string> Config;
};
/** String values with per configuration variants. */
template <typename C>
class ConfigStrings
{
public:
C Default;
std::unordered_map<std::string, C> Config;
};
/** rcc job. */
class Qrc
{
@@ -41,8 +57,7 @@ public:
std::string QrcName;
std::string QrcPathChecksum;
std::string InfoFile;
std::string SettingsFile;
std::map<std::string, std::string> ConfigSettingsFile;
ConfigString SettingsFile;
std::string OutputFile;
bool Generated = false;
bool Unique = false;
@@ -63,7 +78,7 @@ public:
};
using MUFileHandle = std::unique_ptr<MUFile>;
/** Abstract moc/uic/rcc generator variables base class */
/** Abstract moc/uic/rcc generator variables base class. */
struct GenVarsT
{
bool Enabled = false;
@@ -81,39 +96,6 @@ public:
, GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
};
/** Writes a CMake info file. */
class InfoWriter
{
public:
/** Open the given file. */
InfoWriter(std::string const& filename);
/** @return True if the file is open. */
explicit operator bool() const { return static_cast<bool>(Ofs_); }
void Write(cm::string_view text) { Ofs_ << text; }
void Write(cm::string_view, std::string const& value);
void WriteUInt(cm::string_view, unsigned int value);
template <class C>
void WriteStrings(cm::string_view, C const& container);
void WriteConfig(cm::string_view,
std::map<std::string, std::string> const& map);
template <class C>
void WriteConfigStrings(cm::string_view,
std::map<std::string, C> const& map);
void WriteNestedLists(cm::string_view,
std::vector<std::vector<std::string>> const& lists);
private:
template <class IT>
static std::string ListJoin(IT it_begin, IT it_end);
static std::string ConfigKey(cm::string_view, std::string const& config);
private:
cmGeneratedFileStream Ofs_;
};
public:
/** @return The detected Qt version and the required Qt major version. */
static std::pair<IntegerVersion, unsigned int> GetQtVersion(
@@ -153,6 +135,12 @@ private:
cm::string_view genNameUpper);
void AddCleanFile(std::string const& fileName);
void ConfigFileNames(ConfigString& configString, cm::string_view prefix,
cm::string_view suffix);
void ConfigFileClean(ConfigString& configString);
std::string GetMocBuildPath(MUFile const& muf);
bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
bool ignoreMissingTarget) const;
@@ -162,16 +150,17 @@ private:
cmGlobalGenerator* GlobalGen = nullptr;
cmLocalGenerator* LocalGen = nullptr;
cmMakefile* Makefile = nullptr;
cmFilePathChecksum const PathCheckSum;
// -- Configuration
IntegerVersion QtVersion;
unsigned int Verbosity = 0;
bool MultiConfig = false;
std::string ConfigDefault;
std::vector<std::string> ConfigsList;
std::string Verbosity;
std::string TargetsFolder;
bool CMP0071Accept = false;
bool CMP0071Warn = false;
std::string ConfigDefault;
std::vector<std::string> ConfigsList;
std::string TargetsFolder;
/** Common directories. */
struct
@@ -179,8 +168,7 @@ private:
std::string Info;
std::string Build;
std::string Work;
std::string Include;
std::map<std::string, std::string> ConfigInclude;
ConfigString Include;
std::string IncludeGenExp;
} Dir;
@@ -190,12 +178,11 @@ private:
std::string Name;
bool GlobalTarget = false;
// Settings
std::string Parallel;
unsigned int Parallel = 1;
// Configuration files
std::string InfoFile;
std::string SettingsFile;
std::string ParseCacheFile;
std::map<std::string, std::string> ConfigSettingsFile;
ConfigString SettingsFile;
ConfigString ParseCacheFile;
// Dependencies
bool DependOrigin = false;
std::set<std::string> DependFiles;
@@ -212,26 +199,37 @@ private:
MocT()
: GenVarsT(GenT::MOC){};
std::string PredefsCmd;
std::vector<std::string> Includes;
std::map<std::string, std::vector<std::string>> ConfigIncludes;
std::set<std::string> Defines;
std::map<std::string, std::set<std::string>> ConfigDefines;
std::string MocsCompilation;
bool RelaxedMode = false;
bool PathPrefix = false;
std::string CompilationFile;
// Compiler implicit pre defines
std::vector<std::string> PredefsCmd;
ConfigString PredefsFile;
// Defines
ConfigStrings<std::set<std::string>> Defines;
// Includes
ConfigStrings<std::vector<std::string>> Includes;
// Options
std::vector<std::string> Options;
// Filters
std::vector<std::string> MacroNames;
std::vector<std::pair<std::string, std::string>> DependFilters;
// Utility
std::unordered_set<std::string> EmittedBuildPaths;
} Moc;
/** uic variables. */
struct UicT : public GenVarsT
{
using UiFileT = std::pair<std::string, std::vector<std::string>>;
UicT()
: GenVarsT(GenT::UIC){};
std::set<std::string> SkipUi;
std::vector<UiFileT> UiFiles;
ConfigStrings<std::vector<std::string>> Options;
std::vector<std::string> SearchPaths;
std::vector<std::string> Options;
std::map<std::string, std::vector<std::string>> ConfigOptions;
std::vector<std::string> FileFiles;
std::vector<std::vector<std::string>> FileOptions;
} Uic;
/** rcc variables. */

View File

@@ -2,19 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQtAutoGenerator.h"
#include <cm/memory>
#include "cmsys/FStream.hxx"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmQtAutoGen.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
#include "cm_jsoncpp_reader.h"
#include "cmsys/FStream.hxx"
cmQtAutoGenerator::Logger::Logger()
{
@@ -44,13 +36,10 @@ cmQtAutoGenerator::Logger::Logger()
cmQtAutoGenerator::Logger::~Logger() = default;
void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value)
void cmQtAutoGenerator::Logger::RaiseVerbosity(unsigned int value)
{
unsigned long verbosity = 0;
if (cmStrToULong(value, &verbosity)) {
if (this->Verbosity_ < verbosity) {
this->Verbosity_ = static_cast<unsigned int>(verbosity);
}
if (this->Verbosity_ < value) {
this->Verbosity_ = value;
}
}
@@ -214,7 +203,10 @@ bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
return differs;
}
cmQtAutoGenerator::cmQtAutoGenerator() = default;
cmQtAutoGenerator::cmQtAutoGenerator(GenT genType)
: GenType_(genType)
{
}
cmQtAutoGenerator::~cmQtAutoGenerator() = default;
@@ -223,7 +215,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
{
// Info settings
InfoFile_ = infoFile;
cmSystemTools::ConvertToUnixSlashes(InfoFile_);
cmSystemTools::CollapseFullPath(InfoFile_);
if (!InfoFileTime_.Load(InfoFile_)) {
cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
Quoted(InfoFile_), " is not readable\n"));
@@ -232,29 +224,221 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
InfoConfig_ = config;
bool success = false;
// Read info file
{
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());
cmsys::ifstream ifs(InfoFile_.c_str(), (std::ios::in | std::ios::binary));
if (!ifs) {
Log().Error(GenType_,
cmStrCat("Could not to open info file ", Quoted(InfoFile_)));
return false;
}
try {
ifs >> Info_;
} catch (...) {
Log().Error(GenType_,
cmStrCat("Could not read info file ", Quoted(InfoFile_)));
return false;
}
}
if (success) {
success = this->Process();
// Info: setup logger
{
unsigned int value = 0;
if (!InfoUInt("VERBOSITY", value, false)) {
return false;
}
Logger_.RaiseVerbosity(value);
}
return success;
// Info: setup project directories
if (!InfoString("CMAKE_SOURCE_DIR", ProjectDirs_.Source, true) ||
!InfoString("CMAKE_BINARY_DIR", ProjectDirs_.Binary, true) ||
!InfoString("CMAKE_CURRENT_SOURCE_DIR", ProjectDirs_.CurrentSource,
true) ||
!InfoString("CMAKE_CURRENT_BINARY_DIR", ProjectDirs_.CurrentBinary,
true)) {
return false;
}
if (!this->InitFromInfo()) {
return false;
}
// Clear info
Info_ = Json::nullValue;
return this->Process();
}
bool cmQtAutoGenerator::LogInfoError(GenT genType,
cm::string_view message) const
{
this->Log().Error(
genType,
cmStrCat("Info error in info file\n", Quoted(InfoFile()), ":\n", message));
return false;
}
bool cmQtAutoGenerator::LogInfoError(cm::string_view message) const
{
return LogInfoError(GenType_, message);
}
bool cmQtAutoGenerator::JsonGetArray(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::JsonGetArray(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::InfoConfigKey(std::string const& key) const
{
return cmStrCat(key, '_', InfoConfig());
}
bool cmQtAutoGenerator::InfoString(std::string const& key, std::string& value,
bool required) const
{
Json::Value const& jval = Info()[key];
if (!jval.isString()) {
if (!jval.isNull() || required) {
return LogInfoError(cmStrCat(key, " is not a string."));
}
} else {
value = jval.asString();
if (value.empty() && required) {
return LogInfoError(cmStrCat(key, " is empty."));
}
}
return true;
}
bool cmQtAutoGenerator::InfoStringConfig(std::string const& key,
std::string& value,
bool required) const
{
{ // Try config
std::string const configKey = InfoConfigKey(key);
Json::Value const& jval = Info_[configKey];
if (!jval.isNull()) {
if (!jval.isString()) {
return LogInfoError(cmStrCat(configKey, " is not a string."));
}
value = jval.asString();
if (required && value.empty()) {
return LogInfoError(cmStrCat(configKey, " is empty."));
}
return true;
}
}
// Try plain
return InfoString(key, value, required);
}
bool cmQtAutoGenerator::InfoBool(std::string const& key, bool& value,
bool required) const
{
Json::Value const& jval = Info()[key];
if (jval.isBool()) {
value = jval.asBool();
} else {
if (!jval.isNull() || required) {
return LogInfoError(cmStrCat(key, " is not a boolean."));
}
}
return true;
}
bool cmQtAutoGenerator::InfoUInt(std::string const& key, unsigned int& value,
bool required) const
{
Json::Value const& jval = Info()[key];
if (jval.isUInt()) {
value = jval.asUInt();
} else {
if (!jval.isNull() || required) {
return LogInfoError(cmStrCat(key, " is not an unsigned integer."));
}
}
return true;
}
bool cmQtAutoGenerator::InfoArray(std::string const& key,
std::vector<std::string>& list,
bool required) const
{
Json::Value const& jval = Info()[key];
if (!jval.isArray()) {
if (!jval.isNull() || required) {
return LogInfoError(cmStrCat(key, " is not an array."));
}
}
return JsonGetArray(list, jval) || !required;
}
bool cmQtAutoGenerator::InfoArray(std::string const& key,
std::unordered_set<std::string>& list,
bool required) const
{
Json::Value const& jval = Info()[key];
if (!jval.isArray()) {
if (!jval.isNull() || required) {
return LogInfoError(cmStrCat(key, " is not an array."));
}
}
return JsonGetArray(list, jval) || !required;
}
bool cmQtAutoGenerator::InfoArrayConfig(std::string const& key,
std::vector<std::string>& list,
bool required) const
{
{ // Try config
std::string const configKey = InfoConfigKey(key);
Json::Value const& jval = Info()[configKey];
if (!jval.isNull()) {
if (!jval.isArray()) {
return LogInfoError(cmStrCat(configKey, " is not an array string."));
}
if (!JsonGetArray(list, jval) && required) {
return LogInfoError(cmStrCat(configKey, " is empty."));
}
return true;
}
}
// Try plain
return InfoArray(key, list, required);
}
std::string cmQtAutoGenerator::SettingsFind(std::string const& content,

View File

@@ -7,15 +7,15 @@
#include "cmFileTime.h"
#include "cmQtAutoGen.h"
#include "cm_jsoncpp_value.h"
#include <cm/string_view>
#include <mutex>
#include <string>
#include <unordered_set>
#include <vector>
class cmMakefile;
/** \class cmQtAutoGenerator
* \brief Base class for QtAutoGen generators
*/
@@ -34,7 +34,7 @@ public:
// -- Verbosity
unsigned int Verbosity() const { return this->Verbosity_; }
void SetVerbosity(unsigned int value) { this->Verbosity_ = value; }
void RaiseVerbosity(std::string const& value);
void RaiseVerbosity(unsigned int value);
bool Verbose() const { return (this->Verbosity_ != 0); }
void SetVerbose(bool value) { this->Verbosity_ = value ? 1 : 0; }
// -- Color output
@@ -80,7 +80,7 @@ public:
public:
// -- Constructors
cmQtAutoGenerator();
cmQtAutoGenerator(GenT genType);
virtual ~cmQtAutoGenerator();
cmQtAutoGenerator(cmQtAutoGenerator const&) = delete;
@@ -91,10 +91,39 @@ public:
// -- InfoFile
std::string const& InfoFile() const { return InfoFile_; }
Json::Value const& Info() const { return Info_; }
cmFileTime const& InfoFileTime() const { return InfoFileTime_; }
std::string const& InfoDir() const { return InfoDir_; }
std::string const& InfoConfig() const { return InfoConfig_; }
bool LogInfoError(GenT genType, cm::string_view message) const;
bool LogInfoError(cm::string_view message) const;
/** Returns true if strings were appended to the list. */
static bool JsonGetArray(std::vector<std::string>& list,
Json::Value const& jval);
/** Returns true if strings were found in the JSON array. */
static bool JsonGetArray(std::unordered_set<std::string>& list,
Json::Value const& jval);
std::string InfoConfigKey(std::string const& key) const;
/** Returns false if the JSON value isn't a string. */
bool InfoString(std::string const& key, std::string& value,
bool required) const;
bool InfoStringConfig(std::string const& key, std::string& value,
bool required) const;
bool InfoBool(std::string const& key, bool& value, bool required) const;
bool InfoUInt(std::string const& key, unsigned int& value,
bool required) const;
/** Returns false if the JSON value isn't an array. */
bool InfoArray(std::string const& key, std::vector<std::string>& list,
bool required) const;
bool InfoArray(std::string const& key, std::unordered_set<std::string>& list,
bool required) const;
bool InfoArrayConfig(std::string const& key, std::vector<std::string>& list,
bool required) const;
// -- Directories
ProjectDirsT const& ProjectDirs() const { return ProjectDirs_; }
@@ -104,16 +133,22 @@ public:
protected:
// -- Abstract processing interface
virtual bool Init(cmMakefile* makefile) = 0;
virtual bool InitFromInfo() = 0;
virtual bool Process() = 0;
ProjectDirsT& ProjectDirsRef() { return ProjectDirs_; }
// - Utility classes
Logger const& Log() const { return Logger_; }
private:
// -- Info settings
// -- Generator type
GenT GenType_;
// -- Logging
Logger Logger_;
// -- Info file
std::string InfoFile_;
cmFileTime InfoFileTime_;
std::string InfoDir_;
std::string InfoConfig_;
Json::Value Info_;
// -- Directories
ProjectDirsT ProjectDirs_;
};

View File

@@ -11,19 +11,22 @@
#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmQtAutoGen.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
#include "cm_jsoncpp_value.h"
#include "cmsys/FStream.hxx"
#if defined(__APPLE__)
# include <unistd.h>
#endif
static constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
static constexpr std::size_t UiUnderscoreLength = 3; // Length of "ui_"
namespace {
constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
constexpr std::size_t UiUnderscoreLength = 3; // Length of "ui_"
} // End of unnamed namespace
cmQtAutoMocUic::IncludeKeyT::IncludeKeyT(std::string const& key,
std::size_t basePrefixLength)
@@ -1464,10 +1467,10 @@ void cmQtAutoMocUic::JobCompileUicT::Process()
std::vector<std::string> cmd;
cmd.push_back(UicConst().Executable);
{
std::vector<std::string> allOpts = UicConst().TargetOptions;
auto optionIt = UicConst().Options.find(sourceFile);
if (optionIt != UicConst().Options.end()) {
UicMergeOptions(allOpts, optionIt->second,
std::vector<std::string> allOpts = UicConst().Options;
auto optionIt = UicConst().UiFiles.find(sourceFile);
if (optionIt != UicConst().UiFiles.end()) {
UicMergeOptions(allOpts, optionIt->second.Options,
(BaseConst().QtVersionMajor == 5));
}
cmAppend(cmd, allOpts);
@@ -1548,338 +1551,310 @@ void cmQtAutoMocUic::JobFinishT::Process()
Gen()->AbortSuccess();
}
cmQtAutoMocUic::cmQtAutoMocUic() = default;
cmQtAutoMocUic::cmQtAutoMocUic()
: cmQtAutoGenerator(GenT::GEN)
{
}
cmQtAutoMocUic::~cmQtAutoMocUic() = default;
bool cmQtAutoMocUic::Init(cmMakefile* makefile)
bool cmQtAutoMocUic::InitFromInfo()
{
// Utility lambdas
auto InfoGet = [makefile](cm::string_view key) {
return makefile->GetSafeDefinition(std::string(key));
};
auto InfoGetBool = [makefile](cm::string_view key) {
return makefile->IsOn(std::string(key));
};
auto InfoGetList =
[makefile](cm::string_view key) -> std::vector<std::string> {
return cmExpandedList(makefile->GetSafeDefinition(std::string(key)));
};
auto InfoGetLists =
[makefile](cm::string_view key) -> std::vector<std::vector<std::string>> {
std::vector<std::vector<std::string>> lists;
{
std::string const value = makefile->GetSafeDefinition(std::string(key));
std::string::size_type pos = 0;
while (pos < value.size()) {
std::string::size_type next = value.find(ListSep, pos);
std::string::size_type length =
(next != std::string::npos) ? next - pos : value.size() - pos;
// Remove enclosing braces
if (length >= 2) {
std::string::const_iterator itBeg = value.begin() + (pos + 1);
std::string::const_iterator itEnd = itBeg + (length - 2);
lists.emplace_back(cmExpandedList(std::string(itBeg, itEnd)));
}
pos += length;
pos += ListSep.size();
}
}
return lists;
};
auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string {
if (const char* valueConf =
makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) {
return std::string(valueConf);
}
return makefile->GetSafeDefinition(std::string(key));
};
auto InfoGetConfigList =
[&InfoGetConfig](cm::string_view key) -> std::vector<std::string> {
return cmExpandedList(InfoGetConfig(key));
};
auto LogInfoError = [this](cm::string_view msg) -> bool {
this->Log().Error(GenT::GEN,
cmStrCat("In ", Quoted(this->InfoFile()), ":\n", msg));
// -- Required settings
if (!InfoBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
!InfoUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) ||
!InfoUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
!InfoString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
!InfoStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir, true) ||
!InfoString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
!InfoStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile, true) ||
!InfoStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
!InfoArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
!InfoString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
!InfoString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
return false;
};
auto MatchSizes = [&LogInfoError](cm::string_view keyA, cm::string_view keyB,
std::size_t sizeA,
std::size_t sizeB) -> bool {
if (sizeA == sizeB) {
return true;
}
return LogInfoError(cmStrCat("Lists sizes mismatch ", keyA, '(', sizeA,
") ", keyB, '(', sizeB, ')'));
};
// -- Read info file
if (!makefile->ReadListFile(InfoFile())) {
return LogInfoError("File processing failed");
}
// -- Meta
Logger_.RaiseVerbosity(InfoGet("AM_VERBOSITY"));
BaseConst_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
{
unsigned long num = 1;
if (cmStrToULong(InfoGet("AM_PARALLEL"), &num)) {
num = std::max<unsigned long>(num, 1);
num = std::min<unsigned long>(num, ParallelMax);
}
WorkerPool_.SetThreadCount(static_cast<unsigned int>(num));
}
BaseConst_.HeaderExtensions =
makefile->GetCMakeInstance()->GetHeaderExtensions();
// - Files and directories
ProjectDirsRef().Source = InfoGet("AM_CMAKE_SOURCE_DIR");
ProjectDirsRef().Binary = InfoGet("AM_CMAKE_BINARY_DIR");
ProjectDirsRef().CurrentSource = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
ProjectDirsRef().CurrentBinary = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
BaseConst_.AutogenBuildDir = InfoGet("AM_BUILD_DIR");
if (BaseConst_.AutogenBuildDir.empty()) {
return LogInfoError("Autogen build directory missing.");
}
BaseConst_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR");
if (BaseConst_.AutogenIncludeDir.empty()) {
return LogInfoError("Autogen include directory missing.");
}
BaseConst_.CMakeExecutable = InfoGetConfig("AM_CMAKE_EXECUTABLE");
if (BaseConst_.CMakeExecutable.empty()) {
return LogInfoError("CMake executable file name missing.");
}
// -- Checks
if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
return LogInfoError(cmStrCat("The CMake executable ",
MessagePath(BaseConst_.CMakeExecutable),
" does not exist."));
}
BaseConst_.ParseCacheFile = InfoGetConfig("AM_PARSE_CACHE_FILE");
if (BaseConst_.ParseCacheFile.empty()) {
return LogInfoError("Parse cache file name missing.");
}
// - Settings file
SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
if (SettingsFile_.empty()) {
return LogInfoError("Settings file name missing.");
}
// -- Evaluate values
BaseConst_.ThreadCount = std::min(BaseConst_.ThreadCount, ParallelMax);
WorkerPool_.SetThreadCount(BaseConst_.ThreadCount);
// - Qt environment
{
unsigned long qtv = BaseConst_.QtVersionMajor;
if (cmStrToULong(InfoGet("AM_QT_VERSION_MAJOR"), &qtv)) {
BaseConst_.QtVersionMajor = static_cast<unsigned int>(qtv);
}
}
// - Moc
MocConst_.Executable = InfoGet("AM_QT_MOC_EXECUTABLE");
if (!MocConst().Executable.empty()) {
// -- Moc
if (!MocConst_.Executable.empty()) {
// -- Moc is enabled
MocConst_.Enabled = true;
// Load the executable file time
// -- Temporary buffers
struct
{
std::vector<std::string> MacroNames;
std::vector<std::string> DependFilters;
} tmp;
// -- Required settings
if (!InfoBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
!InfoBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
!InfoArray("MOC_SKIP", MocConst_.SkipList, false) ||
!InfoArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions, false) ||
!InfoArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
!InfoArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
!InfoStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
true) ||
!InfoArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
!InfoStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
!MocConst_.PredefsCmd.empty()) ||
!InfoArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
!InfoArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
return false;
}
// -- Evaluate settings
for (std::string const& item : tmp.MacroNames) {
MocConst_.MacroFilters.emplace_back(
item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
}
// Dependency filters
{
Json::Value const& val = Info()["MOC_DEPEND_FILTERS"];
if (!val.isArray()) {
return LogInfoError("MOC_DEPEND_FILTERS JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
auto testEntry = [this, ii](bool test,
cm::string_view message) -> bool {
if (!test) {
this->LogInfoError(
cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", message));
}
return !test;
};
Json::Value const& pairVal = val[ii];
if (testEntry(pairVal.isArray(), "JSON value is not an array.") ||
testEntry(pairVal.size() == 2, "JSON array size invalid.")) {
return false;
}
Json::Value const& keyVal = pairVal[0u];
Json::Value const& expVal = pairVal[1u];
if (testEntry(keyVal.isString(),
"JSON value for keyword is not a string.") ||
testEntry(expVal.isString(),
"JSON value for regular expression is not a string.")) {
return false;
}
std::string const key = keyVal.asString();
std::string const exp = expVal.asString();
if (testEntry(!key.empty(), "Keyword is empty.") ||
testEntry(!exp.empty(), "Regular expression is empty.")) {
return false;
}
this->MocConst_.DependFilters.emplace_back(key, exp);
if (testEntry(
this->MocConst_.DependFilters.back().Exp.is_valid(),
cmStrCat("Regular expression compilation failed.\nKeyword: ",
Quoted(key), "\nExpression: ", Quoted(exp)))) {
return false;
}
}
}
// Check if moc executable exists (by reading the file time)
if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
return LogInfoError(cmStrCat("The moc executable ",
MessagePath(MocConst_.Executable),
" does not exist."));
}
for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) {
MocConst_.SkipList.insert(std::move(sfl));
}
MocConst_.Definitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
MocConst_.IncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
MocConst_.OptionsExtra = InfoGetList("AM_MOC_OPTIONS");
MocConst_.RelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
MocConst_.PathPrefix = InfoGetBool("AM_MOC_PATH_PREFIX");
for (std::string const& item : InfoGetList("AM_MOC_MACRO_NAMES")) {
MocConst_.MacroFilters.emplace_back(
item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
}
{
auto addFilter = [this, &LogInfoError](std::string const& key,
std::string const& exp) -> bool {
auto filterErr = [&LogInfoError, &key,
&exp](cm::string_view err) -> bool {
return LogInfoError(cmStrCat("AUTOMOC_DEPEND_FILTERS: ", err, '\n',
" Key: ", Quoted(key), '\n',
" Exp: ", Quoted(exp), '\n'));
};
if (key.empty()) {
return filterErr("Key is empty");
}
if (exp.empty()) {
return filterErr("Regular expression is empty");
}
this->MocConst_.DependFilters.emplace_back(key, exp);
if (!this->MocConst_.DependFilters.back().Exp.is_valid()) {
return filterErr("Regular expression compiling failed");
}
return true;
};
// Insert default filter for Q_PLUGIN_METADATA
if (BaseConst().QtVersionMajor != 4) {
if (!addFilter("Q_PLUGIN_METADATA",
"[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
"[^\\)]*FILE[ \t]*\"([^\"]+)\"")) {
return false;
}
}
// Insert user defined dependency filters
std::vector<std::string> flts = InfoGetList("AM_MOC_DEPEND_FILTERS");
if ((flts.size() % 2) != 0) {
return LogInfoError(
"AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
}
for (auto itC = flts.begin(), itE = flts.end(); itC != itE; itC += 2) {
if (!addFilter(*itC, *(itC + 1))) {
return false;
}
}
}
MocConst_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
}
// - Uic
UicConst_.Executable = InfoGet("AM_QT_UIC_EXECUTABLE");
if (!UicConst().Executable.empty()) {
// -- Uic
if (!UicConst_.Executable.empty()) {
// Uic is enabled
UicConst_.Enabled = true;
// Load the executable file time
// -- Required settings
if (!InfoArray("UIC_SKIP", UicConst_.SkipList, false) ||
!InfoArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
!InfoArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
return false;
}
// .ui files
{
Json::Value const& val = Info()["UIC_UI_FILES"];
if (!val.isArray()) {
return LogInfoError("UIC_UI_FILES JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
auto testEntry = [this, ii](bool test,
cm::string_view message) -> bool {
if (!test) {
this->LogInfoError(
cmStrCat("UIC_UI_FILES entry ", ii, ": ", message));
}
return !test;
};
Json::Value const& entry = val[ii];
if (testEntry(entry.isArray(), "JSON value is not an array.") ||
testEntry(entry.size() == 2, "JSON array size invalid.")) {
return false;
}
Json::Value const& entryName = entry[0u];
Json::Value const& entryOptions = entry[1u];
if (testEntry(entryName.isString(),
"JSON value for name is not a string.") ||
testEntry(entryOptions.isArray(),
"JSON value for options is not an array.")) {
return false;
}
auto& uiFile = UicConst_.UiFiles[entryName.asString()];
JsonGetArray(uiFile.Options, entryOptions);
}
}
// -- Evaluate settings
// Check if uic executable exists (by reading the file time)
if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
return LogInfoError(cmStrCat("The uic executable ",
MessagePath(UicConst_.Executable),
" does not exist."));
}
for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) {
UicConst_.SkipList.insert(std::move(sfl));
}
UicConst_.SearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
UicConst_.TargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
{
cm::string_view const keyFiles = "AM_UIC_OPTIONS_FILES";
cm::string_view const keyOpts = "AM_UIC_OPTIONS_OPTIONS";
auto sources = InfoGetList(keyFiles);
auto options = InfoGetLists(keyOpts);
if (!MatchSizes(keyFiles, keyOpts, sources.size(), options.size())) {
return false;
}
auto fitEnd = sources.cend();
auto fit = sources.begin();
auto oit = options.begin();
while (fit != fitEnd) {
UicConst_.Options[*fit] = std::move(*oit);
++fit;
++oit;
}
}
}
// Headers
// -- Headers
{
// Get file lists
cm::string_view const keyFiles = "AM_HEADERS";
cm::string_view const keyFlags = "AM_HEADERS_FLAGS";
std::vector<std::string> files = InfoGetList(keyFiles);
std::vector<std::string> flags = InfoGetList(keyFlags);
std::vector<std::string> builds;
if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
return false;
}
if (MocConst().Enabled) {
cm::string_view const keyPaths = "AM_HEADERS_BUILD_PATHS";
builds = InfoGetList(keyPaths);
if (!MatchSizes(keyFiles, keyPaths, files.size(), builds.size())) {
return false;
}
Json::Value const& val = Info()["HEADERS"];
if (!val.isArray()) {
return LogInfoError("HEADERS JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
auto testEntry = [this, ii](bool test, cm::string_view message) -> bool {
if (!test) {
this->LogInfoError(cmStrCat("HEADERS entry ", ii, ": ", message));
}
return !test;
};
// Process file lists
for (std::size_t ii = 0; ii != files.size(); ++ii) {
std::string& fileName(files[ii]);
std::string const& fileFlags(flags[ii]);
if (fileFlags.size() != 2) {
LogInfoError(cmStrCat("Invalid flags string size ", fileFlags.size(),
"in ", keyFlags));
Json::Value const& entry = val[ii];
if (testEntry(entry.isArray(), "JSON value is not an array.") ||
testEntry(entry.size() == 3, "JSON array size invalid.")) {
return false;
}
Json::Value const& entryName = entry[0u];
Json::Value const& entryFlags = entry[1u];
Json::Value const& entryBuild = entry[2u];
if (testEntry(entryName.isString(),
"JSON value for name is not a string.") ||
testEntry(entryFlags.isString(),
"JSON value for flags is not a string.") ||
testEntry(entryBuild.isString(),
"JSON value for build path is not a string.")) {
return false;
}
std::string name = entryName.asString();
std::string flags = entryFlags.asString();
std::string build = entryBuild.asString();
if (testEntry(flags.size() == 2, "Invalid flags string size")) {
return false;
}
cmFileTime fileTime;
if (!fileTime.Load(fileName)) {
LogInfoError(cmStrCat("The header file ", this->MessagePath(fileName),
if (!fileTime.Load(name)) {
LogInfoError(cmStrCat("The header file ", this->MessagePath(name),
" does not exist."));
return false;
}
SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(fileName);
SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
sourceHandle->FileTime = fileTime;
sourceHandle->IsHeader = true;
sourceHandle->Moc = (fileFlags[0] == 'M');
sourceHandle->Uic = (fileFlags[1] == 'U');
sourceHandle->Moc = (flags[0] == 'M');
sourceHandle->Uic = (flags[1] == 'U');
if (sourceHandle->Moc && MocConst().Enabled) {
sourceHandle->BuildPath = std::move(builds[ii]);
if (sourceHandle->BuildPath.empty()) {
return LogInfoError("Header file build path is empty");
if (build.empty()) {
return LogInfoError(
cmStrCat("Header file ", ii, " build path is empty"));
}
sourceHandle->BuildPath = std::move(build);
}
BaseEval().Headers.emplace(std::move(fileName), std::move(sourceHandle));
BaseEval().Headers.emplace(std::move(name), std::move(sourceHandle));
}
}
// Sources
// -- Sources
{
cm::string_view const keyFiles = "AM_SOURCES";
cm::string_view const keyFlags = "AM_SOURCES_FLAGS";
std::vector<std::string> files = InfoGetList(keyFiles);
std::vector<std::string> flags = InfoGetList(keyFlags);
if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
return false;
Json::Value const& val = Info()["SOURCES"];
if (!val.isArray()) {
return LogInfoError("SOURCES JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
auto testEntry = [this, ii](bool test, cm::string_view message) -> bool {
if (!test) {
this->LogInfoError(cmStrCat("SOURCES entry ", ii, ": ", message));
}
return !test;
};
// Process file lists
for (std::size_t ii = 0; ii != files.size(); ++ii) {
std::string& fileName(files[ii]);
std::string const& fileFlags(flags[ii]);
if (fileFlags.size() != 2) {
LogInfoError(cmStrCat("Invalid flags string size ", fileFlags.size(),
"in ", keyFlags));
Json::Value const& entry = val[ii];
if (testEntry(entry.isArray(), "JSON value is not an array.") ||
testEntry(entry.size() == 2, "JSON array size invalid.")) {
return false;
}
Json::Value const& entryName = entry[0u];
Json::Value const& entryFlags = entry[1u];
if (testEntry(entryName.isString(),
"JSON value for name is not a string.") ||
testEntry(entryFlags.isString(),
"JSON value for flags is not a string.")) {
return false;
}
std::string name = entryName.asString();
std::string flags = entryFlags.asString();
if (testEntry(flags.size() == 2, "Invalid flags string size")) {
return false;
}
cmFileTime fileTime;
if (!fileTime.Load(fileName)) {
LogInfoError(cmStrCat("The source file ", this->MessagePath(fileName),
if (!fileTime.Load(name)) {
LogInfoError(cmStrCat("The source file ", this->MessagePath(name),
" does not exist."));
return false;
}
SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(fileName);
SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
sourceHandle->FileTime = fileTime;
sourceHandle->IsHeader = false;
sourceHandle->Moc = (fileFlags[0] == 'M');
sourceHandle->Uic = (fileFlags[1] == 'U');
BaseEval().Sources.emplace(std::move(fileName), std::move(sourceHandle));
sourceHandle->Moc = (flags[0] == 'M');
sourceHandle->Uic = (flags[1] == 'U');
BaseEval().Sources.emplace(std::move(name), std::move(sourceHandle));
}
}
// Init derived information
// ------------------------
// -- Init derived information
// Moc variables
if (MocConst().Enabled) {
// Mocs compilation file
MocConst_.CompFileAbs = AbsoluteBuildPath("mocs_compilation.cpp");
// Moc predefs file
if (!MocConst_.PredefsCmd.empty()) {
std::string pathRel;
if (BaseConst_.MultiConfig) {
pathRel = cmStrCat("moc_predefs_", InfoConfig(), ".h");
} else {
pathRel = "moc_predefs.h";
}
MocConst_.PredefsFileAbs = AbsoluteBuildPath(pathRel);
}
// Compose moc includes list
{
// Compute framework paths
@@ -2031,11 +2006,11 @@ void cmQtAutoMocUic::SettingsFileRead()
if (UicConst().Enabled) {
cryptoHash.Initialize();
cha(UicConst().Executable);
std::for_each(UicConst().TargetOptions.begin(),
UicConst().TargetOptions.end(), cha);
for (const auto& item : UicConst().Options) {
std::for_each(UicConst().Options.begin(), UicConst().Options.end(), cha);
for (const auto& item : UicConst().UiFiles) {
cha(item.first);
std::for_each(item.second.begin(), item.second.end(), cha);
auto const& opts = item.second.Options;
std::for_each(opts.begin(), opts.end(), cha);
}
SettingsStringUic_ = cryptoHash.FinalizeHex();
}
@@ -2080,7 +2055,7 @@ bool cmQtAutoMocUic::SettingsFileWrite()
if (Log().Verbose()) {
Log().Info(
GenT::GEN,
cmStrCat("Writing settings file ", MessagePath(SettingsFile_)));
cmStrCat("Writing the settings file ", MessagePath(SettingsFile_)));
}
// Compose settings file content
std::string content;

View File

@@ -25,8 +25,6 @@
#include <utility>
#include <vector>
class cmMakefile;
/** \class cmQtAutoMocUic
* \brief AUTOMOC and AUTOUIC generator
*/
@@ -42,17 +40,21 @@ public:
public:
// -- Types
/** Include string with sub parts. */
struct IncludeKeyT
{
IncludeKeyT(std::string const& key, std::size_t basePrefixLength);
std::string Key; // Full include string
std::string Dir; // Include directory
std::string Base; // Base part of the include file name
};
/** Search key plus regular expression pair. */
struct KeyExpT
{
KeyExpT() = default;
KeyExpT(const char* key, const char* exp)
: Key(key)
, Exp(exp)
{
}
KeyExpT(std::string key, std::string const& exp)
: Key(std::move(key))
, Exp(exp)
@@ -63,16 +65,6 @@ public:
cmsys::RegularExpression Exp;
};
/** Include string with sub parts. */
struct IncludeKeyT
{
IncludeKeyT(std::string const& key, std::size_t basePrefixLength);
std::string Key; // Full include string
std::string Dir; // Include directory
std::string Base; // Base part of the include file name
};
/** Source file parsing cache. */
class ParseCacheT
{
@@ -169,6 +161,7 @@ public:
// - Config
bool MultiConfig = false;
unsigned int QtVersionMajor = 4;
unsigned int ThreadCount = 0;
// - Directories
std::string AutogenBuildDir;
std::string AutogenIncludeDir;
@@ -251,6 +244,12 @@ public:
/** Uic settings. */
class UicSettingsT
{
public:
struct UiFile
{
std::vector<std::string> Options;
};
public:
UicSettingsT();
~UicSettingsT();
@@ -267,8 +266,8 @@ public:
cmFileTime ExecutableTime;
std::string Executable;
std::unordered_set<std::string> SkipList;
std::vector<std::string> TargetOptions;
std::map<std::string, std::vector<std::string>> Options;
std::vector<std::string> Options;
std::unordered_map<std::string, UiFile> UiFiles;
std::vector<std::string> SearchPaths;
cmsys::RegularExpression RegExpInclude;
};
@@ -523,10 +522,8 @@ public:
std::string CollapseFullPathTS(std::string const& path) const;
private:
// -- Utility accessors
Logger const& Log() const { return Logger_; }
// -- Abstract processing interface
bool Init(cmMakefile* makefile) override;
bool InitFromInfo() override;
void InitJobs();
bool Process() override;
// -- Settings file
@@ -541,8 +538,6 @@ private:
bool CreateDirectories();
private:
// -- Utility
Logger Logger_;
// -- Settings
BaseSettingsT BaseConst_;
BaseEvalT BaseEval_;

View File

@@ -6,7 +6,6 @@
#include "cmCryptoHash.h"
#include "cmDuration.h"
#include "cmFileLockResult.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
#include "cmQtAutoGen.h"
#include "cmStringAlgorithms.h"
@@ -16,112 +15,49 @@
#include <algorithm>
cmQtAutoRcc::cmQtAutoRcc() = default;
cmQtAutoRcc::cmQtAutoRcc()
: cmQtAutoGenerator(GenT::RCC)
{
}
cmQtAutoRcc::~cmQtAutoRcc() = default;
bool cmQtAutoRcc::Init(cmMakefile* makefile)
bool cmQtAutoRcc::InitFromInfo()
{
// -- Utility lambdas
auto InfoGet = [makefile](cm::string_view key) {
return makefile->GetSafeDefinition(std::string(key));
};
auto InfoGetList =
[makefile](cm::string_view key) -> std::vector<std::string> {
return cmExpandedList(makefile->GetSafeDefinition(std::string(key)));
};
auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string {
if (const char* valueConf =
makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) {
return std::string(valueConf);
}
return makefile->GetSafeDefinition(std::string(key));
};
auto InfoGetConfigList =
[&InfoGetConfig](cm::string_view key) -> std::vector<std::string> {
return cmExpandedList(InfoGetConfig(key));
};
auto LogInfoError = [this](cm::string_view msg) -> bool {
this->Log().Error(
GenT::RCC, cmStrCat("In ", MessagePath(this->InfoFile()), ":\n", msg));
// -- Required settings
if (!InfoBool("MULTI_CONFIG", MultiConfig_, true) ||
!InfoString("BUILD_DIR", AutogenBuildDir_, true) ||
!InfoStringConfig("INCLUDE_DIR", IncludeDir_, true) ||
!InfoString("RCC_EXECUTABLE", RccExecutable_, true) ||
!InfoArray("RCC_LIST_OPTIONS", RccListOptions_, false) ||
!InfoString("LOCK_FILE", LockFile_, true) ||
!InfoStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
!InfoString("SOURCE", QrcFile_, true) ||
!InfoString("OUTPUT_CHECKSUM", RccPathChecksum_, true) ||
!InfoString("OUTPUT_NAME", RccFileName_, true) ||
!InfoArray("OPTIONS", Options_, false) ||
!InfoArray("INPUTS", Inputs_, false)) {
return false;
};
// -- Read info file
if (!makefile->ReadListFile(InfoFile())) {
return LogInfoError("File processing failed.");
}
// - Configurations
Logger_.RaiseVerbosity(InfoGet("ARCC_VERBOSITY"));
MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
// - Directories
ProjectDirsRef().Source = InfoGet("ARCC_CMAKE_SOURCE_DIR");
ProjectDirsRef().Binary = InfoGet("ARCC_CMAKE_BINARY_DIR");
AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
if (AutogenBuildDir_.empty()) {
return LogInfoError("Build directory empty.");
}
IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
if (IncludeDir_.empty()) {
return LogInfoError("Include directory empty.");
}
// - Rcc executable
RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
if (!RccExecutableTime_.Load(RccExecutable_)) {
return LogInfoError(cmStrCat(
"The rcc executable ", MessagePath(RccExecutable_), " does not exist."));
}
RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
// - Job
LockFile_ = InfoGet("ARCC_LOCK_FILE");
QrcFile_ = InfoGet("ARCC_SOURCE");
// -- Derive information
QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
Options_ = InfoGetConfigList("ARCC_OPTIONS");
Inputs_ = InfoGetList("ARCC_INPUTS");
// - Settings file
SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
// - Validity checks
if (LockFile_.empty()) {
return LogInfoError("Lock file name missing.");
}
if (SettingsFile_.empty()) {
return LogInfoError("Settings file name missing.");
}
if (AutogenBuildDir_.empty()) {
return LogInfoError("Autogen build directory missing.");
}
if (RccExecutable_.empty()) {
return LogInfoError("rcc executable missing.");
}
if (QrcFile_.empty()) {
return LogInfoError("rcc input file missing.");
}
if (RccFileName_.empty()) {
return LogInfoError("rcc output file missing.");
}
// Init derived information
// ------------------------
RccFilePublic_ =
cmStrCat(AutogenBuildDir_, '/', RccPathChecksum_, '/', RccFileName_);
// Compute rcc output file name
// rcc output file name
if (IsMultiConfig()) {
RccFileOutput_ = cmStrCat(IncludeDir_, '/', MultiConfigOutput());
} else {
RccFileOutput_ = RccFilePublic_;
}
// -- Checks
if (!RccExecutableTime_.Load(RccExecutable_)) {
return LogInfoError(cmStrCat(
"The rcc executable ", MessagePath(RccExecutable_), " does not exist."));
}
return true;
}

View File

@@ -12,8 +12,6 @@
#include <string>
#include <vector>
class cmMakefile;
/** \class cmQtAutoRcc
* \brief AUTORCC generator
*/
@@ -28,12 +26,11 @@ public:
private:
// -- Utility
Logger const& Log() const { return Logger_; }
bool IsMultiConfig() const { return MultiConfig_; }
std::string MultiConfigOutput() const;
// -- Abstract processing interface
bool Init(cmMakefile* makefile) override;
bool InitFromInfo() override;
bool Process() override;
// -- Settings file
bool SettingsFileRead();
@@ -47,8 +44,6 @@ private:
bool GenerateWrapper();
private:
// -- Logging
Logger Logger_;
// -- Config settings
bool MultiConfig_ = false;
// -- Directories