CMakePM: Add supprot for CMakePresets version 3

This includes Condition and toolchainFile

https://cmake.org/cmake/help/v3.21/manual/cmake-presets.7.html

Task-number: QTCREATORBUG-24555
Change-Id: I1026390af67b2be1aa0c3b02b654fc19442d3c89
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Cristian Adam
2022-09-26 18:59:04 +02:00
parent 45a275e054
commit ee4c998ff3
7 changed files with 430 additions and 27 deletions

View File

@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "presetsparser.h"
#include "utils/algorithm.h"
#include "cmakeprojectmanagertr.h"
@@ -34,6 +35,102 @@ bool parseCMakeMinimumRequired(const QJsonValue &jsonValue, QVersionNumber &vers
return true;
}
std::optional<PresetsDetails::Condition> parseCondition(const QJsonValue &jsonValue)
{
std::optional<PresetsDetails::Condition> condition;
if (jsonValue.isUndefined())
return condition;
condition = PresetsDetails::Condition();
if (jsonValue.isNull()) {
condition->type = "null";
return condition;
}
if (jsonValue.isBool()) {
condition->type = "const";
condition->constValue = jsonValue.toBool();
return condition;
}
if (!jsonValue.isObject())
return condition;
QJsonObject object = jsonValue.toObject();
QString type = object.value("type").toString();
if (type.isEmpty())
return condition;
if (type == "const") {
condition->type = type;
condition->constValue = object.value("const").toBool();
return condition;
}
for (const auto &equals : {QString("equals"), QString("notEquals")}) {
if (type == equals) {
condition->type = equals;
condition->lhs = object.value("lhs").toString();
condition->rhs = object.value("rhs").toString();
}
}
if (!condition->type.isEmpty())
return condition;
for (const auto &inList : {QString("inList"), QString("notInList")}) {
if (type == inList) {
condition->type = inList;
condition->string = object.value("string").toString();
if (object.value("list").isArray()) {
condition->list = QStringList();
const QJsonArray listArray = object.value("list").toArray();
for (const QJsonValue &listValue : listArray)
condition->list.value() << listValue.toString();
}
}
}
if (!condition->type.isEmpty())
return condition;
for (const auto &matches : {QString("matches"), QString("notMatches")}) {
if (type == matches) {
condition->type = matches;
condition->string = object.value("string").toString();
condition->regex = object.value("regex").toString();
}
}
if (!condition->type.isEmpty())
return condition;
for (const auto &anyOf : {QString("anyOf"), QString("allOf")}) {
if (type == anyOf) {
condition->type = anyOf;
if (object.value("conditions").isArray()) {
condition->conditions = std::vector<PresetsDetails::Condition::ConditionPtr>();
const QJsonArray conditionsArray = object.value("conditions").toArray();
for (const QJsonValue &conditionsValue : conditionsArray) {
condition->conditions.value().emplace_back(
std::make_shared<PresetsDetails::Condition>(
parseCondition(conditionsValue).value()));
}
}
}
}
if (!condition->type.isEmpty())
return condition;
if (type == "not") {
condition->type = type;
condition->condition = std::make_shared<PresetsDetails::Condition>(
parseCondition(object.value("condition")).value());
return condition;
}
return condition;
}
bool parseConfigurePresets(const QJsonValue &jsonValue,
QList<PresetsDetails::ConfigurePreset> &configurePresets)
{
@@ -68,6 +165,10 @@ bool parseConfigurePresets(const QJsonValue &jsonValue,
preset.inherits.value() << inheritsValue;
}
}
if (object.contains("condition"))
preset.condition = parseCondition(object.value("condition"));
if (object.contains("displayName"))
preset.displayName = object.value("displayName").toString();
if (object.contains("description"))
@@ -76,6 +177,8 @@ bool parseConfigurePresets(const QJsonValue &jsonValue,
preset.generator = object.value("generator").toString();
if (object.contains("binaryDir"))
preset.binaryDir = object.value("binaryDir").toString();
if (object.contains("toolchainFile"))
preset.toolchainFile = object.value("toolchainFile").toString();
if (object.contains("cmakeExecutable"))
preset.cmakeExecutable = object.value("cmakeExecutable").toString();
@@ -218,6 +321,10 @@ bool parseBuildPresets(const QJsonValue &jsonValue,
preset.inherits.value() << inheritsValue;
}
}
if (object.contains("condition"))
preset.condition = parseCondition(object.value("condition"));
if (object.contains("displayName"))
preset.displayName = object.value("displayName").toString();
if (object.contains("description"))
@@ -334,6 +441,9 @@ bool PresetsParser::parse(const Utils::FilePath &jsonFile, QString &errorMessage
void PresetsDetails::ConfigurePreset::inheritFrom(const ConfigurePreset &other)
{
if (!condition && other.condition && !other.condition.value().isNull())
condition = other.condition;
if (!vendor && other.vendor)
vendor = other.vendor;
@@ -346,6 +456,9 @@ void PresetsDetails::ConfigurePreset::inheritFrom(const ConfigurePreset &other)
if (!toolset && other.toolset)
toolset = other.toolset;
if (!toolchainFile && other.toolchainFile)
toolchainFile = other.toolchainFile;
if (!binaryDir && other.binaryDir)
binaryDir = other.binaryDir;
@@ -370,6 +483,9 @@ void PresetsDetails::ConfigurePreset::inheritFrom(const ConfigurePreset &other)
void PresetsDetails::BuildPreset::inheritFrom(const BuildPreset &other)
{
if (!condition && other.condition && !other.condition.value().isNull())
condition = other.condition;
if (!vendor && other.vendor)
vendor = other.vendor;
@@ -401,4 +517,46 @@ void PresetsDetails::BuildPreset::inheritFrom(const BuildPreset &other)
nativeToolOptions = other.nativeToolOptions;
}
bool PresetsDetails::Condition::evaluate() const
{
if (isNull())
return true;
if (isConst() && constValue)
return constValue.value();
if (isEquals() && lhs && rhs)
return lhs.value() == rhs.value();
if (isNotEquals() && lhs && rhs)
return lhs.value() != rhs.value();
if (isInList() && string && list)
return list.value().contains(string.value());
if (isNotInList() && string && list)
return !list.value().contains(string.value());
if (isMatches() && string && regex) {
QRegularExpression qRegex(regex.value());
return qRegex.match(string.value()).hasMatch();
}
if (isNotMatches() && string && regex) {
QRegularExpression qRegex(regex.value());
return !qRegex.match(string.value()).hasMatch();
}
if (isAnyOf() && conditions)
return Utils::anyOf(conditions.value(), [](const ConditionPtr &c) { return c->evaluate(); });
if (isAllOf() && conditions)
return Utils::allOf(conditions.value(), [](const ConditionPtr &c) { return c->evaluate(); });
if (isNot() && condition)
return !condition.value()->evaluate();
return false;
}
} // CMakeProjectManager::Internal