in Source/cmQtAutoMocUic.cxx [2380:2812]
bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
{
// -- Required settings
if (!info.GetBool("MULTI_CONFIG", this->BaseConst_.MultiConfig, true) ||
!info.GetBool("CROSS_CONFIG", this->BaseConst_.CrossConfig, true) ||
!info.GetBool("USE_BETTER_GRAPH", this->BaseConst_.UseBetterGraph,
true) ||
!info.GetUInt("QT_VERSION_MAJOR", this->BaseConst_.QtVersion.Major,
true) ||
!info.GetUInt("QT_VERSION_MINOR", this->BaseConst_.QtVersion.Minor,
true) ||
!info.GetUInt("PARALLEL", this->BaseConst_.ThreadCount, false) ||
#ifdef _WIN32
!info.GetUInt("AUTOGEN_COMMAND_LINE_LENGTH_MAX",
this->BaseConst_.MaxCommandLineLength, false) ||
#endif
!info.GetString("BUILD_DIR", this->BaseConst_.AutogenBuildDir, true) ||
!info.GetStringConfig("INCLUDE_DIR", this->BaseConst_.AutogenIncludeDir,
true) ||
!info.GetString("CMAKE_EXECUTABLE", this->BaseConst_.CMakeExecutable,
true) ||
!info.GetStringConfig("PARSE_CACHE_FILE",
this->BaseConst_.ParseCacheFile, true) ||
!info.GetStringConfig("SETTINGS_FILE", this->SettingsFile_, true) ||
!info.GetArray("CMAKE_LIST_FILES", this->BaseConst_.ListFiles, true) ||
!info.GetArray("HEADER_EXTENSIONS", this->BaseConst_.HeaderExtensions,
true)) {
return false;
}
if (this->BaseConst().UseBetterGraph) {
if (!info.GetStringConfig("DEP_FILE", this->BaseConst_.DepFile, false) ||
!info.GetStringConfig("DEP_FILE_RULE_NAME",
this->BaseConst_.DepFileRuleName, false)) {
return false;
}
if (this->BaseConst_.CrossConfig) {
std::string const mocExecutableWithConfig =
"QT_MOC_EXECUTABLE_" + this->ExecutableConfig();
std::string const uicExecutableWithConfig =
"QT_UIC_EXECUTABLE_" + this->ExecutableConfig();
if (!info.GetString(mocExecutableWithConfig, this->MocConst_.Executable,
false) ||
!info.GetString(uicExecutableWithConfig, this->UicConst_.Executable,
false)) {
return false;
}
} else {
if (!info.GetStringConfig("QT_MOC_EXECUTABLE",
this->MocConst_.Executable, false) ||
!info.GetStringConfig("QT_UIC_EXECUTABLE",
this->UicConst_.Executable, false)) {
return false;
}
}
} else {
if (!info.GetString("QT_MOC_EXECUTABLE", this->MocConst_.Executable,
false) ||
!info.GetString("QT_UIC_EXECUTABLE", this->UicConst_.Executable,
false) ||
!info.GetString("DEP_FILE", this->BaseConst_.DepFile, false) ||
!info.GetString("DEP_FILE_RULE_NAME", this->BaseConst_.DepFileRuleName,
false)) {
return false;
}
}
// -- Checks
if (!this->BaseConst_.CMakeExecutableTime.Load(
this->BaseConst_.CMakeExecutable)) {
return info.LogError(
cmStrCat("The CMake executable ",
this->MessagePath(this->BaseConst_.CMakeExecutable),
" does not exist."));
}
// -- Evaluate values
this->BaseConst_.ThreadCount =
std::min(this->BaseConst_.ThreadCount, ParallelMax);
this->WorkerPool_.SetThreadCount(this->BaseConst_.ThreadCount);
// -- Moc
if (!this->MocConst_.Executable.empty()) {
// -- Moc is enabled
this->MocConst_.Enabled = true;
// -- Temporary buffers
struct
{
std::vector<std::string> MacroNames;
std::vector<std::string> DependFilters;
} tmp;
// -- Required settings
if (!info.GetBool("MOC_RELAXED_MODE", this->MocConst_.RelaxedMode,
false) ||
!info.GetBool("MOC_PATH_PREFIX", this->MocConst_.PathPrefix, true) ||
!info.GetArray("MOC_SKIP", this->MocConst_.SkipList, false) ||
!info.GetArrayConfig("MOC_DEFINITIONS", this->MocConst_.Definitions,
false) ||
!info.GetArrayConfig("MOC_INCLUDES", this->MocConst_.IncludePaths,
false) ||
!info.GetArray("MOC_OPTIONS", this->MocConst_.OptionsExtra, false) ||
!info.GetStringConfig("MOC_COMPILATION_FILE",
this->MocConst_.CompFileAbs, true) ||
!info.GetArray("MOC_PREDEFS_CMD", this->MocConst_.PredefsCmd, false) ||
!info.GetStringConfig("MOC_PREDEFS_FILE",
this->MocConst_.PredefsFileAbs,
!this->MocConst_.PredefsCmd.empty()) ||
!info.GetArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
!info.GetArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
return false;
}
// -- Evaluate settings
for (std::string const& item : tmp.MacroNames) {
this->MocConst_.MacroFilters.emplace_back(
item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
}
// Can moc output dependencies or do we need to setup dependency filters?
if (this->BaseConst_.QtVersion >= IntegerVersion(5, 15)) {
this->MocConst_.CanOutputDependencies = true;
} else {
Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS");
if (!val.isArray()) {
return info.LogError("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 = [&info, ii](bool test, cm::string_view msg) -> bool {
if (!test) {
info.LogError(
cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", msg));
}
return !test;
};
Json::Value const& pairVal = val[ii];
if (testEntry(pairVal.isArray(), "JSON value is not an array.") ||
testEntry(pairVal.size() == 2, "JSON array size invalid.")) {
return false;
}
Json::Value const& keyVal = pairVal[0u];
Json::Value const& expVal = pairVal[1u];
if (testEntry(keyVal.isString(),
"JSON value for keyword is not a string.") ||
testEntry(expVal.isString(),
"JSON value for regular expression is not a string.")) {
return false;
}
std::string const key = keyVal.asString();
std::string const exp = expVal.asString();
if (testEntry(!key.empty(), "Keyword is empty.") ||
testEntry(!exp.empty(), "Regular expression is empty.")) {
return false;
}
this->MocConst_.DependFilters.emplace_back(key, exp);
if (testEntry(
this->MocConst_.DependFilters.back().Exp.is_valid(),
cmStrCat("Regular expression compilation failed.\nKeyword: ",
Quoted(key), "\nExpression: ", Quoted(exp)))) {
return false;
}
}
}
// Check if moc executable exists (by reading the file time)
if (!this->MocConst_.ExecutableTime.Load(this->MocConst_.Executable)) {
return info.LogError(cmStrCat(
"The moc executable ", this->MessagePath(this->MocConst_.Executable),
" does not exist."));
}
}
// -- Uic
if (!this->UicConst_.Executable.empty()) {
// Uic is enabled
this->UicConst_.Enabled = true;
// -- Required settings
if (!info.GetArray("UIC_SKIP", this->UicConst_.SkipList, false) ||
!info.GetArray("UIC_SEARCH_PATHS", this->UicConst_.SearchPaths,
false) ||
!info.GetArrayConfig("UIC_OPTIONS", this->UicConst_.Options, false)) {
return false;
}
// .ui files
{
Json::Value const& val = info.GetValue("UIC_UI_FILES");
if (!val.isArray()) {
return info.LogError("UIC_UI_FILES JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
if (!test) {
info.LogError(cmStrCat("UIC_UI_FILES entry ", ii, ": ", msg));
}
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 = this->UicConst_.UiFiles[entryName.asString()];
InfoT::GetJsonArray(uiFile.Options, entryOptions);
}
}
// -- Evaluate settings
// Check if uic executable exists (by reading the file time)
if (!this->UicConst_.ExecutableTime.Load(this->UicConst_.Executable)) {
return info.LogError(cmStrCat(
"The uic executable ", this->MessagePath(this->UicConst_.Executable),
" does not exist."));
}
}
// -- Headers
{
Json::Value const& val = info.GetValue("HEADERS");
if (!val.isArray()) {
return info.LogError("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 = [&info, ii](bool test, cm::string_view msg) -> bool {
if (!test) {
info.LogError(cmStrCat("HEADERS entry ", ii, ": ", msg));
}
return !test;
};
Json::Value const& entry = val[ii];
if (testEntry(entry.isArray(), "JSON value is not an array.") ||
testEntry(entry.size() == 4, "JSON array size invalid.")) {
return false;
}
Json::Value const& entryName = entry[0u];
Json::Value const& entryFlags = entry[1u];
Json::Value const& entryBuild = entry[2u];
Json::Value const& entryConfigs = entry[3u];
if (testEntry(entryName.isString(),
"JSON value for name is not a string.") ||
testEntry(entryFlags.isString(),
"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(),
"JSON value for build path is not a string.")) {
return false;
}
std::string name = entryName.asString();
std::string flags = entryFlags.asString();
std::string build = entryBuild.asString();
if (testEntry(flags.size() == 2, "Invalid flags string size")) {
return false;
}
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;
if (!fileTime.Load(name)) {
return info.LogError(cmStrCat(
"The header file ", this->MessagePath(name), " does not exist."));
}
SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
sourceHandle->FileTime = fileTime;
sourceHandle->IsHeader = true;
sourceHandle->Moc = (flags[0] == 'M');
sourceHandle->Uic = (flags[1] == 'U');
if (sourceHandle->Moc && this->MocConst().Enabled) {
if (build.empty()) {
return info.LogError(
cmStrCat("Header file ", ii, " build path is empty"));
}
sourceHandle->BuildPath = std::move(build);
}
this->BaseEval().Headers.emplace(std::move(name),
std::move(sourceHandle));
}
}
// -- Sources
{
Json::Value const& val = info.GetValue("SOURCES");
if (!val.isArray()) {
return info.LogError("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 = [&info, ii](bool test, cm::string_view msg) -> bool {
if (!test) {
info.LogError(cmStrCat("SOURCES entry ", ii, ": ", msg));
}
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& entryConfigs = 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(entryConfigs.isNull() || entryConfigs.isArray(),
"JSON value for configs is not null or array.")) {
return false;
}
std::string name = entryName.asString();
std::string flags = entryFlags.asString();
if (testEntry(flags.size() == 2, "Invalid flags string size")) {
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;
if (!fileTime.Load(name)) {
return info.LogError(cmStrCat(
"The source file ", this->MessagePath(name), " does not exist."));
}
SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
sourceHandle->FileTime = fileTime;
sourceHandle->IsHeader = false;
sourceHandle->Moc = (flags[0] == 'M');
sourceHandle->Uic = (flags[1] == 'U');
this->BaseEval().Sources.emplace(std::move(name),
std::move(sourceHandle));
}
}
// -- Init derived information
// Moc variables
if (this->MocConst().Enabled) {
// Compose moc includes list
{
// Compute framework paths
std::set<std::string> frameworkPaths;
for (std::string const& path : this->MocConst().IncludePaths) {
// Extract framework path
if (cmHasLiteralSuffix(path, ".framework/Headers")) {
// Go up twice to get to the framework root
std::vector<std::string> pathComponents;
cmSystemTools::SplitPath(path, pathComponents);
frameworkPaths.emplace(cmSystemTools::JoinPath(
pathComponents.begin(), pathComponents.end() - 2));
}
}
// Reserve options
this->MocConst_.OptionsIncludes.reserve(
this->MocConst().IncludePaths.size() + frameworkPaths.size() * 2);
// Append includes
for (std::string const& path : this->MocConst().IncludePaths) {
this->MocConst_.OptionsIncludes.emplace_back("-I" + path);
}
// Append framework includes
for (std::string const& path : frameworkPaths) {
this->MocConst_.OptionsIncludes.emplace_back("-F");
this->MocConst_.OptionsIncludes.push_back(path);
}
}
// Compose moc definitions list
{
this->MocConst_.OptionsDefinitions.reserve(
this->MocConst().Definitions.size());
for (std::string const& def : this->MocConst().Definitions) {
this->MocConst_.OptionsDefinitions.emplace_back("-D" + def);
}
}
}
return true;
}