Commit 92d7b456 authored by Brad King's avatar Brad King
Browse files

Autogen: Add support for per-config sources

Fixes: #20682
parent 3ffebbae
...@@ -48,6 +48,8 @@ and ``rcc`` for virtual file system content generation. These tools may be ...@@ -48,6 +48,8 @@ and ``rcc`` for virtual file system content generation. These tools may be
automatically invoked by :manual:`cmake(1)` if the appropriate conditions automatically invoked by :manual:`cmake(1)` if the appropriate conditions
are met. The automatic tool invocation may be used with both Qt 4 and Qt 5. are met. The automatic tool invocation may be used with both Qt 4 and Qt 5.
.. _`Qt AUTOMOC`:
AUTOMOC AUTOMOC
^^^^^^^ ^^^^^^^
...@@ -77,8 +79,9 @@ automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. ...@@ -77,8 +79,9 @@ automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
Not included ``moc_<basename>.cpp`` files will be generated in custom Not included ``moc_<basename>.cpp`` files will be generated in custom
folders to avoid name collisions and included in a separate folders to avoid name collisions and included in a separate
``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp`` file which is compiled file which is compiled into the target, named either
into the target. ``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp`` or
``<AUTOGEN_BUILD_DIR>/mocs_compilation_$<CONFIG>.cpp``.
* See :prop_tgt:`AUTOGEN_BUILD_DIR`. * See :prop_tgt:`AUTOGEN_BUILD_DIR`.
......
...@@ -137,7 +137,8 @@ parent directory path of the ``moc`` input file. This scheme allows to have ...@@ -137,7 +137,8 @@ parent directory path of the ``moc`` input file. This scheme allows to have
All not included ``moc`` output files will be included automatically by the All not included ``moc`` output files will be included automatically by the
CMake generated file CMake generated file
- ``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp``, - ``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp``, or
- ``<AUTOGEN_BUILD_DIR>/mocs_compilation_$<CONFIG>.cpp``,
which is added to the target's sources. which is added to the target's sources.
......
qt-autogen-per-config
---------------------
* The :ref:`Qt AUTOMOC` feature now works with per-config sources.
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <cm/iterator> #include <cm/iterator>
#include <cm/memory> #include <cm/memory>
#include <cmext/algorithm> #include <cmext/algorithm>
#include <cmext/string_view>
#include <cm3p/json/value.h> #include <cm3p/json/value.h>
#include <cm3p/json/writer.h> #include <cm3p/json/writer.h>
...@@ -564,8 +565,22 @@ bool cmQtAutoGenInitializer::InitCustomTargets() ...@@ -564,8 +565,22 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
bool cmQtAutoGenInitializer::InitMoc() bool cmQtAutoGenInitializer::InitMoc()
{ {
// Mocs compilation file // Mocs compilation file
this->Moc.CompilationFile = if (this->GlobalGen->IsXcode()) {
cmStrCat(this->Dir.Build, "/mocs_compilation.cpp"); // XXX(xcode-per-cfg-src): Drop this Xcode-specific code path
// when the Xcode generator supports per-config sources.
this->Moc.CompilationFile.Default =
cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default;
} else {
ConfigFileNames(this->Moc.CompilationFile,
cmStrCat(this->Dir.Build, "/mocs_compilation"), ".cpp");
if (this->MultiConfig) {
this->Moc.CompilationFileGenex =
cmStrCat(this->Dir.Build, "/mocs_compilation_$<CONFIG>.cpp"_s);
} else {
this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default;
}
}
// Moc predefs // Moc predefs
if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
...@@ -731,10 +746,14 @@ bool cmQtAutoGenInitializer::InitScanFiles() ...@@ -731,10 +746,14 @@ bool cmQtAutoGenInitializer::InitScanFiles()
auto const& kw = this->GlobalInitializer->kw(); auto const& kw = this->GlobalInitializer->kw();
auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath, auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath,
std::vector<size_t> const& configs,
bool muIt) -> MUFileHandle { bool muIt) -> MUFileHandle {
MUFileHandle muf = cm::make_unique<MUFile>(); MUFileHandle muf = cm::make_unique<MUFile>();
muf->FullPath = fullPath; muf->FullPath = fullPath;
muf->SF = sf; muf->SF = sf;
if (!configs.empty() && configs.size() != this->ConfigsList.size()) {
muf->Configs = configs;
}
muf->Generated = sf->GetIsGenerated(); muf->Generated = sf->GetIsGenerated();
bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN); bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
muf->SkipMoc = this->Moc.Enabled && muf->SkipMoc = this->Moc.Enabled &&
...@@ -773,42 +792,37 @@ bool cmQtAutoGenInitializer::InitScanFiles() ...@@ -773,42 +792,37 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Scan through target files // Scan through target files
{ {
// Scan through target files // Scan through target files
std::vector<cmSourceFile*> srcFiles; for (cmGeneratorTarget::AllConfigSource const& acs :
this->GenTarget->GetConfigCommonSourceFiles(srcFiles); this->GenTarget->GetAllConfigSources()) {
for (cmSourceFile* sf : srcFiles) { std::string const& fullPath = acs.Source->GetFullPath();
// sf->GetExtension() is only valid after sf->ResolveFullPath() ...
// Since we're iterating over source files that might be not in the
// target we need to check for path errors (not existing files).
std::string pathError;
std::string const& fullPath = sf->ResolveFullPath(&pathError);
if (!pathError.empty() || fullPath.empty()) {
continue;
}
std::string const& extLower = std::string const& extLower =
cmSystemTools::LowerCase(sf->GetExtension()); cmSystemTools::LowerCase(acs.Source->GetExtension());
// Register files that will be scanned by moc or uic // Register files that will be scanned by moc or uic
if (this->MocOrUicEnabled()) { if (this->MocOrUicEnabled()) {
if (cm->IsAHeaderExtension(extLower)) { if (cm->IsAHeaderExtension(extLower)) {
addMUHeader(makeMUFile(sf, fullPath, true), extLower); addMUHeader(makeMUFile(acs.Source, fullPath, acs.Configs, true),
extLower);
} else if (cm->IsACLikeSourceExtension(extLower)) { } else if (cm->IsACLikeSourceExtension(extLower)) {
addMUSource(makeMUFile(sf, fullPath, true)); addMUSource(makeMUFile(acs.Source, fullPath, acs.Configs, true));
} }
} }
// Register rcc enabled files // Register rcc enabled files
if (this->Rcc.Enabled) { if (this->Rcc.Enabled) {
if ((extLower == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) && if ((extLower == kw.qrc) &&
!sf->GetPropertyAsBool(kw.SKIP_AUTORCC)) { !acs.Source->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
!acs.Source->GetPropertyAsBool(kw.SKIP_AUTORCC)) {
// Register qrc file // Register qrc file
Qrc qrc; Qrc qrc;
qrc.QrcFile = fullPath; qrc.QrcFile = fullPath;
qrc.QrcName = qrc.QrcName =
cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile); cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
qrc.Generated = sf->GetIsGenerated(); qrc.Generated = acs.Source->GetIsGenerated();
// RCC options // RCC options
{ {
std::string const& opts = sf->GetSafeProperty(kw.AUTORCC_OPTIONS); std::string const& opts =
acs.Source->GetSafeProperty(kw.AUTORCC_OPTIONS);
if (!opts.empty()) { if (!opts.empty()) {
cmExpandList(opts, qrc.Options); cmExpandList(opts, qrc.Options);
} }
...@@ -818,7 +832,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() ...@@ -818,7 +832,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
} }
} }
} }
// cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's // cmGeneratorTarget::GetAllConfigSources computes the target's
// sources meta data cache. Clear it so that OBJECT library targets that // sources meta data cache. Clear it so that OBJECT library targets that
// are AUTOGEN initialized after this target get their added // are AUTOGEN initialized after this target get their added
// mocs_compilation.cpp source acknowledged by this target. // mocs_compilation.cpp source acknowledged by this target.
...@@ -862,7 +876,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() ...@@ -862,7 +876,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
} }
if (sf != nullptr) { if (sf != nullptr) {
auto eMuf = makeMUFile(sf, fullPath, true); auto eMuf = makeMUFile(sf, fullPath, muf.Configs, true);
// Only process moc/uic when the parent is processed as well // Only process moc/uic when the parent is processed as well
if (!muf.MocIt) { if (!muf.MocIt) {
eMuf->MocIt = false; eMuf->MocIt = false;
...@@ -897,14 +911,14 @@ bool cmQtAutoGenInitializer::InitScanFiles() ...@@ -897,14 +911,14 @@ bool cmQtAutoGenInitializer::InitScanFiles()
if (cm->IsAHeaderExtension(extLower)) { if (cm->IsAHeaderExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Headers, sf.get())) { if (!cm::contains(this->AutogenTarget.Headers, sf.get())) {
auto muf = makeMUFile(sf.get(), fullPath, false); auto muf = makeMUFile(sf.get(), fullPath, {}, false);
if (muf->SkipMoc || muf->SkipUic) { if (muf->SkipMoc || muf->SkipUic) {
addMUHeader(std::move(muf), extLower); addMUHeader(std::move(muf), extLower);
} }
} }
} else if (cm->IsACLikeSourceExtension(extLower)) { } else if (cm->IsACLikeSourceExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Sources, sf.get())) { if (!cm::contains(this->AutogenTarget.Sources, sf.get())) {
auto muf = makeMUFile(sf.get(), fullPath, false); auto muf = makeMUFile(sf.get(), fullPath, {}, false);
if (muf->SkipMoc || muf->SkipUic) { if (muf->SkipMoc || muf->SkipUic) {
addMUSource(std::move(muf)); addMUSource(std::move(muf));
} }
...@@ -1067,10 +1081,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() ...@@ -1067,10 +1081,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile); this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile);
// Files provided by the autogen target // Files provided by the autogen target
std::vector<std::string> autogenProvides; std::vector<std::string> autogenByproducts;
if (this->Moc.Enabled) { if (this->Moc.Enabled) {
this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true); this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true);
autogenProvides.push_back(this->Moc.CompilationFile); autogenByproducts.push_back(this->Moc.CompilationFileGenex);
} }
// Compose target comment // Compose target comment
...@@ -1091,8 +1105,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() ...@@ -1091,8 +1105,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
} }
// Compose command lines // Compose command lines
// TODO: Refactor autogen to output a per-config mocs_compilation.cpp instead // FIXME: Take advantage of our per-config mocs_compilation_$<CONFIG>.cpp
// of fiddling with the include directories // instead of fiddling with the include directories
std::vector<std::string> configs; std::vector<std::string> configs;
this->GlobalGen->GetQtAutoGenConfigs(configs); this->GlobalGen->GetQtAutoGenConfigs(configs);
bool stdPipesUTF8 = true; bool stdPipesUTF8 = true;
...@@ -1138,7 +1152,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() ...@@ -1138,7 +1152,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// PRE_BUILD does not support file dependencies! // PRE_BUILD does not support file dependencies!
const std::vector<std::string> no_output; const std::vector<std::string> no_output;
const std::vector<std::string> no_deps; const std::vector<std::string> no_deps;
cmCustomCommand cc(no_output, autogenProvides, no_deps, commandLines, cmCustomCommand cc(no_output, autogenByproducts, no_deps, commandLines,
this->Makefile->GetBacktrace(), autogenComment.c_str(), this->Makefile->GetBacktrace(), autogenComment.c_str(),
this->Dir.Work.c_str(), stdPipesUTF8); this->Dir.Work.c_str(), stdPipesUTF8);
cc.SetEscapeOldStyle(false); cc.SetEscapeOldStyle(false);
...@@ -1283,7 +1297,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() ...@@ -1283,7 +1297,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// Create autogen target // Create autogen target
cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand( cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand(
this->AutogenTarget.Name, true, this->Dir.Work.c_str(), this->AutogenTarget.Name, true, this->Dir.Work.c_str(),
/*byproducts=*/autogenProvides, /*byproducts=*/autogenByproducts,
/*depends=*/dependencies, commandLines, false, autogenComment.c_str()); /*depends=*/dependencies, commandLines, false, autogenComment.c_str());
// Create autogen generator target // Create autogen generator target
this->LocalGen->AddGeneratorTarget( this->LocalGen->AddGeneratorTarget(
...@@ -1533,18 +1547,31 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() ...@@ -1533,18 +1547,31 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
info.SetArray("CMAKE_LIST_FILES", this->Makefile->GetListFiles()); info.SetArray("CMAKE_LIST_FILES", this->Makefile->GetListFiles());
info.SetArray("HEADER_EXTENSIONS", info.SetArray("HEADER_EXTENSIONS",
this->Makefile->GetCMakeInstance()->GetHeaderExtensions()); this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
auto cfgArray = [this](std::vector<size_t> const& configs) -> Json::Value {
Json::Value value;
if (!configs.empty()) {
value = Json::arrayValue;
for (size_t ci : configs) {
value.append(this->ConfigsList[ci]);
}
}
return value;
};
info.SetArrayArray("HEADERS", headers,
[this, &cfgArray](Json::Value& jval, MUFile const* muf) {
jval.resize(4u);
jval[0u] = muf->FullPath;
jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm',
muf->UicIt ? 'U' : 'u');
jval[2u] = cfgArray(muf->Configs);
jval[3u] = this->GetMocBuildPath(*muf);
});
info.SetArrayArray( info.SetArrayArray(
"HEADERS", headers, [this](Json::Value& jval, MUFile const* muf) { "SOURCES", sources, [&cfgArray](Json::Value& jval, MUFile const* muf) {
jval.resize(3u); jval.resize(3u);
jval[0u] = muf->FullPath; jval[0u] = muf->FullPath;
jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u'); jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
jval[2u] = this->GetMocBuildPath(*muf); jval[2u] = cfgArray(muf->Configs);
});
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 // Write moc settings
...@@ -1563,7 +1590,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() ...@@ -1563,7 +1590,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
jval[0u] = pair.first; jval[0u] = pair.first;
jval[1u] = pair.second; jval[1u] = pair.second;
}); });
info.Set("MOC_COMPILATION_FILE", this->Moc.CompilationFile); info.SetConfig("MOC_COMPILATION_FILE", this->Moc.CompilationFile);
info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd); info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile); info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile);
} }
...@@ -1656,6 +1683,28 @@ cmSourceFile* cmQtAutoGenInitializer::AddGeneratedSource( ...@@ -1656,6 +1683,28 @@ cmSourceFile* cmQtAutoGenInitializer::AddGeneratedSource(
return gFile; return gFile;
} }
void cmQtAutoGenInitializer::AddGeneratedSource(ConfigString const& filename,
GenVarsT const& genVars,
bool prepend)
{
// XXX(xcode-per-cfg-src): Drop the Xcode-specific part of the condition
// when the Xcode generator supports per-config sources.
if (!this->MultiConfig || this->GlobalGen->IsXcode()) {
this->AddGeneratedSource(filename.Default, genVars, prepend);
return;
}
for (auto const& cfg : this->ConfigsList) {
std::string const& filenameCfg = filename.Config.at(cfg);
// Register source at makefile
this->RegisterGeneratedSource(filenameCfg);
// Add source file to target for this configuration.
this->GenTarget->AddSource(
cmStrCat("$<$<CONFIG:"_s, cfg, ">:"_s, filenameCfg, ">"_s), prepend);
// Add source file to source group
this->AddToSourceGroup(filenameCfg, genVars.GenNameUpper);
}
}
void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
cm::string_view genNameUpper) cm::string_view genNameUpper)
{ {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep #include "cmConfigure.h" // IWYU pragma: keep
#include <cstddef>
#include <memory> #include <memory>
#include <set> #include <set>
#include <string> #include <string>
...@@ -70,6 +71,7 @@ public: ...@@ -70,6 +71,7 @@ public:
{ {
std::string FullPath; std::string FullPath;
cmSourceFile* SF = nullptr; cmSourceFile* SF = nullptr;
std::vector<size_t> Configs;
bool Generated = false; bool Generated = false;
bool SkipMoc = false; bool SkipMoc = false;
bool SkipUic = false; bool SkipUic = false;
...@@ -132,6 +134,8 @@ private: ...@@ -132,6 +134,8 @@ private:
cmSourceFile* AddGeneratedSource(std::string const& filename, cmSourceFile* AddGeneratedSource(std::string const& filename,
GenVarsT const& genVars, GenVarsT const& genVars,
bool prepend = false); bool prepend = false);
void AddGeneratedSource(ConfigString const& filename,
GenVarsT const& genVars, bool prepend = false);
void AddToSourceGroup(std::string const& fileName, void AddToSourceGroup(std::string const& fileName,
cm::string_view genNameUpper); cm::string_view genNameUpper);
void AddCleanFile(std::string const& fileName); void AddCleanFile(std::string const& fileName);
...@@ -207,7 +211,8 @@ private: ...@@ -207,7 +211,8 @@ private:
bool RelaxedMode = false; bool RelaxedMode = false;
bool PathPrefix = false; bool PathPrefix = false;
std::string CompilationFile; ConfigString CompilationFile;
std::string CompilationFileGenex;
// Compiler implicit pre defines // Compiler implicit pre defines
std::vector<std::string> PredefsCmd; std::vector<std::string> PredefsCmd;
ConfigString PredefsFile; ConfigString PredefsFile;
......
...@@ -2452,17 +2452,20 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) ...@@ -2452,17 +2452,20 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
Json::Value const& entry = val[ii]; Json::Value const& entry = val[ii];
if (testEntry(entry.isArray(), "JSON value is not an array.") || if (testEntry(entry.isArray(), "JSON value is not an array.") ||
testEntry(entry.size() == 3, "JSON array size invalid.")) { testEntry(entry.size() == 4, "JSON array size invalid.")) {
return false; return false;
} }
Json::Value const& entryName = entry[0u]; Json::Value const& entryName = entry[0u];
Json::Value const& entryFlags = entry[1u]; Json::Value const& entryFlags = entry[1u];
Json::Value const& entryBuild = entry[2u]; Json::Value const& entryConfigs = entry[2u];
Json::Value const& entryBuild = entry[3u];
if (testEntry(entryName.isString(), if (testEntry(entryName.isString(),
"JSON value for name is not a string.") || "JSON value for name is not a string.") ||
testEntry(entryFlags.isString(), testEntry(entryFlags.isString(),
"JSON value for flags is not a string.") || "JSON value for flags is not a string.") ||
testEntry(entryConfigs.isNull() || entryConfigs.isArray(),
"JSON value for configs is not null or array.") ||
testEntry(entryBuild.isString(), testEntry(entryBuild.isString(),
"JSON value for build path is not a string.")) { "JSON value for build path is not a string.")) {
return false; return false;
...@@ -2475,6 +2478,22 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) ...@@ -2475,6 +2478,22 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
return false; return false;
} }
if (entryConfigs.isArray()) {
bool configFound = false;
Json::ArrayIndex const configArraySize = entryConfigs.size();
for (Json::ArrayIndex ci = 0; ci != configArraySize; ++ci) {
Json::Value const& config = entryConfigs[ci];
if (testEntry(config.isString(),
"JSON value in config array is not a string.")) {
return false;
}
configFound = configFound || config.asString() == this->InfoConfig();
}
if (!configFound) {
continue;
}
}
cmFileTime fileTime; cmFileTime fileTime;
if (!fileTime.Load(name)) { if (!fileTime.Load(name)) {
return info.LogError(cmStrCat( return info.LogError(cmStrCat(
...@@ -2515,16 +2534,19 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) ...@@ -2515,16 +2534,19 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
Json::Value const& entry = val[ii]; Json::Value const& entry = val[ii];
if (testEntry(entry.isArray(), "JSON value is not an array.") || if (testEntry(entry.isArray(), "JSON value is not an array.") ||
testEntry(entry.size() == 2, "JSON array size invalid.")) { testEntry(entry.size() == 3, "JSON array size invalid.")) {
return false; return false;
} }
Json::Value const& entryName = entry[0u]; Json::Value const& entryName = entry[0u];
Json::Value const& entryFlags = entry[1u]; Json::Value const& entryFlags = entry[1u];
Json::Value const& entryConfigs = entry[2u];
if (testEntry(entryName.isString(), if (testEntry(entryName.isString(),
"JSON value for name is not a string.") || "JSON value for name is not a string.") ||
testEntry(entryFlags.isString(), testEntry(entryFlags.isString(),
"JSON value for flags is not a string.")) { "JSON value for flags is not a string.") ||
testEntry(entryConfigs.isNull() || entryConfigs.isArray(),
"JSON value for configs is not null or array.")) {
return false; return false;
} }
...@@ -2534,6 +2556,22 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) ...@@ -2534,6 +2556,22 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
return false; return false;
} }
if (entryConfigs.isArray()) {
bool configFound = false;
Json::ArrayIndex const configArraySize = entryConfigs.size();
for (Json::ArrayIndex ci = 0; ci != configArraySize; ++ci) {
Json::Value const& config = entryConfigs[ci];
if (testEntry(config.isString(),
"JSON value in config array is not a string.")) {
return false;
}
configFound = configFound || config.asString() == this->InfoConfig();
}
if (!configFound) {
continue;
}
}
cmFileTime fileTime; cmFileTime fileTime;
if (!fileTime.Load(name)) { if (!fileTime.Load(name)) {
return info.LogError(cmStrCat( return info.LogError(cmStrCat(
......
...@@ -2,6 +2,15 @@ cmake_minimum_required(VERSION 3.11) ...@@ -2,6 +2,15 @@ cmake_minimum_required(VERSION 3.11)
project(AutogenOriginDependsOff) project(AutogenOriginDependsOff)
include("../AutogenCoreTest.cmake") include("../AutogenCoreTest.cmake")
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
# XXX(xcode-per-cfg-src): Enable multi-config code path for Xcode
# when the Xcode generator supports per-config sources.
if(_isMultiConfig AND NOT CMAKE_GENERATOR STREQUAL "Xcode")
set(mocs_compilation_cpp "mocs_compilation_$<CONFIG>.cpp")
else()
set(mocs_compilation_cpp "mocs_compilation.cpp")
endif()
set(CSD ${CMAKE_CURRENT_SOURCE_DIR}) set(CSD ${CMAKE_CURRENT_SOURCE_DIR})
set(CBD ${CMAKE_CURRENT_BINARY_DIR}) set(CBD ${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CSD}) include_directories(${CSD})
...@@ -19,7 +28,7 @@ add_custom_command ( ...@@ -19,7 +28,7 @@ add_custom_command (
add_custom_target ( a_mc