summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2019-09-26 13:56:57 +0000
committerKitware Robot <kwrobot@kitware.com>2019-09-26 09:57:15 -0400
commit28a2613dd291c641f17940e3f996bd4cc9b9888d (patch)
tree0e4decbdd61d445daa3215aaec48fd5a295e29fb
parent3cb12895f3d99614ac30bd2f7703f721154b7068 (diff)
parentd867e058924d348ee5ec5bba867965e8f1f276e2 (diff)
downloadcmake-28a2613dd291c641f17940e3f996bd4cc9b9888d.tar.gz
Merge topic 'autogen_json'
d867e05892 Autogen: Use JSON instead of CMake script for info files 881e3cfbf9 Autogen: Variable renames and cleanups fc36f4410b Autogen: Inline GetKnownQtVersions function 1f0d23546d Autogen: Return unsigned int from GetParallelCPUCount() 6a05bd3fa6 cm/algorithm: Provide function cm::clamp Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !3859
-rw-r--r--Source/cmQtAutoGen.cxx11
-rw-r--r--Source/cmQtAutoGen.h10
-rw-r--r--Source/cmQtAutoGenInitializer.cxx902
-rw-r--r--Source/cmQtAutoGenInitializer.h159
-rw-r--r--Source/cmQtAutoGenerator.cxx260
-rw-r--r--Source/cmQtAutoGenerator.h49
-rw-r--r--Source/cmQtAutoMocUic.cxx513
-rw-r--r--Source/cmQtAutoMocUic.h50
-rw-r--r--Source/cmQtAutoRcc.cxx116
-rw-r--r--Source/cmQtAutoRcc.h11
-rw-r--r--Source/cmcmd.cxx8
-rw-r--r--Utilities/std/cm/algorithm38
12 files changed, 1177 insertions, 950 deletions
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 57c88259e1..0f0e86469d 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -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('/');
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index 2a28c1ef8e..d070b790a3 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -17,7 +17,7 @@
class cmQtAutoGen
{
public:
- /// @brief Integer version
+ /** Integer version. */
struct IntegerVersion
{
unsigned int Major = 0;
@@ -43,6 +43,7 @@ public:
}
};
+ /** Compiler features. */
class CompilerFeatures
{
public:
@@ -52,7 +53,7 @@ public:
};
using CompilerFeaturesHandle = std::shared_ptr<CompilerFeatures>;
- /// @brief AutoGen generator type
+ /** AutoGen generator type. */
enum class GenT
{
GEN, // AUTOGEN
@@ -61,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;
@@ -80,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);
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 904572262b..0d56fe1f2a 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -8,7 +8,7 @@
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
-#include "cmFilePathChecksum.h"
+#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -17,7 +17,6 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
@@ -27,34 +26,37 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
#include "cmake.h"
#include "cmsys/SystemInformation.hxx"
-#include <algorithm>
#include <cstddef>
#include <deque>
#include <initializer_list>
#include <map>
+#include <ostream>
#include <set>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
+#include <cm/algorithm>
+#include <cm/iterator>
#include <cm/memory>
namespace {
-std::size_t GetParallelCPUCount()
+unsigned int GetParallelCPUCount()
{
- static std::size_t count = 0;
+ static unsigned int count = 0;
// Detect only on the first call
if (count == 0) {
cmsys::SystemInformation info;
info.RunCPUCheck();
- count = info.GetNumberOfPhysicalCPU();
- count = std::max<std::size_t>(count, 1);
- count = std::min<std::size_t>(count, cmQtAutoGen::ParallelMax);
+ count =
+ cm::clamp(info.GetNumberOfPhysicalCPU(), 1u, cmQtAutoGen::ParallelMax);
}
return count;
}
@@ -124,7 +126,7 @@ bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
return cycle;
}
-/** Sanitizes file search paths */
+/** Sanitizes file search paths. */
class SearchPathSanitizer
{
public:
@@ -158,99 +160,134 @@ std::vector<std::string> SearchPathSanitizer::operator()(
}
return res;
}
-} // End of unnamed namespace
-cmQtAutoGenInitializer::InfoWriter::InfoWriter(std::string const& filename)
+/** @brief Writes a CMake info file. */
+class InfoWriter
{
- Ofs_.SetCopyIfDifferent(true);
- Ofs_.Open(filename, false, true);
-}
+public:
+ // -- Single value
+ void Set(std::string const& key, std::string const& value)
+ {
+ Value_[key] = value;
+ }
+ void SetConfig(std::string const& key,
+ cmQtAutoGenInitializer::ConfigString const& cfgStr);
+ void SetBool(std::string const& key, bool value) { Value_[key] = value; }
+ void SetUInt(std::string const& key, unsigned int value)
+ {
+ Value_[key] = value;
+ }
+
+ // -- Array utility
+ template <typename CONT>
+ static bool MakeArray(Json::Value& jval, CONT const& container);
+
+ template <typename CONT>
+ static void MakeStringArray(Json::Value& jval, CONT const& container);
+
+ // -- Array value
+ template <typename CONT>
+ void SetArray(std::string const& key, CONT const& container);
+ template <typename CONT>
+ void SetConfigArray(
+ std::string const& key,
+ cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr);
+
+ // -- Array of arrays
+ template <typename CONT, typename FUNC>
+ void SetArrayArray(std::string const& key, CONT const& container, FUNC func);
-template <class IT>
-std::string cmQtAutoGenInitializer::InfoWriter::ListJoin(IT it_begin,
- IT it_end)
+ // -- Save to json file
+ bool Save(std::string const& filename);
+
+private:
+ Json::Value Value_;
+};
+
+void InfoWriter::SetConfig(std::string const& key,
+ cmQtAutoGenInitializer::ConfigString const& cfgStr)
{
- std::string res;
- for (IT it = it_begin; it != it_end; ++it) {
- if (it != it_begin) {
- res += ';';
- }
- for (const char* c = it->c_str(); *c; ++c) {
- if (*c == '"') {
- // Escape the double quote to avoid ending the argument.
- res += "\\\"";
- } else if (*c == '$') {
- // Escape the dollar to avoid expanding variables.
- res += "\\$";
- } else if (*c == '\\') {
- // Escape the backslash to avoid other escapes.
- res += "\\\\";
- } else if (*c == ';') {
- // Escape the semicolon to avoid list expansion.
- res += "\\;";
- } else {
- // Other characters will be parsed correctly.
- res += *c;
- }
- }
+ Set(key, cfgStr.Default);
+ for (auto const& item : cfgStr.Config) {
+ Set(cmStrCat(key, '_', item.first), item.second);
}
- return res;
}
-inline std::string cmQtAutoGenInitializer::InfoWriter::ConfigKey(
- cm::string_view key, std::string const& config)
+template <typename CONT>
+bool InfoWriter::MakeArray(Json::Value& jval, CONT const& container)
{
- return cmStrCat(key, "_", config);
+ jval = Json::arrayValue;
+ std::size_t const listSize = cm::size(container);
+ if (listSize == 0) {
+ return false;
+ }
+ jval.resize(static_cast<unsigned int>(listSize));
+ return true;
}
-void cmQtAutoGenInitializer::InfoWriter::Write(cm::string_view key,
- std::string const& value)
-{
- Ofs_ << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
- << ")\n";
-};
-
-void cmQtAutoGenInitializer::InfoWriter::WriteUInt(cm::string_view key,
- unsigned int value)
+template <typename CONT>
+void InfoWriter::MakeStringArray(Json::Value& jval, CONT const& container)
{
- Ofs_ << "set(" << key << " " << value << ")\n";
-};
+ if (MakeArray(jval, container)) {
+ Json::ArrayIndex ii = 0;
+ for (std::string const& item : container) {
+ jval[ii++] = item;
+ }
+ }
+}
-template <class C>
-void cmQtAutoGenInitializer::InfoWriter::WriteStrings(cm::string_view key,
- C const& container)
+template <typename CONT>
+void InfoWriter::SetArray(std::string const& key, CONT const& container)
{
- Ofs_ << "set(" << key << " \""
- << ListJoin(container.begin(), container.end()) << "\")\n";
+ MakeStringArray(Value_[key], container);
}
-void cmQtAutoGenInitializer::InfoWriter::WriteConfig(
- cm::string_view key, std::map<std::string, std::string> const& map)
+template <typename CONT, typename FUNC>
+void InfoWriter::SetArrayArray(std::string const& key, CONT const& container,
+ FUNC func)
{
- for (auto const& item : map) {
- Write(ConfigKey(key, item.first), item.second);
+ Json::Value& jval = Value_[key];
+ if (MakeArray(jval, container)) {
+ Json::ArrayIndex ii = 0;
+ for (auto const& citem : container) {
+ Json::Value& aval = jval[ii++];
+ aval = Json::arrayValue;
+ func(aval, citem);
+ }
}
-};
+}
-template <class C>
-void cmQtAutoGenInitializer::InfoWriter::WriteConfigStrings(
- cm::string_view key, std::map<std::string, C> const& map)
+template <typename CONT>
+void InfoWriter::SetConfigArray(
+ std::string const& key,
+ cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr)
{
- for (auto const& item : map) {
- WriteStrings(ConfigKey(key, item.first), item.second);
+ SetArray(key, cfgStr.Default);
+ for (auto const& item : cfgStr.Config) {
+ SetArray(cmStrCat(key, '_', item.first), item.second);
}
}
-void cmQtAutoGenInitializer::InfoWriter::WriteNestedLists(
- cm::string_view key, std::vector<std::vector<std::string>> const& lists)
+bool InfoWriter::Save(std::string const& filename)
{
- std::vector<std::string> seplist;
- seplist.reserve(lists.size());
- for (std::vector<std::string> const& list : lists) {
- seplist.push_back(cmStrCat("{", ListJoin(list.begin(), list.end()), "}"));
+ cmGeneratedFileStream fileStream;
+ fileStream.SetCopyIfDifferent(true);
+ fileStream.Open(filename, false, true);
+ if (!fileStream) {
+ return false;
+ }
+
+ Json::StyledStreamWriter jsonWriter;
+ try {
+ jsonWriter.write(fileStream, Value_);
+ } catch (...) {
+ return false;
}
- Write(key, cmJoin(seplist, cmQtAutoGen::ListSep));
-};
+
+ return fileStream.Close();
+}
+
+} // End of unnamed namespace
cmQtAutoGenInitializer::cmQtAutoGenInitializer(
cmQtAutoGenGlobalInitializer* globalInitializer,
@@ -262,6 +299,7 @@ cmQtAutoGenInitializer::cmQtAutoGenInitializer(
, GlobalGen(genTarget->GetGlobalGenerator())
, LocalGen(genTarget->GetLocalGenerator())
, Makefile(genTarget->Makefile)
+ , PathCheckSum(genTarget->Makefile)
, QtVersion(qtVersion)
{
AutogenTarget.GlobalTarget = globalAutogenTarget;
@@ -281,12 +319,20 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
// Verbosity
- this->Verbosity = this->Makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
- if (!this->Verbosity.empty()) {
- unsigned long iVerb = 0;
- if (!cmStrToULong(this->Verbosity, &iVerb)) {
- // Non numeric verbosity
- this->Verbosity = cmIsOn(this->Verbosity) ? "1" : "0";
+ {
+ std::string def =
+ this->Makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
+ if (!def.empty()) {
+ unsigned long iVerb = 0;
+ if (cmStrToULong(def, &iVerb)) {
+ // Numeric verbosity
+ this->Verbosity = static_cast<unsigned int>(iVerb);
+ } else {
+ // Non numeric verbosity
+ if (cmIsOn(def)) {
+ this->Verbosity = 1;
+ }
+ }
}
}
@@ -353,16 +399,11 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);
// Include directory
- this->Dir.Include = cmStrCat(this->Dir.Build, "/include");
+ ConfigFileNames(this->Dir.Include, cmStrCat(this->Dir.Build, "/include"),
+ "");
+ this->Dir.IncludeGenExp = this->Dir.Include.Default;
if (this->MultiConfig) {
- this->Dir.Include += "_$<CONFIG>";
- }
- // Per config include directories
- if (this->MultiConfig) {
- for (std::string const& cfg : this->ConfigsList) {
- std::string& dir = this->Dir.ConfigInclude[cfg];
- dir = cmStrCat(this->Dir.Build, "/include_", cfg);
- }
+ this->Dir.IncludeGenExp += "_$<CONFIG>";
}
}
@@ -383,36 +424,31 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmStrCat(this->GenTarget->GetName(), "_autogen");
// Autogen target parallel processing
- this->AutogenTarget.Parallel =
- this->GenTarget->GetSafeProperty("AUTOGEN_PARALLEL");
- if (this->AutogenTarget.Parallel.empty() ||
- (this->AutogenTarget.Parallel == "AUTO")) {
- // Autodetect number of CPUs
- this->AutogenTarget.Parallel = std::to_string(GetParallelCPUCount());
+ {
+ std::string prop = this->GenTarget->GetSafeProperty("AUTOGEN_PARALLEL");
+ if (prop.empty() || (prop == "AUTO")) {
+ // Autodetect number of CPUs
+ this->AutogenTarget.Parallel = GetParallelCPUCount();
+ } else {
+ this->AutogenTarget.Parallel = 1;
+ }
}
// Autogen target info and settings files
{
+ // Info file
this->AutogenTarget.InfoFile =
- cmStrCat(this->Dir.Info, "/AutogenInfo.cmake");
-
- this->AutogenTarget.SettingsFile =
- cmStrCat(this->Dir.Info, "/AutogenOldSettings.txt");
+ cmStrCat(this->Dir.Info, "/AutogenInfo.json");
- if (this->MultiConfig) {
- for (std::string const& cfg : this->ConfigsList) {
- std::string& filename = this->AutogenTarget.ConfigSettingsFile[cfg];
- filename =
- AppendFilenameSuffix(this->AutogenTarget.SettingsFile, "_" + cfg);
- this->AddCleanFile(filename);
- }
- } else {
- this->AddCleanFile(this->AutogenTarget.SettingsFile);
- }
+ // Used settings file
+ ConfigFileNames(this->AutogenTarget.SettingsFile,
+ cmStrCat(this->Dir.Info, "/AutogenUsed"), ".txt");
+ ConfigFileClean(this->AutogenTarget.SettingsFile);
- this->AutogenTarget.ParseCacheFile =
- cmStrCat(this->Dir.Info, "/ParseCache.txt");
- this->AddCleanFile(this->AutogenTarget.ParseCacheFile);
+ // Parse cache file
+ ConfigFileNames(this->AutogenTarget.ParseCacheFile,
+ cmStrCat(this->Dir.Info, "/ParseCache"), ".txt");
+ ConfigFileClean(this->AutogenTarget.ParseCacheFile);
}
// Autogen target: Compute user defined dependencies
@@ -435,9 +471,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
}
- // CMAKE_AUTOMOC_RELAXED_MODE deprecation warning
if (this->Moc.Enabled) {
+ // Path prefix
+ if (cmIsOn(this->GenTarget->GetSafeProperty("AUTOMOC_PATH_PREFIX"))) {
+ this->Moc.PathPrefix = true;
+ }
+
+ // CMAKE_AUTOMOC_RELAXED_MODE
if (this->Makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE")) {
+ this->Moc.RelaxedMode = true;
this->Makefile->IssueMessage(
MessageType::AUTHOR_WARNING,
cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is "
@@ -445,6 +487,32 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
"disabling it and converting the target ",
this->GenTarget->GetName(), " to regular mode."));
}
+
+ // Options
+ cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MOC_OPTIONS"),
+ this->Moc.Options);
+ // Filters
+ cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"),
+ this->Moc.MacroNames);
+ {
+ auto filterList = cmExpandedList(
+ this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
+ if ((filterList.size() % 2) != 0) {
+ cmSystemTools::Error(
+ cmStrCat("AutoMoc: AUTOMOC_DEPEND_FILTERS predefs size ",
+ filterList.size(), " is not a multiple of 2."));
+ return false;
+ }
+ this->Moc.DependFilters.reserve(1 + (filterList.size() / 2));
+ this->Moc.DependFilters.emplace_back(
+ "Q_PLUGIN_METADATA",
+ "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
+ "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
+ for (std::size_t ii = 0; ii != filterList.size(); ii += 2) {
+ this->Moc.DependFilters.emplace_back(filterList[ii],
+ filterList[ii + 1]);
+ }
+ }
}
}
@@ -455,7 +523,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
// Add autogen include directory to the origin target INCLUDE_DIRECTORIES
if (this->MocOrUicEnabled() || (this->Rcc.Enabled && this->MultiConfig)) {
- this->GenTarget->AddIncludeDirectory(this->Dir.Include, true);
+ this->GenTarget->AddIncludeDirectory(this->Dir.IncludeGenExp, true);
}
// Scan files
@@ -479,20 +547,27 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
bool cmQtAutoGenInitializer::InitMoc()
{
// Mocs compilation file
- this->Moc.MocsCompilation =
+ this->Moc.CompilationFile =
cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
- // Moc predefs command
+ // Moc predefs
if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
(this->QtVersion >= IntegerVersion(5, 8))) {
- this->Moc.PredefsCmd = this->Makefile->GetSafeDefinition(
- "CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");
+ // Command
+ cmExpandList(this->Makefile->GetSafeDefinition(
+ "CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"),
+ this->Moc.PredefsCmd);
+ // Header
+ if (!this->Moc.PredefsCmd.empty()) {
+ ConfigFileNames(this->Moc.PredefsFile,
+ cmStrCat(this->Dir.Build, "/moc_predefs"), ".h");
+ }
}
// Moc includes
{
SearchPathSanitizer sanitizer(this->Makefile);
- auto GetIncludeDirs =
+ auto getDirs =
[this, &sanitizer](std::string const& cfg) -> std::vector<std::string> {
// Get the include dirs for this target, without stripping the implicit
// include dirs off, see issue #13667.
@@ -504,22 +579,22 @@ bool cmQtAutoGenInitializer::InitMoc()
};
// Default configuration include directories
- this->Moc.Includes = GetIncludeDirs(this->ConfigDefault);
+ this->Moc.Includes.Default = getDirs(this->ConfigDefault);
// Other configuration settings
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
- std::vector<std::string> dirs = GetIncludeDirs(cfg);
- if (dirs != this->Moc.Includes) {
- this->Moc.ConfigIncludes[cfg] = std::move(dirs);
+ std::vector<std::string> dirs = getDirs(cfg);
+ if (dirs == this->Moc.Includes.Default) {
+ continue;
}
+ this->Moc.Includes.Config[cfg] = std::move(dirs);
}
}
}
// Moc compile definitions
{
- auto GetCompileDefinitions =
- [this](std::string const& cfg) -> std::set<std::string> {
+ auto getDefs = [this](std::string const& cfg) -> std::set<std::string> {
std::set<std::string> defines;
this->LocalGen->GetTargetDefines(this->GenTarget, cfg, "CXX", defines);
#ifdef _WIN32
@@ -532,14 +607,15 @@ bool cmQtAutoGenInitializer::InitMoc()
};
// Default configuration defines
- this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault);
+ this->Moc.Defines.Default = getDefs(this->ConfigDefault);
// Other configuration defines
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
- std::set<std::string> defines = GetCompileDefinitions(cfg);
- if (defines != this->Moc.Defines) {
- this->Moc.ConfigDefines[cfg] = std::move(defines);
+ std::set<std::string> defines = getDefs(cfg);
+ if (defines == this->Moc.Defines.Default) {
+ continue;
}
+ this->Moc.Defines.Config[cfg] = std::move(defines);
}
}
}
@@ -572,23 +648,22 @@ bool cmQtAutoGenInitializer::InitUic()
}
// Uic target options
{
- auto UicGetOpts =
- [this](std::string const& cfg) -> std::vector<std::string> {
+ auto getOpts = [this](std::string const& cfg) -> std::vector<std::string> {
std::vector<std::string> opts;
this->GenTarget->GetAutoUicOptions(opts, cfg);
return opts;
};
- // Default settings
- this->Uic.Options = UicGetOpts(this->ConfigDefault);
-
- // Configuration specific settings
+ // Default options
+ this->Uic.Options.Default = getOpts(this->ConfigDefault);
+ // Configuration specific options
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
- std::vector<std::string> options = UicGetOpts(cfg);
- if (options != this->Uic.Options) {
- this->Uic.ConfigOptions[cfg] = std::move(options);
+ std::vector<std::string> options = getOpts(cfg);
+ if (options == this->Uic.Options.Default) {
+ continue;
}
+ this->Uic.Options.Config[cfg] = std::move(options);
}
}
}
@@ -822,8 +897,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Check if the .ui file has uic options
std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
if (!uicOpts.empty()) {
- this->Uic.FileFiles.push_back(fullPath);
- this->Uic.FileOptions.push_back(cmExpandedList(uicOpts));
+ this->Uic.UiFiles.emplace_back(fullPath, cmExpandedList(uicOpts));
}
} else {
// Register skipped .ui file
@@ -887,31 +961,19 @@ bool cmQtAutoGenInitializer::InitScanFiles()
}
}
// Path checksum and file names
- {
- cmFilePathChecksum const fpathCheckSum(this->Makefile);
- for (Qrc& qrc : this->Rcc.Qrcs) {
- qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
- // RCC output file name
- qrc.RccFile = cmStrCat(this->Dir.Build, '/', qrc.PathChecksum, "/qrc_",
- qrc.QrcName, ".cpp");
- {
- cm::string_view const baseSuffix =
- qrc.Unique ? cm::string_view() : cm::string_view(qrc.PathChecksum);
- std::string const base =
- cmStrCat(this->Dir.Info, "/RCC", qrc.QrcName, baseSuffix);
- qrc.LockFile = cmStrCat(base, ".lock");
- qrc.InfoFile = cmStrCat(base, "Info.cmake");
- qrc.SettingsFile = cmStrCat(base, "Settings.txt");
- if (this->MultiConfig) {
- for (std::string const& cfg : this->ConfigsList) {
- qrc.ConfigSettingsFile[cfg] =
- AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
- }
- }
- }
- }
- }
- // RCC options
+ for (Qrc& qrc : this->Rcc.Qrcs) {
+ // Path checksum
+ qrc.QrcPathChecksum = this->PathCheckSum.getPart(qrc.QrcFile);
+ // Output file name
+ qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,
+ "/qrc_", qrc.QrcName, ".cpp");
+ std::string const base = cmStrCat(this->Dir.Info, "/AutoRcc_",
+ qrc.QrcName, '_', qrc.QrcPathChecksum);
+ qrc.LockFile = cmStrCat(base, "_Lock.lock");
+ qrc.InfoFile = cmStrCat(base, "_Info.json");
+ ConfigFileNames(qrc.SettingsFile, cmStrCat(base, "_Used"), ".txt");
+ }
+ // rcc options
for (Qrc& qrc : this->Rcc.Qrcs) {
// Target options
std::vector<std::string> opts = optionsTarget;
@@ -921,7 +983,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Replace '-' with '_'. The former is not valid for symbol names.
std::replace(name.begin(), name.end(), '-', '_');
if (!qrc.Unique) {
- name += cmStrCat('_', qrc.PathChecksum);
+ name += cmStrCat('_', qrc.QrcPathChecksum);
}
std::vector<std::string> nameOpts;
nameOpts.emplace_back("-name");
@@ -932,7 +994,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
RccMergeOptions(opts, qrc.Options, modernQt);
qrc.Options = std::move(opts);
}
- // RCC resources
+ // rcc resources
for (Qrc& qrc : this->Rcc.Qrcs) {
if (!qrc.Generated) {
std::string error;
@@ -957,8 +1019,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// Files provided by the autogen target
std::vector<std::string> autogenProvides;
if (this->Moc.Enabled) {
- this->AddGeneratedSource(this->Moc.MocsCompilation, this->Moc, true);
- autogenProvides.push_back(this->Moc.MocsCompilation);
+ this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true);
+ autogenProvides.push_back(this->Moc.CompilationFile);
}
// Compose target comment
@@ -1100,10 +1162,10 @@ bool cmQtAutoGenInitializer::InitRccTargets()
// Register info file as generated by CMake
this->Makefile->AddCMakeOutputFile(qrc.InfoFile);
// Register file at target
- this->AddGeneratedSource(qrc.RccFile, this->Rcc);
+ this->AddGeneratedSource(qrc.OutputFile, this->Rcc);
std::vector<std::string> ccOutput;
- ccOutput.push_back(qrc.RccFile);
+ ccOutput.push_back(qrc.OutputFile);
std::vector<std::string> ccDepends;
// Add the .qrc and info file to the custom command dependencies
@@ -1133,7 +1195,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
{
ccName = cmStrCat(this->GenTarget->GetName(), "_arcc_", qrc.QrcName);
if (!qrc.Unique) {
- ccName += cmStrCat('_', qrc.PathChecksum);
+ ccName += cmStrCat('_', qrc.QrcPathChecksum);
}
cmTarget* autoRccTarget = this->Makefile->AddUtilityCommand(
@@ -1212,229 +1274,185 @@ bool cmQtAutoGenInitializer::SetupCustomTargets()
bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
{
- InfoWriter ofs(this->AutogenTarget.InfoFile);
- if (ofs) {
- // Utility lambdas
- auto MfDef = [this](const char* key) {
- return this->Makefile->GetSafeDefinition(key);
- };
+ // Utility lambdas
+ auto MfDef = [this](std::string const& key) {
+ return this->Makefile->GetSafeDefinition(key);
+ };
- // Write common settings
- ofs.Write("# Meta\n");
- ofs.Write("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
- ofs.Write("AM_PARALLEL", this->AutogenTarget.Parallel);
- ofs.Write("AM_VERBOSITY", this->Verbosity);
-
- ofs.Write("# Directories\n");
- ofs.Write("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
- ofs.Write("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
- ofs.Write("AM_CMAKE_CURRENT_SOURCE_DIR",
- MfDef("CMAKE_CURRENT_SOURCE_DIR"));
- ofs.Write("AM_CMAKE_CURRENT_BINARY_DIR",
- MfDef("CMAKE_CURRENT_BINARY_DIR"));
- ofs.Write("AM_BUILD_DIR", this->Dir.Build);
- ofs.Write("AM_INCLUDE_DIR", this->Dir.Include);
- ofs.WriteConfig("AM_INCLUDE_DIR", this->Dir.ConfigInclude);
-
- std::vector<std::string> headers;
- std::vector<std::string> headersFlags;
- std::vector<std::string> headersBuildPaths;
- std::vector<std::string> sources;
- std::vector<std::string> sourcesFlags;
- std::set<std::string> moc_skip;
- std::set<std::string> uic_skip;
-
- // Filter headers
- {
- auto headerCount = this->AutogenTarget.Headers.size();
- headers.reserve(headerCount);
- headersFlags.reserve(headerCount);
+ // Filtered headers and sources
+ std::set<std::string> moc_skip;
+ std::set<std::string> uic_skip;
+ std::vector<MUFile const*> headers;
+ std::vector<MUFile const*> sources;
- std::vector<MUFile const*> sortedHeaders;
- {
- sortedHeaders.reserve(headerCount);
- for (auto const& pair : this->AutogenTarget.Headers) {
- sortedHeaders.emplace_back(pair.second.get());
- }
- std::sort(sortedHeaders.begin(), sortedHeaders.end(),
- [](MUFile const* a, MUFile const* b) {
- return (a->FullPath < b->FullPath);
- });
+ // Filter headers
+ {
+ headers.reserve(this->AutogenTarget.Headers.size());
+ for (auto const& pair : this->AutogenTarget.Headers) {
+ MUFile const* const muf = pair.second.get();
+ if (muf->Generated && !this->CMP0071Accept) {
+ continue;
}
-
- for (MUFile const* const muf : sortedHeaders) {
- if (muf->Generated && !this->CMP0071Accept) {
- continue;
- }
- if (muf->SkipMoc) {
- moc_skip.insert(muf->FullPath);
- }
- if (muf->SkipUic) {
- uic_skip.insert(muf->FullPath);
- }
- if (muf->MocIt || muf->UicIt) {
- headers.emplace_back(muf->FullPath);
- headersFlags.emplace_back(
- cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u'));
- }
+ if (muf->SkipMoc) {
+ moc_skip.insert(muf->FullPath);
}
- }
- // Header build paths
- {
- cmFilePathChecksum const fpathCheckSum(this->Makefile);
- std::unordered_set<std::string> emitted;
- for (std::string const& hdr : headers) {
- std::string const basePath =
- cmStrCat(fpathCheckSum.getPart(hdr), "/moc_",
- cmSystemTools::GetFilenameWithoutLastExtension(hdr));
- std::string suffix;
- for (int ii = 0; ii != 1024; ++ii) {
- std::string path = cmStrCat(basePath, suffix, ".cpp");
- if (emitted.emplace(path).second) {
- headersBuildPaths.emplace_back(std::move(path));
- break;
- }
- suffix = cmStrCat('_', ii + 1);
- }
+ if (muf->SkipUic) {
+ uic_skip.insert(muf->FullPath);
+ }
+ if (muf->MocIt || muf->UicIt) {
+ headers.emplace_back(muf);
}
}
+ std::sort(headers.begin(), headers.end(),
+ [](MUFile const* a, MUFile const* b) {
+ return (a->FullPath < b->FullPath);
+ });
+ }
- // Filter sources
- {
- auto sourcesCount = this->AutogenTarget.Sources.size();
- sources.reserve(sourcesCount);
- sourcesFlags.reserve(sourcesCount);
-
- std::vector<MUFile const*> sorted;
- sorted.reserve(sourcesCount);
- for (auto const& pair : this->AutogenTarget.Sources) {
- sorted.emplace_back(pair.second.get());
+ // Filter sources
+ {
+ sources.reserve(this->AutogenTarget.Sources.size());
+ for (auto const& pair : this->AutogenTarget.Sources) {
+ MUFile const* const muf = pair.second.get();
+ if (muf->Generated && !this->CMP0071Accept) {
+ continue;
}
- std::sort(sorted.begin(), sorted.end(),
- [](MUFile const* a, MUFile const* b) {
- return (a->FullPath < b->FullPath);
- });
-
- for (MUFile const* const muf : sorted) {
- if (muf->Generated && !this->CMP0071Accept) {
- continue;
- }
- if (muf->SkipMoc) {
- moc_skip.insert(muf->FullPath);
- }
- if (muf->SkipUic) {
- uic_skip.insert(muf->FullPath);
- }
- if (muf->MocIt || muf->UicIt) {
- sources.emplace_back(muf->FullPath);
- sourcesFlags.emplace_back(
- cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u'));
- }
+ if (muf->SkipMoc) {
+ moc_skip.insert(muf->FullPath);
+ }
+ if (muf->SkipUic) {
+ uic_skip.insert(muf->FullPath);
+ }
+ if (muf->MocIt || muf->UicIt) {
+ sources.emplace_back(muf);
}
}
+ std::sort(sources.begin(), sources.end(),
+ [](MUFile const* a, MUFile const* b) {
+ return (a->FullPath < b->FullPath);
+ });
+ }
- ofs.Write("# Qt\n");
- ofs.WriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major);
- ofs.Write("AM_QT_MOC_EXECUTABLE", this->Moc.Executable);
- ofs.Write("AM_QT_UIC_EXECUTABLE", this->Uic.Executable);
-
- ofs.Write("# Files\n");
- ofs.Write("AM_CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());
- ofs.Write("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile);
- ofs.WriteConfig("AM_SETTINGS_FILE",
- this->AutogenTarget.ConfigSettingsFile);
- ofs.Write("AM_PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
- ofs.WriteStrings("AM_HEADERS", headers);
- ofs.WriteStrings("AM_HEADERS_FLAGS", headersFlags);
- ofs.WriteStrings("AM_HEADERS_BUILD_PATHS", headersBuildPaths);
- ofs.WriteStrings("AM_SOURCES", sources);
- ofs.WriteStrings("AM_SOURCES_FLAGS", sourcesFlags);
-
- // Write moc settings
- if (this->Moc.Enabled) {
- ofs.Write("# MOC settings\n");
- ofs.WriteStrings("AM_MOC_SKIP", moc_skip);
- ofs.WriteStrings("AM_MOC_DEFINITIONS", this->Moc.Defines);
- ofs.WriteConfigStrings("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines);
- ofs.WriteStrings("AM_MOC_INCLUDES", this->Moc.Includes);
- ofs.WriteConfigStrings("AM_MOC_INCLUDES", this->Moc.ConfigIncludes);
- ofs.Write("AM_MOC_OPTIONS",
- this->GenTarget->GetSafeProperty("AUTOMOC_MOC_OPTIONS"));
- ofs.Write("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
- ofs.Write("AM_MOC_PATH_PREFIX",
- this->GenTarget->GetSafeProperty("AUTOMOC_PATH_PREFIX"));
- ofs.Write("AM_MOC_MACRO_NAMES",
- this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"));
- ofs.Write("AM_MOC_DEPEND_FILTERS",
- this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
- ofs.Write("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
- }
-
- // Write uic settings
- if (this->Uic.Enabled) {
- // Add skipped .ui files
- uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());
+ // Info writer
+ InfoWriter info;
+
+ // General
+ info.SetBool("MULTI_CONFIG", this->MultiConfig);
+ info.SetUInt("PARALLEL", this->AutogenTarget.Parallel);
+ info.SetUInt("VERBOSITY", this->Verbosity);
+
+ // Directories
+ info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+ info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+ info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+ info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+ info.Set("BUILD_DIR", this->Dir.Build);
+ info.SetConfig("INCLUDE_DIR", this->Dir.Include);
+
+ info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major);
+ info.Set("QT_MOC_EXECUTABLE", this->Moc.Executable);
+ info.Set("QT_UIC_EXECUTABLE", this->Uic.Executable);
+
+ info.Set("CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());
+ info.SetConfig("SETTINGS_FILE", this->AutogenTarget.SettingsFile);
+ info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
+ info.SetArray("HEADER_EXTENSIONS",
+ this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
+ info.SetArrayArray(
+ "HEADERS", headers, [this](Json::Value& jval, MUFile const* muf) {
+ jval.resize(3u);
+ jval[0u] = muf->FullPath;
+ jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
+ jval[2u] = this->GetMocBuildPath(*muf);
+ });
+ info.SetArrayArray(
+ "SOURCES", sources, [](Json::Value& jval, MUFile const* muf) {
+ jval.resize(2u);
+ jval[0u] = muf->FullPath;
+ jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
+ });
+
+ // Write moc settings
+ if (this->Moc.Enabled) {
+ info.SetArray("MOC_SKIP", moc_skip);
+ info.SetConfigArray("MOC_DEFINITIONS", this->Moc.Defines);
+ info.SetConfigArray("MOC_INCLUDES", this->Moc.Includes);
+ info.SetArray("MOC_OPTIONS", this->Moc.Options);
+ info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode);
+ info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix);
+ info.SetArray("MOC_MACRO_NAMES", this->Moc.MacroNames);
+ info.SetArrayArray(
+ "MOC_DEPEND_FILTERS", this->Moc.DependFilters,
+ [](Json::Value& jval, std::pair<std::string, std::string> const& pair) {
+ jval.resize(2u);
+ jval[0u] = pair.first;
+ jval[1u] = pair.second;
+ });
+ info.Set("MOC_COMPILATION_FILE", this->Moc.CompilationFile);
+ info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
+ info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile);
+ }
- ofs.Write("# UIC settings\n");
- ofs.WriteStrings("AM_UIC_SKIP", uic_skip);
- ofs.WriteStrings("AM_UIC_TARGET_OPTIONS", this->Uic.Options);
- ofs.WriteConfigStrings("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions);
- ofs.WriteStrings("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles);
- ofs.WriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions);
- ofs.WriteStrings("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths);
- }
- } else {
- cmSystemTools::Error(cmStrCat("AutoGen: Could not write file ",
- this->AutogenTarget.InfoFile));
- return false;
+ // Write uic settings
+ if (this->Uic.Enabled) {
+ // Add skipped .ui files
+ uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());
+
+ info.SetArray("UIC_SKIP", uic_skip);
+ info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFiles,
+ [](Json::Value& jval, UicT::UiFileT const& uiFile) {
+ jval.resize(2u);
+ jval[0u] = uiFile.first;
+ InfoWriter::MakeStringArray(jval[1u], uiFile.second);
+ });
+ info.SetConfigArray("UIC_OPTIONS", this->Uic.Options);
+ info.SetArray("UIC_SEARCH_PATHS", this->Uic.SearchPaths);
}
+ info.Save(this->AutogenTarget.InfoFile);
+
return true;
}
bool cmQtAutoGenInitializer::SetupWriteRccInfo()
{
for (Qrc const& qrc : this->Rcc.Qrcs) {
- InfoWriter ofs(qrc.InfoFile);
- if (ofs) {
- // Utility lambdas
- auto MfDef = [this](const char* key) {
- return this->Makefile->GetSafeDefinition(key);
- };
+ // Utility lambdas
+ auto MfDef = [this](std::string const& key) {
+ return this->Makefile->GetSafeDefinition(key);
+ };
- // Write
- ofs.Write("# Configurations\n");
- ofs.Write("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
- ofs.Write("ARCC_VERBOSITY", this->Verbosity);
- ofs.Write("# Settings file\n");
- ofs.Write("ARCC_SETTINGS_FILE", qrc.SettingsFile);
- ofs.WriteConfig("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile);
-
- ofs.Write("# Directories\n");
- ofs.Write("ARCC_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
- ofs.Write("ARCC_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
- ofs.Write("ARCC_BUILD_DIR", this->Dir.Build);
- ofs.Write("ARCC_INCLUDE_DIR", this->Dir.Include);
- ofs.WriteConfig("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude);
-
- ofs.Write("# Rcc executable\n");
- ofs.Write("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);
- ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS",
- this->Rcc.ExecutableFeatures->ListOptions);
-
- ofs.Write("# Rcc job\n");
- ofs.Write("ARCC_LOCK_FILE", qrc.LockFile);
- ofs.Write("ARCC_SOURCE", qrc.QrcFile);
- ofs.Write("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
- ofs.Write("ARCC_OUTPUT_NAME",
- cmSystemTools::GetFilenameName(qrc.RccFile));
- ofs.WriteStrings("ARCC_OPTIONS", qrc.Options);
- ofs.WriteStrings("ARCC_INPUTS", qrc.Resources);
- } else {
- cmSystemTools::Error(
- cmStrCat("AutoRcc: Could not write file ", qrc.InfoFile));
- return false;
- }
+ InfoWriter info;
+
+ // General
+ info.SetBool("MULTI_CONFIG", this->MultiConfig);
+ info.SetUInt("VERBOSITY", this->Verbosity);
+
+ // Files
+ info.Set("LOCK_FILE", qrc.LockFile);
+ info.SetConfig("SETTINGS_FILE", qrc.SettingsFile);
+
+ // Directories
+ info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+ info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+ info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+ info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+ info.Set("BUILD_DIR", this->Dir.Build);
+ info.SetConfig("INCLUDE_DIR", this->Dir.Include);
+
+ // rcc executable
+ info.Set("RCC_EXECUTABLE", this->Rcc.Executable);
+ info.SetArray("RCC_LIST_OPTIONS",
+ this->Rcc.ExecutableFeatures->ListOptions);
+
+ // qrc file
+ info.Set("SOURCE", qrc.QrcFile);
+ info.Set("OUTPUT_CHECKSUM", qrc.QrcPathChecksum);
+ info.Set("OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.OutputFile));
+ info.SetArray("OPTIONS", qrc.Options);
+ info.SetArray("INPUTS", qrc.Resources);
+
+ info.Save(qrc.InfoFile);
}
return true;
@@ -1507,64 +1525,82 @@ void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName)
fileName.c_str(), false);
}
-static unsigned int CharPtrToUInt(const char* const input)
+void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,
+ cm::string_view prefix,
+ cm::string_view suffix)
{
- unsigned long tmp = 0;
- if (input != nullptr && cmStrToULong(input, &tmp)) {
- return static_cast<unsigned int>(tmp);
+ configString.Default = cmStrCat(prefix, suffix);
+ if (this->MultiConfig) {
+ for (auto const& cfg : this->ConfigsList) {
+ configString.Config[cfg] = cmStrCat(prefix, '_', cfg, suffix);
+ }
}
- return 0;
}
-static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
- cmGeneratorTarget const* genTarget)
+void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString)
{
- // Qt version variable prefixes
- static std::initializer_list<
- std::pair<cm::string_view, cm::string_view>> const keys{
- { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" },
- { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" },
- { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" },
- };
-
- std::vector<cmQtAutoGen::IntegerVersion> result;
- result.reserve(keys.size() * 2);
-
- // Adds a version to the result (nullptr safe)
- auto addVersion = [&result](const char* major, const char* minor) {
- cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major),
- CharPtrToUInt(minor));
- if (ver.Major != 0) {
- result.emplace_back(ver);
+ this->AddCleanFile(configString.Default);
+ if (this->MultiConfig) {
+ for (auto const& pair : configString.Config) {
+ this->AddCleanFile(pair.second);
}
- };
-
- cmMakefile* makefile = genTarget->Makefile;
-
- // Read versions from variables
- for (auto const& keyPair : keys) {
- addVersion(makefile->GetDefinition(std::string(keyPair.first)),
- makefile->GetDefinition(std::string(keyPair.second)));
- }
-
- // Read versions from directory properties
- for (auto const& keyPair : keys) {
- addVersion(makefile->GetProperty(std::string(keyPair.first)),
- makefile->GetProperty(std::string(keyPair.second)));
}
-
- return result;
}
std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
{
+ // Converts a char ptr to an unsigned int value
+ auto toUInt = [](const char* const input) -> unsigned int {
+ unsigned long tmp = 0;
+ if (input != nullptr && cmStrToULong(input, &tmp)) {
+ return static_cast<unsigned int>(tmp);
+ }
+ return 0u;
+ };
+
+ // Initialize return value to a default
std::pair<IntegerVersion, unsigned int> res(
IntegerVersion(),
- CharPtrToUInt(target->GetLinkInterfaceDependentStringProperty(
- "QT_MAJOR_VERSION", "")));
+ toUInt(target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
+ "")));
+
+ // Acquire known Qt versions
+ std::vector<cmQtAutoGen::IntegerVersion> knownQtVersions;
+ {
+ // Qt version variable prefixes
+ static std::initializer_list<
+ std::pair<cm::string_view, cm::string_view>> const keys{
+ { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" },
+ { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" },
+ { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" },
+ };
- auto knownQtVersions = GetKnownQtVersions(target);
+ knownQtVersions.reserve(keys.size() * 2);
+
+ // Adds a version to the result (nullptr safe)
+ auto addVersion = [&knownQtVersions, &toUInt](const char* major,
+ const char* minor) {
+ cmQtAutoGen::IntegerVersion ver(toUInt(major), toUInt(minor));
+ if (ver.Major != 0) {
+ knownQtVersions.emplace_back(ver);
+ }
+ };
+
+ // Read versions from variables
+ for (auto const& keyPair : keys) {
+ addVersion(target->Makefile->GetDefinition(std::string(keyPair.first)),
+ target->Makefile->GetDefinition(std::string(keyPair.second)));
+ }
+
+ // Read versions from directory properties
+ for (auto const& keyPair : keys) {
+ addVersion(target->Makefile->GetProperty(std::string(keyPair.first)),
+ target->Makefile->GetProperty(std::string(keyPair.second)));
+ }
+ }
+
+ // Evaluate known Qt versions
if (!knownQtVersions.empty()) {
if (res.second == 0) {
// No specific version was requested by the target:
@@ -1583,6 +1619,30 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
return res;
}
+std::string cmQtAutoGenInitializer::GetMocBuildPath(MUFile const& muf)
+{
+ std::string res;
+ if (!muf.MocIt) {
+ return res;
+ }
+ {
+ std::string const basePath =
+ cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_",
+ FileNameWithoutLastExtension(muf.FullPath));
+ std::string suffix;
+ constexpr std::size_t num_tries_max = 256;
+ for (std::size_t ii = 0; ii != num_tries_max; ++ii) {
+ res = cmStrCat(basePath, suffix, ".cpp");
+ if (this->Moc.EmittedBuildPaths.emplace(res).second) {
+ break;
+ }
+ // Compute new suffix
+ suffix = cmStrCat('_', ii + 1);
+ }
+ }
+ return res;
+}
+
bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
const std::string& executable,
bool ignoreMissingTarget) const
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index 7ce9fad9e9..0580ddb85b 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -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>
@@ -26,29 +25,47 @@ class cmQtAutoGenGlobalInitializer;
class cmSourceFile;
class cmTarget;
-/// @brief Initializes the QtAutoGen generators
+/** \class cmQtAutoGenerator
+ * \brief Initializes the QtAutoGen generators
+ */
class cmQtAutoGenInitializer : public cmQtAutoGen
{
public:
- /// @brief Rcc job information
+ /** 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
{
public:
std::string LockFile;
std::string QrcFile;
std::string QrcName;
- std::string PathChecksum;
+ std::string QrcPathChecksum;
std::string InfoFile;
- std::string SettingsFile;
- std::map<std::string, std::string> ConfigSettingsFile;
- std::string RccFile;
+ ConfigString SettingsFile;
+ std::string OutputFile;
bool Generated = false;
bool Unique = false;
std::vector<std::string> Options;
std::vector<std::string> Resources;
};
- /// @brief Moc/Uic file
+ /** moc and/or uic file. */
struct MUFile
{
std::string FullPath;
@@ -61,7 +78,7 @@ public:
};
using MUFileHandle = std::unique_ptr<MUFile>;
- /// @brief Abstract moc/uic/rcc generator variables base class
+ /** Abstract moc/uic/rcc generator variables base class. */
struct GenVarsT
{
bool Enabled = false;
@@ -74,47 +91,13 @@ public:
std::string Executable;
CompilerFeaturesHandle ExecutableFeatures;
- /// @brief Constructor
GenVarsT(GenT gen)
: Gen(gen)
, GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
};
- /// @brief Writes a CMake info file
- class InfoWriter
- {
- public:
- /// @brief 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
+ /** @return The detected Qt version and the required Qt major version. */
static std::pair<IntegerVersion, unsigned int> GetQtVersion(
cmGeneratorTarget const* genTarget);
@@ -128,7 +111,7 @@ public:
bool SetupCustomTargets();
private:
- /// @brief If moc or uic is enabled, the autogen target will be generated
+ /** If moc or uic is enabled, the autogen target will be generated. */
bool MocOrUicEnabled() const
{
return (this->Moc.Enabled || this->Uic.Enabled);
@@ -152,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;
@@ -161,39 +150,39 @@ private:
cmGlobalGenerator* GlobalGen = nullptr;
cmLocalGenerator* LocalGen = nullptr;
cmMakefile* Makefile = nullptr;
+ cmFilePathChecksum const PathCheckSum;
- // Configuration
+ // -- Configuration
IntegerVersion QtVersion;
+ unsigned int Verbosity = 0;
bool MultiConfig = false;
+ bool CMP0071Accept = false;
+ bool CMP0071Warn = false;
std::string ConfigDefault;
std::vector<std::string> ConfigsList;
- std::string Verbosity;
std::string TargetsFolder;
- bool CMP0071Accept = false;
- bool CMP0071Warn = false;
- /// @brief Common directories
+ /** Common directories. */
struct
{
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;
- /// @brief Autogen target variables
+ /** Autogen target variables. */
struct
{
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;
@@ -204,45 +193,53 @@ private:
std::vector<MUFile*> FilesGenerated;
} AutogenTarget;
- /// @brief Moc only variables
+ /** moc variables. */
struct MocT : public GenVarsT
{
- 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;
-
- /// @brief Constructor
MocT()
: GenVarsT(GenT::MOC){};
+
+ 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;
- /// @brief Uic only variables
+ /** uic variables. */
struct UicT : public GenVarsT
{
- std::set<std::string> SkipUi;
- 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;
+ using UiFileT = std::pair<std::string, std::vector<std::string>>;
- /// @brief Constructor
UicT()
: GenVarsT(GenT::UIC){};
+
+ std::set<std::string> SkipUi;
+ std::vector<UiFileT> UiFiles;
+ ConfigStrings<std::vector<std::string>> Options;
+ std::vector<std::string> SearchPaths;
} Uic;
- /// @brief Rcc only variables
+ /** rcc variables. */
struct RccT : public GenVarsT
{
- bool GlobalTarget = false;
- std::vector<Qrc> Qrcs;
-
- /// @brief Constructor
RccT()
: GenVarsT(GenT::RCC){};
+
+ bool GlobalTarget = false;
+ std::vector<Qrc> Qrcs;
} Rcc;
};
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index eb829faea9..a9d4fee3c7 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -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,
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index f60acb0531..7f83fc6b84 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -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_;
};
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 5cd1ba17f8..5f3cd5fe98 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -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
- 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");
+ // -- 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;
+ }
- for (std::string const& item : InfoGetList("AM_MOC_MACRO_NAMES")) {
+ // -- 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
{
- 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'));
+ 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;
};
- if (key.empty()) {
- return filterErr("Key is empty");
+
+ 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;
}
- if (exp.empty()) {
- return filterErr("Regular expression is empty");
+
+ 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;
}
- this->MocConst_.DependFilters.emplace_back(key, exp);
- if (!this->MocConst_.DependFilters.back().Exp.is_valid()) {
- return filterErr("Regular expression compiling failed");
+
+ 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;
}
- 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]*\"([^\"]+)\"")) {
+ 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;
}
}
- // 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");
+ }
+ // 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."));
+ }
+ }
+
+ // -- Uic
+ if (!UicConst_.Executable.empty()) {
+ // Uic is enabled
+ UicConst_.Enabled = true;
+
+ // -- 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.");
}
- for (auto itC = flts.begin(), itE = flts.end(); itC != itE; itC += 2) {
- if (!addFilter(*itC, *(itC + 1))) {
+ 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);
}
}
- MocConst_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
- }
- // - Uic
- UicConst_.Executable = InfoGet("AM_QT_UIC_EXECUTABLE");
- if (!UicConst().Executable.empty()) {
- UicConst_.Enabled = true;
- // Load the executable file time
+ // -- 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())) {
+ 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;
+ };
+
+ 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;
}
- }
- // 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));
+ 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;
+ };
+
+ 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;
+ }
- // 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));
+ 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;
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 15b66ca248..7101b8fd3e 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -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,24 +65,13 @@ 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
{
public:
// -- Types
- /**
- * Entry of the file parsing cache
- */
+
+ /** Entry of the file parsing cache. */
struct FileT
{
void Clear();
@@ -170,6 +161,7 @@ public:
// - Config
bool MultiConfig = false;
unsigned int QtVersionMajor = 4;
+ unsigned int ThreadCount = 0;
// - Directories
std::string AutogenBuildDir;
std::string AutogenIncludeDir;
@@ -253,6 +245,12 @@ public:
class UicSettingsT
{
public:
+ struct UiFile
+ {
+ std::vector<std::string> Options;
+ };
+
+ public:
UicSettingsT();
~UicSettingsT();
@@ -268,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;
};
@@ -524,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
@@ -542,8 +538,6 @@ private:
bool CreateDirectories();
private:
- // -- Utility
- Logger Logger_;
// -- Settings
BaseSettingsT BaseConst_;
BaseEvalT BaseEval_;
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index 1bf8ca418d..b0b15d4065 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -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;
}
diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h
index 636a6672db..945b68fce1 100644
--- a/Source/cmQtAutoRcc.h
+++ b/Source/cmQtAutoRcc.h
@@ -12,9 +12,9 @@
#include <string>
#include <vector>
-class cmMakefile;
-
-// @brief AUTORCC generator
+/** \class cmQtAutoRcc
+ * \brief AUTORCC generator
+ */
class cmQtAutoRcc : public cmQtAutoGenerator
{
public:
@@ -26,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();
@@ -45,8 +44,6 @@ private:
bool GenerateWrapper();
private:
- // -- Logging
- Logger Logger_;
// -- Config settings
bool MultiConfig_ = false;
// -- Directories
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 211fd4c723..bf856d71d5 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -1058,18 +1058,18 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
#ifndef CMAKE_BOOTSTRAP
if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
cmQtAutoMocUic autoGen;
- std::string const& infoDir = args[2];
+ std::string const& infoFile = args[2];
std::string const& config = args[3];
- return autoGen.Run(infoDir, config) ? 0 : 1;
+ return autoGen.Run(infoFile, config) ? 0 : 1;
}
if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
- cmQtAutoRcc autoGen;
+ cmQtAutoRcc autoRcc;
std::string const& infoFile = args[2];
std::string config;
if (args.size() > 3) {
config = args[3];
}
- return autoGen.Run(infoFile, config) ? 0 : 1;
+ return autoRcc.Run(infoFile, config) ? 0 : 1;
}
#endif
diff --git a/Utilities/std/cm/algorithm b/Utilities/std/cm/algorithm
new file mode 100644
index 0000000000..8ade99cb72
--- /dev/null
+++ b/Utilities/std/cm/algorithm
@@ -0,0 +1,38 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_algorithm
+#define cm_algorithm
+
+#include <algorithm> // IWYU pragma: export
+#include <cassert>
+
+namespace cm {
+
+#if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
+
+using std::clamp;
+
+#else
+
+template <typename T>
+T const& clamp(T const& v, T const& lo, T const& hi)
+{
+ assert(!(hi < lo));
+ return (v < lo) ? lo : (hi < v) ? hi : v;
+}
+
+template <typename T, typename Comp>
+T const& clamp(T const& v, T const& lo, T const& hi, Comp comp)
+{
+ assert(!comp(hi, lo));
+ return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
+}
+
+#endif
+
+} // namespace cm
+
+#endif